verify

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Sep 30, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package verify verifies AuthKit tokens without a database: access tokens and delegated access tokens of the issuers a Verifier trusts, checked against their keys (a JWKS, static keys or a live key source). It also holds the claims, actor and context helpers and the net/http middleware, which authenticate through a *Verifier or an *authkit.Client (which adds API keys and remote applications from its database).

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrSenderProofRequired refuses a bound token presented without its
	// proof: no TLS peer or another leaf, no or an invalid DPoP proof, or a
	// token verified detached from its request.
	ErrSenderProofRequired iam.Error = errmodel.E(errmodel.CodeSenderProofRequired)

	// ErrSenderProofUnavailable is a DPoP replay store failure: the request
	// is refused, not proven invalid.
	ErrSenderProofUnavailable = errors.New("sender proof replay protection unavailable")
	// ErrInvalidConfirmation refuses a cnf claim that is not exactly one
	// x5t#S256 or jkt thumbprint.
	ErrInvalidConfirmation iam.Error = errmodel.E(errmodel.CodeInvalidConfirmation)
	// ErrConfirmationWrongTokenType refuses cnf on a token type AuthKit does
	// not bind: an unenforced binding would be a silent downgrade.
	ErrConfirmationWrongTokenType iam.Error = errmodel.E(errmodel.CodeConfirmationWrongTokenType)
)

Sender-proof errors: RFC 8705 certificate-bound and RFC 9449 DPoP-bound delegated tokens.

Functions

func ActorFromClaims added in v0.147.0

func ActorFromClaims(c Claims) (iam.Actor, bool)

ActorFromClaims derives the actor verified claims act as. It is pure and never yields the system. ok is false for claims that carry no AuthKit authority: another issuer's user, a 2FA-enrollment-only token, or an unrecognized shape. A user or AuthKit-minted delegated actor is bound to the session or device key its token was minted from (iam.Actor.InSession), so every permission check refuses it once that sign-in is revoked.

func ActorFromContext added in v0.147.0

func ActorFromContext(ctx context.Context) (iam.Actor, bool)

ActorFromContext is the actor the claims the middleware stored in ctx act as (ActorFromClaims), resolved once when they were stored.

func AuthenticateRequest added in v0.147.0

func AuthenticateRequest(ctx context.Context, a Authenticator, r *http.Request) (auth.Principal, error)

AuthenticateRequest verifies r through a and returns its helpers/auth principal, for code written against helpers/auth providers. When a is a PermissionChecker (*authkit.Client), the principal's Can checks the credential's permissions live, the session included; otherwise it is identity only.

func IdentityFromContext added in v0.147.0

func IdentityFromContext(ctx context.Context) (auth.Identity, bool)

IdentityFromContext is the verified caller's provider-neutral identity.

func Optional

func Optional(a Authenticator) func(http.Handler) http.Handler

Optional is Required when the request carries an Authorization header and passes it through anonymously otherwise. A present but invalid credential is refused.

func PrincipalFromClaims added in v0.147.0

func PrincipalFromClaims(a Authenticator, cl Claims) (auth.Principal, error)

PrincipalFromClaims hands claims a trusted middleware verified for this same request to helpers/auth code without verifying again, which would spend a single-use sender proof twice. Never pass claims from anywhere else. See AuthenticateRequest for Can.

func RequirePermission added in v0.65.0

func RequirePermission(a Authority, perm iam.Perm) func(http.Handler) http.Handler

