session_claims.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package sts
  2. import (
  3. "time"
  4. "github.com/golang-jwt/jwt/v5"
  5. )
  6. // STSSessionClaims represents comprehensive session information embedded in JWT tokens
  7. // This eliminates the need for separate session storage by embedding all session
  8. // metadata directly in the token itself - enabling true stateless operation
  9. type STSSessionClaims struct {
  10. jwt.RegisteredClaims
  11. // Session identification
  12. SessionId string `json:"sid"` // session_id (abbreviated for smaller tokens)
  13. SessionName string `json:"snam"` // session_name (abbreviated for smaller tokens)
  14. TokenType string `json:"typ"` // token_type
  15. // Role information
  16. RoleArn string `json:"role"` // role_arn
  17. AssumedRole string `json:"assumed"` // assumed_role_user
  18. Principal string `json:"principal"` // principal_arn
  19. // Authorization data
  20. Policies []string `json:"pol,omitempty"` // policies (abbreviated)
  21. // Identity provider information
  22. IdentityProvider string `json:"idp"` // identity_provider
  23. ExternalUserId string `json:"ext_uid"` // external_user_id
  24. ProviderIssuer string `json:"prov_iss"` // provider_issuer
  25. // Request context (optional, for policy evaluation)
  26. RequestContext map[string]interface{} `json:"req_ctx,omitempty"`
  27. // Session metadata
  28. AssumedAt time.Time `json:"assumed_at"` // when role was assumed
  29. MaxDuration int64 `json:"max_dur,omitempty"` // maximum session duration in seconds
  30. }
  31. // NewSTSSessionClaims creates new STS session claims with all required information
  32. func NewSTSSessionClaims(sessionId, issuer string, expiresAt time.Time) *STSSessionClaims {
  33. now := time.Now()
  34. return &STSSessionClaims{
  35. RegisteredClaims: jwt.RegisteredClaims{
  36. Issuer: issuer,
  37. Subject: sessionId,
  38. IssuedAt: jwt.NewNumericDate(now),
  39. ExpiresAt: jwt.NewNumericDate(expiresAt),
  40. NotBefore: jwt.NewNumericDate(now),
  41. },
  42. SessionId: sessionId,
  43. TokenType: TokenTypeSession,
  44. AssumedAt: now,
  45. }
  46. }
  47. // ToSessionInfo converts JWT claims back to SessionInfo structure
  48. // This enables seamless integration with existing code expecting SessionInfo
  49. func (c *STSSessionClaims) ToSessionInfo() *SessionInfo {
  50. var expiresAt time.Time
  51. if c.ExpiresAt != nil {
  52. expiresAt = c.ExpiresAt.Time
  53. }
  54. return &SessionInfo{
  55. SessionId: c.SessionId,
  56. SessionName: c.SessionName,
  57. RoleArn: c.RoleArn,
  58. AssumedRoleUser: c.AssumedRole,
  59. Principal: c.Principal,
  60. Policies: c.Policies,
  61. ExpiresAt: expiresAt,
  62. IdentityProvider: c.IdentityProvider,
  63. ExternalUserId: c.ExternalUserId,
  64. ProviderIssuer: c.ProviderIssuer,
  65. RequestContext: c.RequestContext,
  66. }
  67. }
  68. // IsValid checks if the session claims are valid (not expired, etc.)
  69. func (c *STSSessionClaims) IsValid() bool {
  70. now := time.Now()
  71. // Check expiration
  72. if c.ExpiresAt != nil && c.ExpiresAt.Before(now) {
  73. return false
  74. }
  75. // Check not-before
  76. if c.NotBefore != nil && c.NotBefore.After(now) {
  77. return false
  78. }
  79. // Ensure required fields are present
  80. if c.SessionId == "" || c.RoleArn == "" || c.Principal == "" {
  81. return false
  82. }
  83. return true
  84. }
  85. // GetSessionId returns the session identifier
  86. func (c *STSSessionClaims) GetSessionId() string {
  87. return c.SessionId
  88. }
  89. // GetExpiresAt returns the expiration time
  90. func (c *STSSessionClaims) GetExpiresAt() time.Time {
  91. if c.ExpiresAt != nil {
  92. return c.ExpiresAt.Time
  93. }
  94. return time.Time{}
  95. }
  96. // WithRoleInfo sets role-related information in the claims
  97. func (c *STSSessionClaims) WithRoleInfo(roleArn, assumedRole, principal string) *STSSessionClaims {
  98. c.RoleArn = roleArn
  99. c.AssumedRole = assumedRole
  100. c.Principal = principal
  101. return c
  102. }
  103. // WithPolicies sets the policies associated with this session
  104. func (c *STSSessionClaims) WithPolicies(policies []string) *STSSessionClaims {
  105. c.Policies = policies
  106. return c
  107. }
  108. // WithIdentityProvider sets identity provider information
  109. func (c *STSSessionClaims) WithIdentityProvider(providerName, externalUserId, providerIssuer string) *STSSessionClaims {
  110. c.IdentityProvider = providerName
  111. c.ExternalUserId = externalUserId
  112. c.ProviderIssuer = providerIssuer
  113. return c
  114. }
  115. // WithRequestContext sets request context for policy evaluation
  116. func (c *STSSessionClaims) WithRequestContext(ctx map[string]interface{}) *STSSessionClaims {
  117. c.RequestContext = ctx
  118. return c
  119. }
  120. // WithMaxDuration sets the maximum session duration
  121. func (c *STSSessionClaims) WithMaxDuration(duration time.Duration) *STSSessionClaims {
  122. c.MaxDuration = int64(duration.Seconds())
  123. return c
  124. }
  125. // WithSessionName sets the session name
  126. func (c *STSSessionClaims) WithSessionName(sessionName string) *STSSessionClaims {
  127. c.SessionName = sessionName
  128. return c
  129. }