validator

package
v1.1.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 2, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidConfig indicates invalid validator configuration.
	ErrInvalidConfig = errors.New("invalid validator configuration")

	// ErrTokenExpired indicates the token has expired.
	ErrTokenExpired = errors.New("token expired")

	// ErrInvalidIssuer indicates the token issuer doesn't match expected value.
	ErrInvalidIssuer = errors.New("invalid issuer")

	// ErrInvalidAudience indicates the token audience doesn't match expected value.
	ErrInvalidAudience = errors.New("invalid audience")

	// ErrTokenNotYetValid indicates the token is not yet valid (nbf claim).
	ErrTokenNotYetValid = errors.New("token not yet valid")

	// ErrInvalidSignature indicates the token signature verification failed.
	ErrInvalidSignature = errors.New("invalid signature")

	// ErrKeyNotFound indicates the public key for the token was not found.
	ErrKeyNotFound = errors.New("public key not found")

	// ErrJWKSFetchFailed indicates JWKS fetch from the endpoint failed.
	ErrJWKSFetchFailed = errors.New("JWKS fetch failed")
)

Sentinel errors for use with errors.Is()

Functions

This section is empty.

Types

type Claims

type Claims struct {
	// Standard JWT claims (RFC 7519)
	Issuer    string     `json:"iss,omitempty"` // Token issuer (Logto endpoint)
	Subject   string     `json:"sub,omitempty"` // Subject - user ID
	Audience  []string   `json:"aud,omitempty"` // Intended audience (API resource indicator)
	ExpiresAt *time.Time `json:"exp,omitempty"` // Expiration time
	NotBefore *time.Time `json:"nbf,omitempty"` // Not valid before
	IssuedAt  *time.Time `json:"iat,omitempty"` // Issued at time
	ID        string     `json:"jti,omitempty"` // Unique token identifier

	// Logto-specific claims
	ClientID       string `json:"client_id,omitempty"`       // Application that requested the token
	OrganizationID string `json:"organization_id,omitempty"` // Organization context (for org-scoped tokens)

	// Permissions (space-separated string from OIDC provider)
	Scope string `json:"scope,omitempty"` // Space-separated permissions
}

Claims represents JWT token claims from Logto Identity Provider. This is used internally for parsing JWT tokens. See: https://docs.logto.io/authorization/validate-access-tokens

func (*Claims) GetScopes

func (c *Claims) GetScopes() []string

GetScopes parses the space-separated scope string into a slice

func (*Claims) HasAudience

func (c *Claims) HasAudience(audience string) bool

HasAudience checks if the token was issued for the specified audience. The audience claim (aud) can be a single string or an array of strings. This is critical for security - tokens should only be accepted if issued for the specific API resource (audience) that is validating them.

func (*Claims) UnmarshalJSON

func (c *Claims) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom JSON unmarshaling to handle: - Unix timestamps for time fields (exp, nbf, iat) - Audience as either string or array of strings

type JWKSValidator

type JWKSValidator struct {
	// contains filtered or unexported fields
}

JWKSValidator validates JWT tokens using cached JWKS public keys

func NewJWKSValidator

func NewJWKSValidator(jwksURL, issuer, audience string, cacheTTL time.Duration, logger *slog.Logger) (*JWKSValidator, error)

NewJWKSValidator creates a new JWT validator with JWKS caching.

Parameters:

  • jwksURL: URL to fetch JWKS public keys from (e.g., "https://your-tenant.logto.app/oidc/jwks")
  • issuer: Expected token issuer (e.g., "https://your-tenant.logto.app/oidc")
  • audience: Expected audience - the API resource indicator the token was issued for. This is critical for security: tokens issued for different APIs will be rejected. Use empty string to skip audience validation (NOT recommended for production).
  • cacheTTL: How long to cache JWKS keys before refreshing
  • logger: Optional slog.Logger for debug output (nil uses slog.Default())

func (*JWKSValidator) StartBackgroundRefresh

func (v *JWKSValidator) StartBackgroundRefresh(ctx context.Context, interval time.Duration)

StartBackgroundRefresh starts a goroutine to refresh JWKS periodically. The ctx parameter controls the lifecycle of the background goroutine - when ctx is cancelled, the background refresh stops. Each refresh operation uses a fresh context with 30s timeout.

func (*JWKSValidator) ValidateToken

func (v *JWKSValidator) ValidateToken(ctx context.Context, tokenString string) (*TokenInfo, error)

ValidateToken validates a JWT token and returns TokenInfo

type Token

type Token interface {
	// GetUserID returns the subject (sub) claim - the user identifier
	GetUserID() string

	// GetOrganizationID returns the organization context (if present)
	GetOrganizationID() string

	// GetScopes returns parsed scope permissions
	GetScopes() []string

	// HasScope checks if token has a specific permission
	HasScope(scope string) bool

	// HasAllScopes checks if token has all specified permissions
	HasAllScopes(scopes ...string) bool

	// HasAnyScope checks if token has any of the specified permissions
	HasAnyScope(scopes ...string) bool

	// GetRawClaims returns all JWT claims for custom claim access
	GetRawClaims() map[string]any
}

Token represents a validated JWT access token. Implement this interface to create custom token types with typed claims.

