Documentation
¶
Overview ¶
Package oidc provides OpenID Connect authentication support for GraphDB.
Index ¶
- Constants
- Variables
- func DefaultScopes() []string
- func HigherPrivilegeRole(a, b string) string
- func RolePriority(role string) int
- type CachedDiscovery
- type CachedJWKS
- type Config
- type DiscoveryClient
- type ErrorResponse
- type IDTokenClaims
- type JWK
- type JWKS
- type JWKSClient
- type LoginResponse
- type OIDCDiscovery
- type OIDCHandler
- type OIDCTokenValidator
- type RoleMapper
- type RoleMapping
- type StateEntry
- type StateStore
- type TokenResponse
- type TokenValidationRequest
- type UserInfo
Constants ¶
const ( DefaultJWKSCacheTTL = time.Hour DefaultRole = "viewer" )
Default configuration values
const ( // StateLength is the byte length of CSRF state tokens StateLength = 32 // DefaultStateTTL is how long state tokens are valid DefaultStateTTL = 10 * time.Minute // MaxStateEntries is the maximum number of pending state entries (DoS protection) MaxStateEntries = 10000 )
const MaxKeyCacheSize = 1000
MaxKeyCacheSize limits the number of cached RSA keys to prevent unbounded growth
Variables ¶
var ( ErrKeyNotFound = errors.New("key not found in JWKS") ErrInvalidKeyUse = errors.New("key is not for signature verification") ErrUnsupportedKty = errors.New("unsupported key type") )
var ( ErrTokenMalformed = errors.New("token is malformed") ErrTokenExpired = errors.New("token has expired") ErrInvalidSignature = errors.New("invalid token signature") ErrInvalidIssuer = errors.New("invalid token issuer") ErrInvalidAudience = errors.New("invalid token audience") ErrMissingSubject = errors.New("token missing subject claim") ErrUnsupportedAlg = errors.New("unsupported signing algorithm") )
Functions ¶
func HigherPrivilegeRole ¶
HigherPrivilegeRole returns the role with higher privilege
func RolePriority ¶
RolePriority returns the priority of a role (higher = more privileged)
Types ¶
type CachedDiscovery ¶
type CachedDiscovery struct {
Discovery *OIDCDiscovery
FetchedAt time.Time
ExpiresAt time.Time
}
CachedDiscovery holds a discovery document with cache metadata
type CachedJWKS ¶
CachedJWKS holds JWKS with cache metadata
type Config ¶
type Config struct {
// Enabled determines if OIDC authentication is active
Enabled bool `json:"enabled"`
// Issuer is the OIDC provider URL (e.g., "https://accounts.google.com")
Issuer string `json:"issuer"`
// ClientID is the OAuth2 client ID
ClientID string `json:"client_id"`
// ClientSecret is the OAuth2 client secret (required for authorization code flow)
ClientSecret string `json:"client_secret"`
// RedirectURI is the callback URL (auto-detected if empty)
RedirectURI string `json:"redirect_uri"`
// Scopes to request from the provider (default: openid, profile, email)
Scopes []string `json:"scopes"`
// RoleMappings define how to map OIDC claims to GraphDB roles
RoleMappings []RoleMapping `json:"role_mappings"`
// DefaultRole is assigned when no role mapping matches (default: viewer)
DefaultRole string `json:"default_role"`
// JWKSCacheTTL is how long to cache JWKS (default: 1 hour)
JWKSCacheTTL time.Duration `json:"jwks_cache_ttl"`
// AllowedAudiences are additional valid audience values
AllowedAudiences []string `json:"allowed_audiences"`
}
Config holds OIDC provider configuration
func LoadConfigFromEnv ¶
LoadConfigFromEnv loads OIDC configuration from environment variables
func (*Config) GetAllowedAudiences ¶
GetAllowedAudiences returns all valid audience values (ClientID + configured audiences)
type DiscoveryClient ¶
type DiscoveryClient struct {
// contains filtered or unexported fields
}
DiscoveryClient fetches and caches OIDC discovery documents
func NewDiscoveryClient ¶
func NewDiscoveryClient() *DiscoveryClient
NewDiscoveryClient creates a new discovery client with default settings
func NewDiscoveryClientWithHTTP ¶
func NewDiscoveryClientWithHTTP(client *http.Client, cacheTTL time.Duration) *DiscoveryClient
NewDiscoveryClientWithHTTP creates a discovery client with custom HTTP client Useful for testing with mock servers
func (*DiscoveryClient) ClearCache ¶
func (c *DiscoveryClient) ClearCache()
ClearCache removes all cached discovery documents
func (*DiscoveryClient) ClearCacheForIssuer ¶
func (c *DiscoveryClient) ClearCacheForIssuer(issuer string)
ClearCacheForIssuer removes the cached discovery for a specific issuer
func (*DiscoveryClient) GetDiscovery ¶
func (c *DiscoveryClient) GetDiscovery(ctx context.Context, issuer string) (*OIDCDiscovery, error)
GetDiscovery fetches the OIDC discovery document for an issuer. Results are cached for cacheTTL duration.
type ErrorResponse ¶
ErrorResponse represents an error response
type IDTokenClaims ¶
type IDTokenClaims struct {
// Standard claims
Issuer string `json:"iss"`
Subject string `json:"sub"`
Audience any `json:"aud"` // Can be string or []string
ExpiresAt int64 `json:"exp"`
IssuedAt int64 `json:"iat"`
AuthTime int64 `json:"auth_time,omitempty"`
Nonce string `json:"nonce,omitempty"`
// Profile claims
Name string `json:"name,omitempty"`
GivenName string `json:"given_name,omitempty"`
FamilyName string `json:"family_name,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty"`
Picture string `json:"picture,omitempty"`
// Email claims
Email string `json:"email,omitempty"`
EmailVerified bool `json:"email_verified,omitempty"`
// Additional claims for role mapping
Groups []string `json:"groups,omitempty"`
Roles []string `json:"roles,omitempty"`
// Raw claims map for custom claim access
Raw map[string]any `json:"-"`
}
IDTokenClaims represents standard OIDC ID token claims
func (*IDTokenClaims) GetAudiences ¶
func (c *IDTokenClaims) GetAudiences() []string
GetAudiences returns the audience claim as a slice (handles both string and array)
type JWK ¶
type JWK struct {
Kty string `json:"kty"` // Key type (RSA, EC)
Kid string `json:"kid"` // Key ID
Use string `json:"use"` // Key use (sig)
Alg string `json:"alg"` // Algorithm (RS256, RS384, RS512)
// RSA key components
N string `json:"n,omitempty"` // RSA modulus
E string `json:"e,omitempty"` // RSA exponent
// EC key components (for future support)
Crv string `json:"crv,omitempty"` // Curve name
X string `json:"x,omitempty"` // X coordinate
Y string `json:"y,omitempty"` // Y coordinate
}
JWK represents a JSON Web Key
func FindKeyByKid ¶
FindKeyByKid searches for a key by its kid in a JWKS
type JWKSClient ¶
type JWKSClient struct {
// contains filtered or unexported fields
}
JWKSClient fetches and caches JSON Web Key Sets
func NewJWKSClient ¶
func NewJWKSClient(cacheTTL time.Duration) *JWKSClient
NewJWKSClient creates a new JWKS client with default settings
func NewJWKSClientWithHTTP ¶
func NewJWKSClientWithHTTP(client *http.Client, cacheTTL time.Duration) *JWKSClient
NewJWKSClientWithHTTP creates a JWKS client with custom HTTP client Useful for testing with mock servers
func (*JWKSClient) ClearCache ¶
func (c *JWKSClient) ClearCache()
ClearCache removes all cached JWKS and keys
func (*JWKSClient) ClearCacheForURL ¶
func (c *JWKSClient) ClearCacheForURL(jwksURL string)
ClearCacheForURL removes the cached JWKS for a specific URL
type LoginResponse ¶
type LoginResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in"`
User UserInfo `json:"user"`
}
LoginResponse is returned after successful OIDC authentication
type OIDCDiscovery ¶
type OIDCDiscovery struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
UserinfoEndpoint string `json:"userinfo_endpoint"`
JWKSUri string `json:"jwks_uri"`
ScopesSupported []string `json:"scopes_supported"`
ClaimsSupported []string `json:"claims_supported"`
}
OIDCDiscovery represents the OIDC discovery document (.well-known/openid-configuration)
type OIDCHandler ¶
type OIDCHandler struct {
// contains filtered or unexported fields
}
OIDCHandler handles OIDC authentication endpoints
func NewOIDCHandler ¶
func NewOIDCHandler( config *Config, userStore *auth.UserStore, jwtManager *auth.JWTManager, ) *OIDCHandler
NewOIDCHandler creates a new OIDC authentication handler
func NewOIDCHandlerWithClients ¶
func NewOIDCHandlerWithClients( config *Config, discoveryClient *DiscoveryClient, tokenValidator *OIDCTokenValidator, userStore *auth.UserStore, jwtManager *auth.JWTManager, stateStore *StateStore, httpClient *http.Client, ) *OIDCHandler
NewOIDCHandlerWithClients creates an OIDC handler with custom clients (for testing)
func (*OIDCHandler) ServeHTTP ¶
func (h *OIDCHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler interface for routing
type OIDCTokenValidator ¶
type OIDCTokenValidator struct {
// contains filtered or unexported fields
}
OIDCTokenValidator validates OIDC ID tokens using RS256/384/512
func NewOIDCTokenValidator ¶
func NewOIDCTokenValidator(config *Config) *OIDCTokenValidator
NewOIDCTokenValidator creates a new OIDC token validator
func NewOIDCTokenValidatorWithClients ¶
func NewOIDCTokenValidatorWithClients( config *Config, discoveryClient *DiscoveryClient, jwksClient *JWKSClient, ) *OIDCTokenValidator
NewOIDCTokenValidatorWithClients creates a validator with custom clients (for testing)
func (*OIDCTokenValidator) GetOIDCClaims ¶
func (v *OIDCTokenValidator) GetOIDCClaims(ctx context.Context, tokenString string) (*IDTokenClaims, error)
GetOIDCClaims extracts and returns the full OIDC claims from a token (useful for user provisioning)
func (*OIDCTokenValidator) Name ¶
func (v *OIDCTokenValidator) Name() string
Name returns the validator name for logging/debugging. Implements the auth.TokenValidator interface.
func (*OIDCTokenValidator) ValidateToken ¶
func (v *OIDCTokenValidator) ValidateToken(ctx context.Context, tokenString string) (*auth.Claims, error)
ValidateToken validates an OIDC ID token and returns GraphDB claims. Implements the auth.TokenValidator interface.
type RoleMapper ¶
type RoleMapper struct {
// contains filtered or unexported fields
}
RoleMapper maps OIDC claims to GraphDB roles
func NewRoleMapper ¶
func NewRoleMapper(mappings []RoleMapping, defaultRole string) *RoleMapper
NewRoleMapper creates a new role mapper with the given mappings
func (*RoleMapper) MapRole ¶
func (m *RoleMapper) MapRole(claims *IDTokenClaims) string
MapRole determines the GraphDB role based on OIDC claims. Mappings are evaluated in order; first match wins. Higher-privilege mappings should be listed first (admin before editor before viewer).
type RoleMapping ¶
type RoleMapping struct {
// ClaimName is the OIDC claim to check (e.g., "groups", "roles", "cognito:groups")
ClaimName string `json:"claim_name"`
// ClaimValues are the values that trigger this mapping (OR logic)
ClaimValues []string `json:"claim_value"`
// GraphDBRole is the target GraphDB role ("admin", "editor", "viewer")
GraphDBRole string `json:"graphdb_role"`
}
RoleMapping defines how to map OIDC claims to GraphDB roles
type StateEntry ¶
StateEntry holds CSRF state with expiration
type StateStore ¶
type StateStore struct {
// contains filtered or unexported fields
}
StateStore manages CSRF state for OAuth2 flows
func NewStateStore ¶
func NewStateStore() *StateStore
NewStateStore creates a new state store with default settings
func NewStateStoreWithTTL ¶
func NewStateStoreWithTTL(ttl time.Duration) *StateStore
NewStateStoreWithTTL creates a state store with custom TTL
func (*StateStore) Close ¶
func (s *StateStore) Close()
Close stops the cleanup goroutine and releases resources
func (*StateStore) GenerateState ¶
func (s *StateStore) GenerateState() (string, error)
GenerateState creates a new CSRF state token
func (*StateStore) Len ¶
func (s *StateStore) Len() int
Len returns the number of pending state entries
func (*StateStore) ValidateAndConsume ¶
func (s *StateStore) ValidateAndConsume(state string) (*StateEntry, bool)
ValidateAndConsume validates a state token and removes it (one-time use)
type TokenResponse ¶
type TokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in"`
RefreshToken string `json:"refresh_token,omitempty"`
IDToken string `json:"id_token"`
Scope string `json:"scope,omitempty"`
}
TokenResponse represents the response from the token endpoint
type TokenValidationRequest ¶
type TokenValidationRequest struct {
IDToken string `json:"id_token"`
}
TokenValidationRequest is the request body for POST /auth/oidc/token