RequirePermission authenticates the request (it includes Required) and requires perm, checked live, in the group attached to the request (WithGroup, or an adapter's SetGroup). The check includes the token's session: once it is revoked the request is 401 session_revoked. A request with no group fails closed: 500 internal_error, logged with its route. It panics at construction on a perm a does not register.

func RequirePermissionOn added in v0.147.0

func RequirePermissionOn(a Authority, ref iam.GroupRef, perm iam.Perm) func(http.Handler) http.Handler

RequirePermissionOn is RequirePermission in one fixed group, such as iam.RootGroup().

func RequireSession added in v0.147.0

func RequireSession(a Authority) func(http.Handler) http.Handler

RequireSession is Required plus the session check: the session or device key the token was minted from is still active (not logged out, revoked, banned or deleted), or the request is 401 session_revoked. A user's token passes, and so does a delegated token AuthKit minted from a sign-in, while that sign-in stands; any other credential is 403 forbidden.

func Required

func Required(a Authenticator) func(http.Handler) http.Handler

Required authenticates every request through a, storing its claims and actor in the request context, and answers 401 otherwise. It is stateless: a token outlives its revoked session until it expires. The live gates (RequireSession, RequirePermission, Sensitive) include it.

Stacked gates over the same a verify a request once: the first stores the claims and the later ones reuse them, so a DPoP proof is spent and an API key looked up once. Claims another authenticator verified, or verified for another credential, or stored by SetClaims are verified again.

func Sensitive added in v0.54.0

func Sensitive(a Authority) func(http.Handler) http.Handler

Sensitive is RequireSession plus a recent sign-in of the user's own token: within the last 15 minutes, with the second factor when the account has one. A stale sign-in answers 403 step_up_required with the account's step-up methods, which auth-ui handles; a delegated token, which carries no sign-in of its own, is 403 forbidden. Stack it after RequirePermission when a route needs both.

func SetClaims

func SetClaims(ctx context.Context, cl Claims) context.Context

SetClaims stores cl in ctx for the handlers. The gates never trust claims stored this way: they verify the request themselves.

func WithGroup added in v0.147.0

func WithGroup(ctx context.Context, ref iam.GroupRef) context.Context

WithGroup attaches the permission group a request acts in, for RequirePermission: the route's loader sets it once it has resolved the URL to its entity (a channel's group).

Types

type Authenticator added in v0.147.0

type Authenticator interface {
	VerifyRequest(r *http.Request) (Claims, error)
}

Authenticator authenticates requests: a *Verifier, or an *authkit.Client, which also accepts its API keys and its remote applications' tokens.

type Authority added in v0.147.0

type Authority interface {
	Authenticator
	PermissionChecker
	SessionChecker
}

Authority authenticates requests and checks sessions and permissions live: what the live gates need. *authkit.Client is one.

type Claims

type Claims struct {
	// Kind is the credential class: iam.ActorUser or iam.ActorDelegated for a
	// token, and from *authkit.Client also iam.ActorAPIKey and
	// iam.ActorRemoteApplication.
	Kind iam.ActorKind
	// JOSEType is the token's typ header ("access+jwt",
	// "delegated-access+jwt", "remote-application-access+jwt"); empty for an
	// API key.
	JOSEType string
	// Issuer is the validated iss.
	Issuer string

	// UserID is a local user: set only for an issuer registered IsLocal.
	UserID string
	// Subject is another issuer's user. It is meaningful only with Issuer and
	// never names a local user.
	Subject string
	// DelegatedSubject is a delegated token's delegated_sub, whose authority
	// is Permissions: the user who minted a token of this deployment, else an
	// external actor. It never sets UserID.
	DelegatedSubject string
	// SessionID (sid) or DeviceKeyID names the sign-in a native token, or a
	// delegated token AuthKit minted from one, was minted from; the session
	// check refuses the token once it is revoked.
	SessionID   string
	DeviceKeyID string
	// APIKeyID is the key an API-key credential resolved to.
	APIKeyID string
	// RemoteApplicationID is the stored application behind a remote
	// application token or its delegation, resolved from the validated iss.
	RemoteApplicationID string
	// Group binds a machine credential's authority to the group it was
	// granted in: set for API keys, remote applications and their
	// delegations; nil otherwise.
	Group *PermissionScope

	// Permissions are the credential's permission strings: an API key's or
	// application's stored grants, or a delegated token's grant (bounded by
	// the application's stored ceiling when an application issued it). Native
	// user tokens carry none; their authority is read live (Can).
	Permissions []string
	// Attributes is the attributes claim, each value raw JSON for the
	// consuming service to decode; AuthKit assigns no key a meaning.
	Attributes map[string]json.RawMessage
	// Entitlements is the issuer's token-time entitlements snapshot.
	Entitlements []string
	// RootRole is the user's root-group role at mint ("root:admin"), for
	// display only: UI and content visibility without a database call. It is
	// stale up to the token lifetime and never authorizes anything; every
	// permission check reads the role live.
	RootRole string

	Email         string
	EmailVerified bool
	Username      string

	// AMR, ACR and AuthTime describe the sign-in the token carries.
	AMR      []string
	ACR      string
	AuthTime time.Time
	// TwoFAEnrollment marks a token that reaches only AuthKit's 2FA
	// enrollment routes; every verifier refuses it elsewhere.
	TwoFAEnrollment bool
	// MFAEnrolled is whether the user had a usable second factor at mint.
	MFAEnrolled bool
	JTI         string

	// CertificateThumbprint (cnf x5t#S256) or JWKThumbprint (cnf jkt) is a
	// delegated token's sender binding, already matched against this
	// request's TLS peer certificate or DPoP proof; empty for a bearer token.
	CertificateThumbprint string
	JWKThumbprint         string
}

