docs
This commit is contained in:
@@ -14,7 +14,13 @@ import (
|
||||
"github.com/lestrrat-go/jwx/v2/jwt"
|
||||
)
|
||||
|
||||
// RegisterRoutes registers all authentication-related routes to the Echo engine
|
||||
// RegisterRoutes registers all authentication-related routes to the Echo engine.
|
||||
// It configures login and callback endpoints, and applies JWT authentication middleware.
|
||||
// If the DISABLE_AUTH environment variable is set to "true", authentication is bypassed.
|
||||
//
|
||||
// Parameters:
|
||||
// - e: The Echo instance to register routes on
|
||||
// - config: Configuration provider for authentication settings
|
||||
func RegisterRoutes(e *echo.Echo, config auth.ConfigProvider) {
|
||||
// check the auth feature flag
|
||||
fmt.Println("Registering routes for Auth.")
|
||||
@@ -54,7 +60,16 @@ func RegisterRoutes(e *echo.Echo, config auth.ConfigProvider) {
|
||||
e.Use(TokenValidationMiddleware(config))
|
||||
}
|
||||
|
||||
// GetTokenFromRequest extracts the token from the request
|
||||
// GetTokenFromRequest extracts the JWT token from the HTTP request.
|
||||
// It first attempts to retrieve the token from the Authorization header
|
||||
// in Bearer token format. If not found, it then tries to retrieve the token
|
||||
// from the "auth_token" cookie. Returns an empty string if no token is found.
|
||||
//
|
||||
// Parameters:
|
||||
// - c: The Echo context containing the HTTP request
|
||||
//
|
||||
// Returns:
|
||||
// - string: The extracted JWT token, or an empty string if not found
|
||||
func GetTokenFromRequest(c echo.Context) string {
|
||||
// First try from Authorization header
|
||||
authHeader := c.Request().Header.Get("Authorization")
|
||||
@@ -71,7 +86,17 @@ func GetTokenFromRequest(c echo.Context) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetUserInfo gets user information from the context
|
||||
// GetUserInfo retrieves user information from the Echo context.
|
||||
// It first attempts to retrieve user info directly from the context.
|
||||
// If not found there, it tries to extract and parse the JWT token,
|
||||
// then extract user information from the token claims.
|
||||
//
|
||||
// Parameters:
|
||||
// - c: The Echo context containing the HTTP request and context values
|
||||
//
|
||||
// Returns:
|
||||
// - UserInfo: Structure containing username, email, and groups
|
||||
// - bool: True if user information was successfully retrieved, false otherwise
|
||||
func GetUserInfo(c echo.Context) (UserInfo, bool) {
|
||||
// Try to get user info from context
|
||||
userInfo, ok := c.Get("user_info").(UserInfo)
|
||||
@@ -101,7 +126,17 @@ func GetUserInfo(c echo.Context) (UserInfo, bool) {
|
||||
return userInfo, true
|
||||
}
|
||||
|
||||
// RequireGroups creates a middleware that checks if the user is in any of the specified groups
|
||||
// RequireGroups creates a middleware that enforces group-based authorization.
|
||||
// It checks if the authenticated user belongs to at least one of the specified groups.
|
||||
// If the user is not authenticated, it returns a 401 Unauthorized response.
|
||||
// If the user is authenticated but doesn't belong to any of the required groups,
|
||||
// it returns a 403 Forbidden response with detailed information.
|
||||
//
|
||||
// Parameters:
|
||||
// - groups: Variable number of group names that grant access
|
||||
//
|
||||
// Returns:
|
||||
// - echo.MiddlewareFunc: Middleware function for Echo framework
|
||||
func RequireGroups(groups ...string) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
|
||||
@@ -16,8 +16,22 @@ import (
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// initiateLoginWithPKCE generates PKCE code challenge and redirects to Cognito
|
||||
// This function starts the OAuth authorization flow with PKCE
|
||||
// initiateLoginWithPKCE initiates the OAuth 2.0 authorization flow with PKCE (Proof Key for Code Exchange)
|
||||
// for Amazon Cognito authentication.
|
||||
//
|
||||
// This function:
|
||||
// 1. Generates a random state parameter to prevent CSRF attacks
|
||||
// 2. Creates a code verifier and its corresponding code challenge for PKCE
|
||||
// 3. Stores the PKCE parameters in a session for later verification
|
||||
// 4. Builds the authorization URL with all required OAuth and PKCE parameters
|
||||
// 5. Redirects the user to the Cognito login page
|
||||
//
|
||||
// Parameters:
|
||||
// - c: The Echo context for handling the HTTP request and response
|
||||
// - config: Configuration provider that supplies auth-related settings
|
||||
//
|
||||
// Returns:
|
||||
// - An error if any step of the process fails, or nil on successful redirect
|
||||
func initiateLoginWithPKCE(c echo.Context, config auth.ConfigProvider) error {
|
||||
// Generate random state parameter to prevent CSRF
|
||||
state, err := generateRandomString(32)
|
||||
@@ -63,9 +77,24 @@ func initiateLoginWithPKCE(c echo.Context, config auth.ConfigProvider) error {
|
||||
return c.Redirect(http.StatusFound, authURL)
|
||||
}
|
||||
|
||||
// exchangeCodeForTokensWithPKCE exchanges the authorization code for tokens using PKCE
|
||||
// Called during the OAuth callback flow to get tokens from the authorization code
|
||||
// Makes an HTTP request to Cognito's token endpoint to perform this exchange
|
||||
// exchangeCodeForTokensWithPKCE exchanges an authorization code for OAuth tokens using PKCE.
|
||||
//
|
||||
// This function performs the second part of the OAuth 2.0 authorization code flow with PKCE:
|
||||
// 1. Builds a token request with the authorization code, code verifier, and other required parameters
|
||||
// 2. Sends the request to the Cognito token endpoint
|
||||
// 3. Processes the response to extract the tokens
|
||||
//
|
||||
// It handles both confidential clients (with a client secret) and public clients (without a secret)
|
||||
// by adapting the authentication method used with the token endpoint.
|
||||
//
|
||||
// Parameters:
|
||||
// - authCode: The authorization code received from the OAuth provider (Cognito)
|
||||
// - codeVerifier: The original code verifier that was used to generate the code challenge
|
||||
// - config: Configuration provider that supplies auth-related settings
|
||||
//
|
||||
// Returns:
|
||||
// - A pointer to a TokenResponse containing the ID token, access token, and refresh token
|
||||
// - An error if the token exchange fails for any reason
|
||||
func exchangeCodeForTokensWithPKCE(authCode, codeVerifier string, config auth.ConfigProvider) (*TokenResponse, error) {
|
||||
data := url.Values{}
|
||||
data.Set("grant_type", "authorization_code")
|
||||
@@ -118,9 +147,24 @@ func exchangeCodeForTokensWithPKCE(authCode, codeVerifier string, config auth.Co
|
||||
return &tokenResponse, nil
|
||||
}
|
||||
|
||||
// handleOAuthCallback handles the OAuth 2.0 authorization code flow callback with PKCE
|
||||
// Called when Cognito redirects back to our application with an authorization code
|
||||
// Exchanges the code for tokens, verifies them, and redirects to home page with token in cookie
|
||||
// handleOAuthCallback processes the callback from Cognito after a user has authenticated.
|
||||
//
|
||||
// This function completes the OAuth 2.0 authorization code flow with PKCE by:
|
||||
// 1. Extracting and validating the authorization code and state parameters
|
||||
// 2. Retrieving the stored code verifier associated with the state parameter
|
||||
// 3. Exchanging the authorization code for tokens using the code verifier
|
||||
// 4. Verifying the received tokens using the JSON Web Key Set (JWKS)
|
||||
// 5. Extracting user information and group memberships from the tokens
|
||||
// 6. Checking if the user has the required permissions based on their group memberships
|
||||
// 7. Setting the access token as a cookie and redirecting to the home page if authorized
|
||||
//
|
||||
// Parameters:
|
||||
// - c: The Echo context for handling the HTTP request and response
|
||||
// - config: Configuration provider that supplies auth-related settings and permissions
|
||||
//
|
||||
// Returns:
|
||||
// - Various HTTP status codes and error messages based on the outcome of each step
|
||||
// - Redirects to the home page on successful authentication and authorization
|
||||
func handleOAuthCallback(c echo.Context, config auth.ConfigProvider) error {
|
||||
// Extract the authorization code and state
|
||||
code := c.QueryParam("code")
|
||||
|
||||
@@ -10,14 +10,38 @@ import (
|
||||
"github.com/lestrrat-go/jwx/v2/jwk"
|
||||
)
|
||||
|
||||
// Time constants for JWKS operations
|
||||
const (
|
||||
JWKS_CACHE_TTL = 24 * time.Hour
|
||||
// JWKS_CACHE_TTL is the time-to-live duration for the JWKS cache (24 hours)
|
||||
JWKS_CACHE_TTL = 24 * time.Hour
|
||||
|
||||
// JWKS_CLIENT_TIMEOUT is the timeout duration for HTTP requests to fetch JWKS (10 seconds)
|
||||
JWKS_CLIENT_TIMEOUT = 10 * time.Second
|
||||
)
|
||||
|
||||
// GetJWKS returns the cached JWKS or fetches a new one if needed
|
||||
// This function implements caching logic to minimize external requests
|
||||
// Used during token validation to get the key set for signature verification
|
||||
// GetJWKS retrieves a JSON Web Key Set (JWKS) from the specified URL, using a
|
||||
// thread-safe caching mechanism to minimize external requests.
|
||||
//
|
||||
// It implements a double-checked locking pattern to efficiently handle concurrent
|
||||
// access to the cached JWKS. It first attempts to retrieve a valid cached key set
|
||||
// using a read lock. If the cache is empty or expired, it acquires a write lock
|
||||
// to update the cache, but does a second check to avoid redundant fetches in case
|
||||
// another goroutine has already updated the cache.
|
||||
//
|
||||
// The retrieved JWKS is cached for JWKS_CACHE_TTL duration (24 hours by default).
|
||||
// This cache duration can be adjusted based on the security requirements and the
|
||||
// key rotation policy of the identity provider.
|
||||
//
|
||||
// Parameters:
|
||||
// - jwksURL: The URL from which to fetch the JWKS (typically provided by the Cognito or OAuth provider)
|
||||
// - logger: A structured logger for recording debug and error information during the JWKS retrieval process
|
||||
//
|
||||
// Returns:
|
||||
// - jwk.Set: The parsed JSON Web Key Set containing the public keys used for token verification
|
||||
// - error: An error if the JWKS cannot be fetched or parsed, nil otherwise
|
||||
//
|
||||
// This function is primarily used during token validation to get the key set
|
||||
// needed for signature verification of JWTs issued by the identity provider.
|
||||
func GetJWKS(jwksURL string, logger *slog.Logger) (jwk.Set, error) {
|
||||
// Try to use cached JWKS first (read lock)
|
||||
jwksCache.mutex.RLock()
|
||||
@@ -55,9 +79,28 @@ func GetJWKS(jwksURL string, logger *slog.Logger) (jwk.Set, error) {
|
||||
return keySet, nil
|
||||
}
|
||||
|
||||
// fetchJWKS retrieves the JSON Web Key Set from Cognito
|
||||
// Used to get the public keys needed to verify token signatures
|
||||
// Makes an HTTP request to the JWKS URL and returns the raw JSON
|
||||
// fetchJWKS makes an HTTP request to retrieve the JSON Web Key Set (JWKS) from
|
||||
// the specified URL, typically from a Cognito or other OAuth identity provider.
|
||||
//
|
||||
// This function handles the actual HTTP communication with the JWKS endpoint,
|
||||
// using a timeout-configured HTTP client to ensure the request doesn't hang
|
||||
// indefinitely. It performs a standard GET request and reads the raw JSON
|
||||
// response containing the public keys.
|
||||
//
|
||||
// The HTTP client is configured with JWKS_CLIENT_TIMEOUT (10 seconds by default)
|
||||
// to prevent long-running requests. This timeout can be adjusted based on network
|
||||
// conditions and reliability requirements.
|
||||
//
|
||||
// Parameters:
|
||||
// - jwksURL: The URL endpoint from which to fetch the JWKS
|
||||
//
|
||||
// Returns:
|
||||
// - string: The raw JSON string containing the JWKS data if successful
|
||||
// - error: An error if the HTTP request fails, the response cannot be read,
|
||||
// or any other error occurs during the fetching process
|
||||
//
|
||||
// This function is typically called by GetJWKS when the cached JWKS has expired
|
||||
// or is not available, and should not be called directly in most cases.
|
||||
func fetchJWKS(jwksURL string) (string, error) {
|
||||
client := &http.Client{Timeout: JWKS_CLIENT_TIMEOUT}
|
||||
req, err := http.NewRequest("GET", jwksURL, nil)
|
||||
|
||||
@@ -11,9 +11,24 @@ import (
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// TokenValidationMiddleware verifies JWT tokens efficiently
|
||||
// This is the primary middleware that handles both authentication and authorization
|
||||
// Applied to all routes to enforce security requirements
|
||||
// TokenValidationMiddleware verifies JWT tokens and enforces authentication and authorization.
|
||||
//
|
||||
// This middleware performs several critical security functions:
|
||||
// - Validates JWT tokens and their signatures against the JWKS from the identity provider
|
||||
// - Extracts and validates claims from the token
|
||||
// - Extracts user groups and stores them in the context
|
||||
// - Checks authorization based on the user's group memberships
|
||||
// - Enforces route-specific permissions
|
||||
//
|
||||
// The middleware skips authentication for public paths and handles special cases
|
||||
// like OAuth callbacks and login initiation. For protected routes, it enforces
|
||||
// both authentication (valid token) and authorization (correct group membership).
|
||||
//
|
||||
// Parameters:
|
||||
// - config: A ConfigProvider implementation that supplies all necessary auth configuration
|
||||
//
|
||||
// Returns:
|
||||
// - echo.MiddlewareFunc: An Echo middleware function that can be added to the middleware chain
|
||||
func TokenValidationMiddleware(config auth.ConfigProvider) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
@@ -109,7 +124,23 @@ func TokenValidationMiddleware(config auth.ConfigProvider) echo.MiddlewareFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// JWTAuthMiddleware checks for JWT token in cookies and adds it to the Authorization header
|
||||
// JWTAuthMiddleware extracts JWT tokens from cookies and adds them to the Authorization header.
|
||||
//
|
||||
// This middleware serves as a bridge between cookie-based and header-based authentication:
|
||||
// - Checks for auth_token cookie and transfers it to the Authorization header
|
||||
// - Skips processing for login and callback paths that handle authentication
|
||||
// - Manages cookie deletion during logout operations
|
||||
// - Redirects unauthenticated requests to the login path
|
||||
//
|
||||
// This middleware should be registered before TokenValidationMiddleware in the middleware
|
||||
// chain to ensure the JWT token is properly placed in the Authorization header before
|
||||
// validation occurs.
|
||||
//
|
||||
// Parameters:
|
||||
// - config: A ConfigProvider implementation that supplies auth configuration values
|
||||
//
|
||||
// Returns:
|
||||
// - echo.MiddlewareFunc: An Echo middleware function that can be added to the middleware chain
|
||||
func JWTAuthMiddleware(config auth.ConfigProvider) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
|
||||
@@ -6,9 +6,23 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// matchRoute checks if a request path matches a route pattern
|
||||
// Converts Echo route patterns to regex for matching
|
||||
// Supports parameter patterns like '/users/:id' and wildcard patterns
|
||||
// matchRoute determines if a request path matches a route pattern by converting
|
||||
// Echo-style route patterns to regular expressions for matching.
|
||||
//
|
||||
// The function supports several pattern formats:
|
||||
// - Exact path matching (e.g., "/users/profile")
|
||||
// - Parameter patterns (e.g., "/users/:id" matches "/users/123")
|
||||
// - Wildcard patterns (e.g., "/static/*" matches any path starting with "/static/")
|
||||
//
|
||||
// Parameters:
|
||||
// - requestPath: The actual HTTP request path to check
|
||||
// - routePattern: The Echo-style route pattern to match against
|
||||
//
|
||||
// Returns:
|
||||
// - bool: true if the requestPath matches the routePattern, false otherwise
|
||||
//
|
||||
// Note that if the conversion of the route pattern to a regular expression fails,
|
||||
// the function will return false.
|
||||
func matchRoute(requestPath, routePattern string) bool {
|
||||
// Convert Echo route pattern to regex pattern
|
||||
// e.g., "/users/:id" to "/users/([^/]+)"
|
||||
@@ -43,9 +57,28 @@ func matchRoute(requestPath, routePattern string) bool {
|
||||
return regex.MatchString(requestPath)
|
||||
}
|
||||
|
||||
// checkPermissions checks if the user has the required permissions
|
||||
// Used by both the main token validation middleware and the OAuth callback handler
|
||||
// Returns true if authorized, false if not, along with the required groups
|
||||
// checkPermissions verifies if a user has the necessary permissions to access a specific
|
||||
// path based on their group memberships and the route permission configuration.
|
||||
//
|
||||
// This function is used by both the main token validation middleware and the OAuth
|
||||
// callback handler to implement route-based access control. It works by:
|
||||
// 1. Finding a matching route pattern in the routePermissions map
|
||||
// 2. Extracting the required groups for that route
|
||||
// 3. Checking if the user belongs to any of the required groups
|
||||
//
|
||||
// If no matching route pattern is found, access is allowed by default.
|
||||
// If a matching pattern is found but no groups are required, access is allowed.
|
||||
// Otherwise, the user must belong to at least one of the required groups.
|
||||
//
|
||||
// Parameters:
|
||||
// - path: The HTTP request path to check permissions for
|
||||
// - userGroups: A slice of group names that the user belongs to
|
||||
// - routePermissions: A map where keys are route patterns and values are slices of required group names
|
||||
// - logger: A structured logger for recording debug and authorization information
|
||||
//
|
||||
// Returns:
|
||||
// - bool: true if the user is authorized, false otherwise
|
||||
// - []string: The list of required groups for the matching route (may be empty)
|
||||
func checkPermissions(path string, userGroups []string, routePermissions map[string][]string, logger *slog.Logger) (bool, []string) {
|
||||
// Find matching route pattern
|
||||
var requiredGroups []string
|
||||
@@ -83,15 +116,3 @@ func checkPermissions(path string, userGroups []string, routePermissions map[str
|
||||
|
||||
return false, requiredGroups
|
||||
}
|
||||
|
||||
//// Helper function to mask sensitive values
|
||||
//// Used for logging sensitive information like client IDs
|
||||
//func maskString(s string) string {
|
||||
// if s == "" {
|
||||
// return "<not set>"
|
||||
// }
|
||||
// if len(s) <= 8 {
|
||||
// return "****"
|
||||
// }
|
||||
// return s[:4] + "..." + s[len(s)-4:]
|
||||
//}
|
||||
|
||||
@@ -18,9 +18,20 @@ import (
|
||||
|
||||
const PKCE_SESSION_TTL = 5 * time.Minute
|
||||
|
||||
// verifyToken verifies the JWT token and returns its claims
|
||||
// Used during both OAuth callback and subsequent API requests with bearer token
|
||||
// Verifies signature, expiration, issuer, and other JWT claims
|
||||
// verifyToken verifies the JWT token and returns its claims.
|
||||
//
|
||||
// This function validates the provided JWT token against a JWK key set,
|
||||
// verifying signature, expiration, issuer, and other standard JWT claims.
|
||||
// It's used during both OAuth callback and subsequent API requests with bearer tokens.
|
||||
//
|
||||
// Parameters:
|
||||
// - tokenString: The raw JWT token string to verify
|
||||
// - keySet: The JWK set containing keys to verify the token signature
|
||||
// - config: Configuration provider containing auth settings like region and user pool ID
|
||||
//
|
||||
// Returns:
|
||||
// - map[string]interface{}: The verified token claims as a map
|
||||
// - error: Error if token verification fails for any reason
|
||||
func verifyToken(tokenString string, keySet jwk.Set, config auth.ConfigProvider) (map[string]interface{}, error) {
|
||||
region := config.GetAuthRegion()
|
||||
issuer := fmt.Sprintf("https://cognito-idp.%s.amazonaws.com/%s", region, config.GetAuthUserPoolID())
|
||||
@@ -46,9 +57,18 @@ func verifyToken(tokenString string, keySet jwk.Set, config auth.ConfigProvider)
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
// GetUserGroups extracts user groups from the token claims
|
||||
// Attempts to find groups in different claim names depending on Cognito setup
|
||||
// Returns an array of group names or an error if no groups found
|
||||
// GetUserGroups extracts user groups from the token claims.
|
||||
//
|
||||
// This function attempts to find groups in different claim names depending
|
||||
// on the Cognito setup. It checks several common claim names where group
|
||||
// information might be stored, handling different data formats.
|
||||
//
|
||||
// Parameters:
|
||||
// - claims: A map of token claims extracted from a verified JWT token
|
||||
//
|
||||
// Returns:
|
||||
// - []string: An array of group names that the user belongs to
|
||||
// - error: Error if no groups are found in any of the expected claim fields
|
||||
func GetUserGroups(claims map[string]interface{}) ([]string, error) {
|
||||
// The claim containing the groups might have different names depending on your Cognito setup
|
||||
// Common names are "cognito:groups", "groups", or a custom attribute
|
||||
@@ -74,8 +94,17 @@ func GetUserGroups(claims map[string]interface{}) ([]string, error) {
|
||||
return nil, errors.New("no groups found in token claims")
|
||||
}
|
||||
|
||||
// createCodeChallenge creates a code challenge from a code verifier
|
||||
// Implements S256 code challenge method as specified in PKCE RFC 7636
|
||||
// createCodeChallenge creates a code challenge from a code verifier.
|
||||
//
|
||||
// This function implements the S256 code challenge method as specified in
|
||||
// PKCE (Proof Key for Code Exchange) RFC 7636. It creates a SHA256 hash
|
||||
// of the verifier and encodes it as base64url without padding.
|
||||
//
|
||||
// Parameters:
|
||||
// - verifier: The PKCE code verifier string to transform
|
||||
//
|
||||
// Returns:
|
||||
// - string: The generated code challenge for use in the authorization request
|
||||
func createCodeChallenge(verifier string) string {
|
||||
// Create SHA256 hash of the verifier
|
||||
hash := sha256.Sum256([]byte(verifier))
|
||||
@@ -86,8 +115,19 @@ func createCodeChallenge(verifier string) string {
|
||||
return challenge
|
||||
}
|
||||
|
||||
// generateRandomString creates a cryptographically secure random string
|
||||
// Used for generating state parameter and code verifier
|
||||
// generateRandomString creates a cryptographically secure random string.
|
||||
//
|
||||
// This function generates a cryptographically secure random byte sequence
|
||||
// of the specified length and encodes it as a URL-safe base64 string.
|
||||
// It's used for generating the state parameter and code verifier in the
|
||||
// OAuth/PKCE flow.
|
||||
//
|
||||
// Parameters:
|
||||
// - length: The desired length of the random string
|
||||
//
|
||||
// Returns:
|
||||
// - string: The generated random string
|
||||
// - error: Error if random bytes generation fails
|
||||
func generateRandomString(length int) (string, error) {
|
||||
b := make([]byte, length)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
@@ -96,8 +136,17 @@ func generateRandomString(length int) (string, error) {
|
||||
return base64.RawURLEncoding.EncodeToString(b)[:length], nil
|
||||
}
|
||||
|
||||
// storePKCESession stores the PKCE session for later verification
|
||||
// In a production environment, this should be replaced with a proper session store
|
||||
// storePKCESession stores the PKCE session for later verification.
|
||||
//
|
||||
// This function creates and stores a new PKCE session in the in-memory session map,
|
||||
// associating it with the provided state parameter. It also performs cleanup of
|
||||
// expired sessions. In a production environment, this should be replaced with
|
||||
// a proper persistent session store.
|
||||
//
|
||||
// Parameters:
|
||||
// - state: The OAuth state parameter that serves as the session identifier
|
||||
// - codeVerifier: The PKCE code verifier to store for later validation
|
||||
// - logger: A structured logger for recording debug information
|
||||
func storePKCESession(state, codeVerifier string, logger *slog.Logger) {
|
||||
pkceSessionMap.Lock()
|
||||
defer pkceSessionMap.Unlock()
|
||||
@@ -120,7 +169,19 @@ func storePKCESession(state, codeVerifier string, logger *slog.Logger) {
|
||||
}
|
||||
}
|
||||
|
||||
// getCodeVerifier retrieves and validates the code verifier for a state
|
||||
// getCodeVerifier retrieves and validates the code verifier for a state.
|
||||
//
|
||||
// This function looks up a PKCE session by its state parameter and returns
|
||||
// the associated code verifier if the session exists and hasn't expired.
|
||||
// It's used during the token exchange step of the OAuth/PKCE flow.
|
||||
//
|
||||
// Parameters:
|
||||
// - state: The OAuth state parameter that serves as the session identifier
|
||||
// - logger: A structured logger for recording debug information
|
||||
//
|
||||
// Returns:
|
||||
// - string: The code verifier associated with the state
|
||||
// - error: Error if no session is found or if the session has expired
|
||||
func getCodeVerifier(state string, logger *slog.Logger) (string, error) {
|
||||
pkceSessionMap.RLock()
|
||||
defer pkceSessionMap.RUnlock()
|
||||
@@ -137,7 +198,17 @@ func getCodeVerifier(state string, logger *slog.Logger) (string, error) {
|
||||
return session.CodeVerifier, nil
|
||||
}
|
||||
|
||||
// ExtractUserInfo extracts user information from JWT claims
|
||||
// ExtractUserInfo extracts user information from JWT claims.
|
||||
//
|
||||
// This function parses a verified JWT claims map and extracts relevant user
|
||||
// information such as username, email, and group memberships. It creates and
|
||||
// returns a UserInfo struct with the extracted data.
|
||||
//
|
||||
// Parameters:
|
||||
// - claims: A map of token claims extracted from a verified JWT token
|
||||
//
|
||||
// Returns:
|
||||
// - UserInfo: A struct containing the extracted user information
|
||||
func ExtractUserInfo(claims map[string]interface{}) UserInfo {
|
||||
userInfo := UserInfo{}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user