oidcverify

package
v0.10.1 Latest Latest
Warning

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

Go to latest
Published: Oct 24, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package oidcverify verifies tokens KySignOn issues: RS256 JWTs whose signing key is published at the issuer's JWKS endpoint. Five products parsed these with their own code, and at least one read the claims without checking the signature at all. One wrong check of alg, aud, iss, exp or kid accepts a token it should not, indistinguishable from a good one, so the check lives here once, on the standard library alone.

The algorithm is pinned to RS256 because that is what KySignOn signs with. A token whose header says anything else, including "none", is refused before any signature work.

Index

Constants

View Source
const MaxLogoutTokenAge = 5 * time.Minute

MaxLogoutTokenAge bounds logout-token freshness even if exp is far in the future. KySignOn issues a fresh token for each attempt with a two-minute expiration.

Variables

View Source
var (
	ErrMalformed      = errors.New("oidcverify: token is not a three-part JWT")
	ErrTokenType      = errors.New("oidcverify: token purpose does not match")
	ErrAlgorithm      = errors.New("oidcverify: token algorithm is not RS256")
	ErrUnknownKey     = errors.New("oidcverify: no JWKS key matches the token's kid")
	ErrSignature      = errors.New("oidcverify: signature does not verify")
	ErrIssuer         = errors.New("oidcverify: issuer does not match")
	ErrAudience       = errors.New("oidcverify: audience does not include this client")
	ErrExpired        = errors.New("oidcverify: token has expired")
	ErrNotYetValid    = errors.New("oidcverify: token is not yet valid")
	ErrIssuedInFuture = errors.New("oidcverify: token was issued in the future")
	ErrNoSubject      = errors.New("oidcverify: token has no subject")
	ErrNonce          = errors.New("oidcverify: nonce does not match")
	ErrJWKS           = errors.New("oidcverify: JWKS fetch failed")
)
View Source
var ErrInsecureIssuer = errors.New("oidcverify: issuer and JWKS URL must be https with a host")

ErrInsecureIssuer means the issuer or JWKS URL is not HTTPS. Key discovery over plaintext lets whoever answers the request decide which keys verify tokens.

View Source
var ErrLogoutClaims = errors.New("oidcverify: invalid logout claims")

ErrLogoutClaims means a signed token does not meet the KySignOn logout profile.

Functions

This section is empty.

Types

type Claims

type Claims struct {
	Issuer    string
	Subject   string
	Audience  []string
	ExpiresAt time.Time
	IssuedAt  time.Time
	NotBefore time.Time
	Nonce     string
	KeyID     string
	Raw       map[string]json.RawMessage
}

Claims are the standard claims every KySignOn token carries, plus the raw set for product-specific ones (role, groups, email).

func ClaimsFromContext

func ClaimsFromContext(ctx context.Context) (Claims, bool)

ClaimsFromContext returns the Claims Middleware stored.

func (Claims) String

func (c Claims) String(name string) string

String returns a string claim from Raw, or "".

type LogoutClaims

type LogoutClaims struct {
	Issuer      string
	Subject     string
	SessionID   string
	Audience    []string
	JWTID       string
	IssuedAt    time.Time
	ExpiresAt   time.Time
	ReplayUntil time.Time // last acceptance boundary, including clock-skew leeway
	KeyID       string
}

LogoutClaims identifies sessions to end, never an identity to authenticate. With a SessionID, match that issuer/client-scoped session and Subject when present. Without a SessionID, end all sessions for Issuer and Subject at this client. The receiver must atomically record (Issuer, JWTID) with session invalidation and retain it through ReplayUntil, including across restart. Verification is stateless.

type Verifier

type Verifier struct {
	Issuer   string
	Audience string
	// AllowMultipleAudiences accepts an aud array that names this client among others.
	// Off by default: a token minted for several clients is a token any of them can replay.
	AllowMultipleAudiences bool
	// JWKSURL defaults to Issuer + "/.well-known/jwks.json".
	JWKSURL string
	// HTTPClient defaults to a client with a ten-second timeout.
	HTTPClient *http.Client
	// Now defaults to time.Now.
	Now func() time.Time
	// Leeway is the clock-skew allowance for exp, nbf and iat.
	Leeway time.Duration
	// MinRefresh bounds how often an unknown kid may trigger a JWKS fetch. Default 30s.
	MinRefresh time.Duration
	// MaxAge is how long a fetched key set is trusted before a refresh. Default 1h.
	MaxAge time.Duration
	// contains filtered or unexported fields
}

Verifier checks tokens for one issuer and one audience. Zero Leeway means one minute.

func (*Verifier) Middleware

func (v *Verifier) Middleware(onReject func(r *http.Request, err error)) func(http.Handler) http.Handler

Middleware reads a bearer token, verifies it, and stores the Claims on the context. Every failure answers 401 with a fixed body; the reason goes only to onReject.

func (*Verifier) Verify

func (v *Verifier) Verify(ctx context.Context, token string) (Claims, error)

Verify checks an authentication token against the issuer's JWKS and standard claims. Logout and other security-event tokens are refused; use VerifyLogout for logout. An unknown kid triggers at most one rate-limited JWKS refresh.

func (*Verifier) VerifyLogout

func (v *Verifier) VerifyLogout(ctx context.Context, token string) (LogoutClaims, error)

VerifyLogout verifies an RS256 logout+jwt with issuer, audience, required iat/exp/jti, a sub or sid, the back-channel event object, and no nonce or token_use claim. It shares Verify's JWKS cache, refresh limits, clock and leeway. Tokens older than MaxLogoutTokenAge plus leeway are refused. It neither records replay IDs nor ends sessions; the receiver owns those durable operations and bounds its HTTP request.

func (*Verifier) VerifyWithNonce

func (v *Verifier) VerifyWithNonce(ctx context.Context, token, nonce string) (Claims, error)

VerifyWithNonce is Verify plus a nonce check, for ID tokens from the authorization-code flow. An empty nonce skips the check; a token carrying a nonce when none is expected is still accepted, since access tokens carry none.

Jump to

Keyboard shortcuts

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