Claims is a verified credential: what the middleware stores in the request context. Kind says which fields apply.

func ClaimsFromContext

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

ClaimsFromContext is the claims the middleware stored in ctx.

func (Claims) HasAMR added in v0.52.0

func (c Claims) HasAMR(m string) bool

HasAMR reports whether the sign-in used authentication method m.

func (Claims) HasEntitlement

func (c Claims) HasEntitlement(ent string) bool

HasEntitlement reports whether the claims carry entitlement ent.

func (Claims) HasPermission

func (c Claims) HasPermission(perm iam.Perm) bool

HasPermission reports whether the claims carry a permission covering perm.

func (Claims) Identity added in v0.147.0

func (c Claims) Identity() (auth.Identity, bool)

Identity is the claims' provider-neutral identity (helpers/auth); ok is false when they name no subject under an issuer.

func (Claims) IsUser added in v0.72.0

func (c Claims) IsUser() bool

IsUser reports whether the claims are a local user's.

type IssuerKeyStatus added in v0.143.0

type IssuerKeyStatus = jwks.Status

IssuerKeyStatus is one JWKS issuer's key-refresh state: key count, freshness, the age of the last successful fetch against MaxStale, and the last error.

type IssuerOptions

type IssuerOptions struct {
	// JWKSURI is fetched on first use and refreshed in the background when
	// its keys expire or an unknown kid arrives. Expired keys keep verifying
	// while refreshes fail, up to MaxStale.
	JWKSURI string
	// Keys are static PEM public keys, each with its kid. Replace them by
	// calling AddIssuer again.
	Keys []iam.RemoteApplicationKey
	// KeySource is read live on every verification: a co-located, rotating
	// key source such as AuthKit's own.
	KeySource keys.Source

	// CacheTTL is how long fetched JWKS keys are fresh (default 10m).
	CacheTTL time.Duration
	// MaxStale bounds how long after the last successful fetch JWKS keys
	// keep verifying while refreshes fail, so a peer's key revocation cannot
	// be suppressed by blocking the fetch. Past it the issuer's tokens fail
	// with 503 issuer_keys_unavailable. Default 4h; never below CacheTTL.
	MaxStale time.Duration

	// IsLocal marks the issuer whose users are this host's own: only its
	// access tokens set Claims.UserID (others set Subject).
	IsLocal bool
}

IssuerOptions is where an issuer's keys come from: exactly one of JWKSURI, Keys and KeySource.

type PermissionChecker added in v0.65.0

type PermissionChecker interface {
	Can(ctx context.Context, a iam.Actor, ref iam.GroupRef, perm iam.Perm) (bool, error)
	// KnownPermission reports whether perm is registered.
	KnownPermission(perm iam.Perm) bool
}

PermissionChecker checks an actor's authority in a group live; *authkit.Client is one. Can is false for an unknown group or an actor bound to another group, iam.ErrSessionRevoked once the actor's session is revoked, and iam.ErrUnknownPermission for an unregistered perm.

type PermissionScope added in v0.65.0

type PermissionScope struct {
	GroupID         string
	AuthorityIssuer string
	Persona         iam.Persona
}

PermissionScope is a credential's group binding: the group, the issuer whose group it is, and the group's persona.

type ServiceJWTVerifyOption

type ServiceJWTVerifyOption func(*serviceJWTConfig)

ServiceJWTVerifyOption configures VerifyServiceJWT.

func WithServiceJWTMaxLifetime

func WithServiceJWTMaxLifetime(d time.Duration) ServiceJWTVerifyOption

WithServiceJWTMaxLifetime caps the accepted lifetime (default 15m).

type SessionChecker added in v0.147.0

type SessionChecker interface {
	// CheckSession: the session or device key the token was minted from is
	// still active. A user's token carries one, and so does a delegated
	// token AuthKit minted from it.
	CheckSession(ctx context.Context, cl Claims) error
	// CheckRecentSignIn: CheckSession, and the user's own token, signed in
	// recently enough for a sensitive action, with the second factor when
	// the account has one.
	CheckRecentSignIn(ctx context.Context, cl Claims) error
}

SessionChecker checks the sign-in behind verified claims live; *authkit.Client is one. Both return nil or the error to answer: iam.ErrSessionRevoked, forbidden for a credential that carries no sign-in, or (CheckRecentSignIn) step_up_required carrying the step-up methods.

type Verifier

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