Example of creating a custom token type:

type MyToken struct {
    *validator.TokenInfo
    TenantID string
    Roles    []string
}

func NewMyToken(info *validator.TokenInfo) *MyToken {
    return &MyToken{
        TokenInfo: info,
        TenantID:  info.GetStringClaim("tenant_id"),
        Roles:     info.GetStringSliceClaim("roles"),
    }
}

type TokenInfo

type TokenInfo struct {
	// Standard JWT claims (RFC 7519)
	Issuer    string     // iss - token issuer (Logto endpoint)
	Subject   string     // sub - user ID
	Audience  []string   // aud - API resource(s) token was issued for
	ExpiresAt *time.Time // exp - token expiration time
	IssuedAt  *time.Time // iat - when token was issued
	NotBefore *time.Time // nbf - token not valid before (nil if not set)
	JWTID     string     // jti - unique token identifier

	// Logto-specific claims
	ClientID       string   // client_id - application that requested the token
	OrganizationID string   // organization_id - organization context (for org-scoped tokens)
	Scopes         []string // scope - parsed permissions

	// Convenience alias (for backward compatibility)
	UserID string // Alias for Subject (sub claim)

	// RawClaims contains all JWT claims for access to custom claims
	// configured via Logto Custom JWT feature.
	// See: https://docs.logto.io/developers/custom-token-claims
	RawClaims map[string]any
}

TokenInfo represents a validated Logto JWT access token. This is NOT a full user - only security context from the token. Use Client.GetUser() to get full user profile.

Implements the Token interface.

See: https://docs.logto.io/authorization/validate-access-tokens

func (*TokenInfo) GetArrayMapClaim added in v1.1.4

func (t *TokenInfo) GetArrayMapClaim(key string) []map[string]any

GetArrayMapClaim returns a custom claim as []map[string]any. Handles JSON arrays of objects which are decoded as []any containing map[string]any items. Returns nil if claim doesn't exist or cannot be converted.

func (*TokenInfo) GetBoolClaim

func (t *TokenInfo) GetBoolClaim(key string) bool

GetBoolClaim returns a custom claim as bool. Returns false if claim doesn't exist or is not a bool.

func (*TokenInfo) GetClaim

func (t *TokenInfo) GetClaim(key string) any

GetClaim returns a custom claim value by key. Returns nil if the claim doesn't exist or RawClaims is nil.

func (*TokenInfo) GetFloat64Claim

func (t *TokenInfo) GetFloat64Claim(key string) float64

GetFloat64Claim returns a custom claim as float64. JSON numbers are decoded as float64. Returns 0 if claim doesn't exist or is not a number.

func (*TokenInfo) GetIntClaim

func (t *TokenInfo) GetIntClaim(key string) int

GetIntClaim returns a custom claim as int. Converts from float64 since JSON numbers are decoded as float64. Returns 0 if claim doesn't exist or is not a number.

func (*TokenInfo) GetMapClaim added in v1.1.4

func (t *TokenInfo) GetMapClaim(key string) map[string]any

GetMapClaim returns a custom claim as map[string]any. JSON objects are decoded as map[string]any. Returns nil if claim doesn't exist or is not a map.

func (*TokenInfo) GetOrganizationID

func (t *TokenInfo) GetOrganizationID() string

GetOrganizationID returns the organization context (if present)

func (*TokenInfo) GetRawClaims

func (t *TokenInfo) GetRawClaims() map[string]any

GetRawClaims returns all JWT claims for custom claim access

func (*TokenInfo) GetScopes

func (t *TokenInfo) GetScopes() []string

GetScopes returns parsed scope permissions

func (*TokenInfo) GetStringClaim

func (t *TokenInfo) GetStringClaim(key string) string

GetStringClaim returns a custom claim as string. Returns empty string if claim doesn't exist or is not a string.

func (*TokenInfo) GetStringSliceClaim

func (t *TokenInfo) GetStringSliceClaim(key string) []string

GetStringSliceClaim returns a custom claim as []string. Handles JSON arrays which are decoded as []any. Returns nil if claim doesn't exist or cannot be converted.

func (*TokenInfo) GetUserID

func (t *TokenInfo) GetUserID() string

GetUserID returns the subject (sub) claim - the user identifier

func (*TokenInfo) HasAllScopes

func (t *TokenInfo) HasAllScopes(scopes ...string) bool

HasAllScopes checks if token has all of the specified permissions

func (*TokenInfo) HasAnyScope

func (t *TokenInfo) HasAnyScope(scopes ...string) bool

HasAnyScope checks if token has any of the specified permissions

func (*TokenInfo) HasAudience

func (t *TokenInfo) HasAudience(audience string) bool

HasAudience checks if token was issued for the specified audience.

func (*TokenInfo) HasScope

func (t *TokenInfo) HasScope(scope string) bool

HasScope checks if token has a specific permission

func (*TokenInfo) IsExpired

func (t *TokenInfo) IsExpired() bool

IsExpired checks if the token has expired.

type TokenValidator

type TokenValidator interface {
	ValidateToken(ctx context.Context, token string) (*TokenInfo, error)
}

TokenValidator validates JWT tokens and returns TokenInfo

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL