token

package
v0.29.0 Latest Latest
Warning

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

Go to latest
Published: May 5, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Index

Constants

View Source
const (
	TokenCategoryAccess  = "access"
	TokenCategoryRefresh = "refresh"
)

Token category constants used in the "type" JWT claim.

View Source
const (
	TokenTypeBearer = "Bearer"
)

Token type constants

Variables

View Source
var (
	// ErrTokenGeneration indicates token generation failed
	ErrTokenGeneration = errors.New("failed to generate token")

	// ErrInvalidToken indicates the token is invalid
	ErrInvalidToken = errors.New("invalid token")

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

	// ErrInvalidRefreshToken indicates the refresh token is invalid
	ErrInvalidRefreshToken = errors.New("invalid refresh token")

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

	// ErrInvalidScope indicates scope validation failed
	ErrInvalidScope = errors.New("invalid scope")
)
View Source
var ErrReservedClaimKey = errors.New("reserved claim key")

ErrReservedClaimKey is returned when caller-supplied extra claims attempt to set a reserved JWT/OIDC standard claim. The issuer owns these claims and callers must not provide them via extra_claims.

Functions

func BuildReservedClaimKeys added in v0.29.0

func BuildReservedClaimKeys(prefix string) map[string]struct{}

BuildReservedClaimKeys returns the set of JWT claim keys that callers must not supply via extra_claims for a deployment configured with the given private-claim prefix. It includes:

  • the static RFC/OIDC/AuthGate-internal keys (canonical list owned by internal/config to avoid drift between this package's runtime check and config's startup collision check),
  • the bare logical names from privateClaims (legacy-name impersonation guard — without it, callers could submit extra_claims={"domain":"evil"} and the bare claim would survive into the signed JWT),
  • the composed `<prefix>_<logical>` key for every entry in privateClaims,
  • the default-prefixed forms (extra_<logical>) ALWAYS, regardless of the configured prefix. Reserving the default forms universally blocks an impersonation vector during prefix transitions: a deployment running JWT_PRIVATE_CLAIM_PREFIX=acme would otherwise accept caller-supplied "extra_domain" and let it land in the signed JWT, fooling any un-migrated downstream consumer that still reads the default key.

Build once at parser construction time and reuse — the result is intended to be passed into ValidateExtraClaims rather than recomputed per request.

func ComputeAtHash added in v0.13.0

func ComputeAtHash(accessToken string) string

ComputeAtHash computes the at_hash claim value per OIDC Core 1.0 §3.3.2.11. at_hash = base64url( left-most 128 bits of SHA-256( ASCII(access_token) ) )

func DeriveKeyID added in v0.22.0

func DeriveKeyID(pub crypto.PublicKey) (string, error)

DeriveKeyID computes a deterministic kid from the SHA-256 hash of the DER-encoded public key (SPKI format). Returns a base64url-encoded string of the full 32-byte hash, suitable for JWKS key rotation.

func EmittedName added in v0.29.0

func EmittedName(prefix, logical string) string

EmittedName composes the JWT key written for a private claim: "<prefix>_<logical>". AuthGate adds the separating underscore itself; the configured prefix must therefore not have a trailing underscore (validated at startup in config.validateJWTPrivateClaimPrefix).

Centralizing composition here means every emission site, every reserved-key derivation, and every test reads the same source of truth — there is no place where someone could forget to add the underscore.

func LoadSigningKey added in v0.22.0

func LoadSigningKey(path string) (crypto.Signer, error)

LoadSigningKey reads a PEM file and returns the parsed private key. Supports RSA (PKCS#1 / PKCS#8) and ECDSA (SEC1 / PKCS#8).

func ParseSigningKey added in v0.28.0

func ParseSigningKey(data []byte) (crypto.Signer, error)

ParseSigningKey parses PEM-encoded data into a supported private key. Supports RSA (PKCS#1 / PKCS#8) and ECDSA (SEC1 / PKCS#8). All PEM blocks are tried in order until a supported key is found.

func ValidateExtraClaims added in v0.29.0

func ValidateExtraClaims(m map[string]any, reserved map[string]struct{}) error

ValidateExtraClaims rejects empty keys and any key in the supplied reserved set. Returns the first violation found; nil for an empty or nil claims map. The reserved set must be supplied by the caller (typically built once via BuildReservedClaimKeys at parser construction time) and must be non-nil — a nil reserved map would silently disable reserved-key enforcement because nil-map lookups always return ok=false. No additional key-format validation (length, character set, namespacing) is performed — callers that need stricter input rules must layer them on top.

Types

type IDTokenParams added in v0.13.0

type IDTokenParams = core.IDTokenParams

IDTokenParams holds all data needed to generate an OIDC ID Token (OIDC Core 1.0 §2). Re-exported from core as a type alias so existing callers (token.IDTokenParams{...}) compile unchanged while the canonical definition lives in core.

type IDTokenProvider added in v0.15.0

type IDTokenProvider = core.IDTokenProvider

IDTokenProvider is an optional capability of a TokenProvider. Currently, LocalTokenProvider is the only built-in production implementation. Re-exported from core for callers that import only the token package.

type LocalTokenProvider

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

LocalTokenProvider generates and validates JWT tokens locally

func NewLocalTokenProvider

func NewLocalTokenProvider(cfg *config.Config, opts ...Option) (*LocalTokenProvider, error)

NewLocalTokenProvider creates a new local token provider. By default it uses HS256. Use WithSigningKey and WithKeyID for asymmetric algorithms. Returns an error if the algorithm requires an asymmetric key but none was provided.

func (*LocalTokenProvider) Algorithm added in v0.22.0

func (p *LocalTokenProvider) Algorithm() string

Algorithm returns the JWT signing algorithm name (e.g. "HS256", "RS256", "ES256").

func (*LocalTokenProvider) GenerateClientCredentialsToken added in v0.12.0

func (p *LocalTokenProvider) GenerateClientCredentialsToken(
	ctx context.Context,
	userID, clientID, scopes string,
	ttl time.Duration,
	extraClaims map[string]any,
) (*Result, error)

GenerateClientCredentialsToken creates an access token for the client_credentials grant. If ttl > 0 it overrides the default CLIENT_CREDENTIALS_TOKEN_EXPIRATION. The userID field carries the synthetic machine identity "client:<clientID>".

func (*LocalTokenProvider) GenerateIDToken added in v0.13.0

func (p *LocalTokenProvider) GenerateIDToken(params IDTokenParams) (string, error)

GenerateIDToken creates a signed JWT ID Token for the given params. The signing algorithm and key are determined by the provider's configuration. ID tokens are not stored in the database; they are short-lived and non-revocable by design.

func (*LocalTokenProvider) GenerateRefreshToken

func (p *LocalTokenProvider) GenerateRefreshToken(
	ctx context.Context,
	userID, clientID, scopes string,
	ttl time.Duration,
	extraClaims map[string]any,
) (*Result, error)

GenerateRefreshToken creates a refresh token JWT. If ttl > 0 it overrides the default REFRESH_TOKEN_EXPIRATION.

func (*LocalTokenProvider) GenerateToken

func (p *LocalTokenProvider) GenerateToken(
	ctx context.Context,
	userID, clientID, scopes string,
	ttl time.Duration,
	extraClaims map[string]any,
) (*Result, error)

GenerateToken creates a JWT access token using local signing. If ttl > 0 it overrides p.config.JWTExpiration and no jitter is applied (the caller has chosen an explicit lifetime per client profile).

func (*LocalTokenProvider) KeyID added in v0.22.0

func (p *LocalTokenProvider) KeyID() string

KeyID returns the "kid" value used in JWT headers.

func (*LocalTokenProvider) Name

func (p *LocalTokenProvider) Name() string

Name returns provider name for logging

func (*LocalTokenProvider) ParseJWT added in v0.18.0

func (p *LocalTokenProvider) ParseJWT(tokenString string) (*ValidationResult, error)

ParseJWT parses a JWT token, verifies its signature, and extracts standard claims. It does not check the "type" claim — callers (ValidateToken, ValidateRefreshToken) add their own type-specific checks on top.

func (*LocalTokenProvider) PublicKey added in v0.22.0

func (p *LocalTokenProvider) PublicKey() crypto.PublicKey

PublicKey returns the asymmetric public verification key. Returns nil for HS256 (symmetric key).

func (*LocalTokenProvider) RefreshAccessToken

func (p *LocalTokenProvider) RefreshAccessToken(
	ctx context.Context,
	refreshToken string,
	accessTTL, refreshTTL time.Duration,
	extraClaims map[string]any,
) (*RefreshResult, error)

RefreshAccessToken generates new access token (and optionally new refresh token in rotation mode). accessTTL and refreshTTL override the default expirations when > 0, allowing the caller (TokenService) to apply the client's current TokenProfile at refresh time rather than reusing the TTL the original tokens were issued with.

extraClaims is also re-applied here, so callers (TokenService) can inject the client's CURRENT project / service_account at refresh time rather than freezing values from the original issuance.

func (*LocalTokenProvider) ValidateRefreshToken

func (p *LocalTokenProvider) ValidateRefreshToken(
	ctx context.Context,
	tokenString string,
) (*ValidationResult, error)

ValidateRefreshToken verifies a refresh token JWT

func (*LocalTokenProvider) ValidateToken

func (p *LocalTokenProvider) ValidateToken(
	ctx context.Context,
	tokenString string,
) (*ValidationResult, error)

ValidateToken verifies a JWT access token using local verification. It rejects refresh tokens (type=="refresh") at the JWT level.

type Option added in v0.22.0

type Option func(*LocalTokenProvider)

Option configures a LocalTokenProvider.

func WithKeyID added in v0.22.0

func WithKeyID(kid string) Option

WithKeyID sets the "kid" JWT header value.

func WithSigningKey added in v0.22.0

func WithSigningKey(privateKey crypto.Signer, publicKey crypto.PublicKey) Option

WithSigningKey sets the asymmetric signing and verification keys. Only *rsa.PrivateKey/*rsa.PublicKey (RS256) and *ecdsa.PrivateKey/*ecdsa.PublicKey (ES256) are supported; NewLocalTokenProvider validates concrete types and returns an error on mismatch.

type PrivateClaim added in v0.29.0

type PrivateClaim struct {
	// LogicalName is the stable identifier used internally and inside
	// EmittedName composition. It must NOT be changed without coordinating
	// with downstream consumers — the composed emitted key is part of the
	// public token contract.
	LogicalName string
}

PrivateClaim describes an AuthGate-emitted private JWT claim issued under the configurable prefix (JWT_PRIVATE_CLAIM_PREFIX). The emitted key is composed at runtime via EmittedName(prefix, LogicalName).

Trust levels differ across the registry:

  • `domain` is **server-attested**: sourced from the AuthGate process's JWT_DOMAIN configuration; cannot be set per-client or by a caller.
  • `uid` is **server-attested**: sourced from the User.Username row resolved at issuance/refresh time; cannot be set per-client or by a caller. Omitted when the issuance has no real user (client_credentials grant) or the user lookup fails. Reflects username-at-issuance — a subsequent admin rename surfaces on the next issuance/refresh.
  • `project` and `service_account` are **owner-set**: sourced from the OAuthApplication row (admin or client owner). A signed JWT only proves AuthGate emitted these values, not that the asserted project / service-account ownership has been independently verified.

Downstream gateways that route or authorize on these claims must verify the JWT signature AND apply their own access policies — never treat owner-set values as authoritative proof of identity. See docs/JWT_VERIFICATION.md for the full trust model.

func PrivateClaimRegistry added in v0.29.0

func PrivateClaimRegistry() []PrivateClaim

PrivateClaimRegistry returns a defensive copy of the AuthGate-emitted private-claim registry. Callers that need to iterate the registry from outside this package (tests, downstream tooling) must use this accessor; the underlying slice is intentionally unexported to prevent cross-package mutation.

type RefreshResult

type RefreshResult = core.TokenRefreshResult

RefreshResult is an alias for core.TokenRefreshResult.

type Result

type Result = core.TokenResult

Result is an alias for core.TokenResult. All existing callers using *token.Result continue to compile unchanged.

type ValidationResult

type ValidationResult = core.TokenValidationResult

ValidationResult is an alias for core.TokenValidationResult.

Jump to

Keyboard shortcuts

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