Verifier verifies tokens from the issuers added with AddIssuer.

func NewVerifier

func NewVerifier(opts ...VerifierOption) *Verifier

NewVerifier returns a Verifier that trusts no issuer until AddIssuer.

func (*Verifier) AddIssuer

func (v *Verifier) AddIssuer(issuerID string, audiences []string, opts IssuerOptions) error

AddIssuer trusts issuerID's tokens for any of audiences, replacing an earlier registration of it. A failure leaves the earlier one in place.

func (*Verifier) AuthenticateRequest added in v0.126.0

func (v *Verifier) AuthenticateRequest(ctx context.Context, r *http.Request) (auth.Principal, error)

AuthenticateRequest verifies r and returns its helpers/auth principal, identity only: a Verifier checks no permissions.

func (*Verifier) CheckIssuerKeys added in v0.143.0

func (v *Verifier) CheckIssuerKeys(context.Context) error

CheckIssuerKeys is a no-I/O health probe: it fails naming every JWKS issuer whose last key fetch failed, with the age of its keys and whether they are past MaxStale (its tokens then fail closed). Other issuers are unaffected.

func (*Verifier) IssuerKeyStatuses added in v0.143.0

func (v *Verifier) IssuerKeyStatuses() []IssuerKeyStatus

IssuerKeyStatuses reports every JWKS issuer's key state, sorted by issuer.

func (*Verifier) RemoveIssuer

func (v *Verifier) RemoveIssuer(issuerID string)

RemoveIssuer stops trusting issuerID's tokens and drops its cached keys.

func (*Verifier) Verify

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

Verify verifies an access token or a delegated access token detached from any request, so a sender-bound delegated token fails with ErrSenderProofRequired (use VerifyRequest). ctx bounds the key fetches.

func (*Verifier) VerifyClaims

func (v *Verifier) VerifyClaims(ctx context.Context, token string) (map[string]any, error)

VerifyClaims verifies a token's signature, issuer, audience and times and returns its raw claims, for host-defined token profiles: it enforces no AuthKit token type, subject, permission or sender binding. Use Verify or VerifyRequest for AuthKit tokens.

func (*Verifier) VerifyDelegatedAccess

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

VerifyDelegatedAccess is Verify accepting only a delegated access token.

func (*Verifier) VerifyDelegatedAccessRequest added in v0.98.0

func (v *Verifier) VerifyDelegatedAccessRequest(r *http.Request) (Claims, error)

VerifyDelegatedAccessRequest is VerifyRequest accepting only a delegated access token.

func (*Verifier) VerifyRequest added in v0.65.0

func (v *Verifier) VerifyRequest(r *http.Request) (Claims, error)

VerifyRequest verifies the request's bearer (or DPoP) token, its sender proof included. It is stateless: a token outlives its revoked session until it expires; RequireSession, RequirePermission and Sensitive check the session live (through *authkit.Client).

func (*Verifier) VerifyServiceJWT

func (v *Verifier) VerifyServiceJWT(ctx context.Context, token string, opts ...ServiceJWTVerifyOption) (iam.ServiceJWTClaims, error)

VerifyServiceJWT verifies a service JWT (token_use=service) of a trusted issuer and returns its claims. It grants nothing: the host intersects the requested permissions with its own grants for the issuer and subject.

type VerifierOption

type VerifierOption func(*verifierConfig)

VerifierOption configures a Verifier.

func WithDPoP added in v0.101.0

func WithDPoP(replay func(ctx context.Context, key string, ttl time.Duration) (bool, error)) VerifierOption

WithDPoP accepts RFC 9449 DPoP-bound delegated tokens, with WithPublicURL. replay is the proof replay store: it atomically claims key until ttl and returns true only for the first claim; every replica must share it, and its errors fail closed. Client.NewVerifier wires AuthKit's own.

func WithHTTPClient

func WithHTTPClient(client *http.Client) VerifierOption

WithHTTPClient sets the client JWKS are fetched with (default: a timeout-bounded client).

func WithPublicURL added in v0.149.0

func WithPublicURL(url string) VerifierOption

WithPublicURL is where clients reach the paths this verifier sees: "https://api.example.com", or "https://example.com/api" when a proxy in front strips /api. A DPoP proof must name it plus the request's path, the rule HTTPConfig.PublicURL sets for AuthKit's own routes. No Host or Forwarded header is consulted.

func WithSkew

func WithSkew(d time.Duration) VerifierOption

WithSkew sets the clock skew allowed on exp, nbf and iat (default 60s).

Jump to

Keyboard shortcuts

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