Documentation
¶
Overview ¶
Package issuer verifies tokens from a trusted external issuer, so a platform that already authenticates its users can open a Dexaflow UI session for them without holding Dexaflow's own signing secret (#1284).
The issuer signs with its own key and publishes it as a JWKS; Dexaflow only ever reads public keys. A verified token names an existing user (by the issuer's subject) in an allowed tenant. It never creates users and never grants roles: roles stay whatever the user row holds.
Index ¶
Constants ¶
const DefaultBearerMaxLifetime = 15 * time.Minute
DefaultBearerMaxLifetime bounds exp - iat of a bearer when Config.BearerMaxLifetime is zero. A bearer is reused until it expires and cannot be revoked before then, so it is kept short; the user it names is still reloaded on every request.
const DefaultMaxLifetime = 2 * time.Minute
DefaultMaxLifetime bounds exp - iat when Config.MaxLifetime is zero. A handoff is posted the moment it is minted, so two minutes is generous.
const KeyRefreshCooldown = 30 * time.Second
KeyRefreshCooldown is the least time between two downloads of the issuer's JWKS. A token whose key is not cached triggers a download, and anyone can mint such a token, so without a floor every forged request would cost an outbound call to the issuer. A real key rotation is picked up at most this long after the previous download.
Variables ¶
var ( // ErrInvalidToken covers a bad signature, issuer, audience, expiry or a // missing subject or jti: the token is not one the trusted issuer made for // us. ErrInvalidToken = errors.New("issuer: invalid token") // ErrLifetime is a token without iat, one valid for longer than // MaxLifetime, or one issued in the future. A handoff token is meant to be // used once, right away; a long or post-dated one is a long replay window. ErrLifetime = errors.New("issuer: token lifetime missing or too long") // ErrTenantNotAllowed is a tenant claim that is absent, not a string, or // not in AllowedTenants. ErrTenantNotAllowed = errors.New("issuer: tenant not allowed") // ErrReplayed is a token whose jti this server already accepted. A handoff // token opens one session; a second post of the same token is a replay. ErrReplayed = errors.New("issuer: token already used") )
Verification failures. Each is fail-closed; callers log the class and show the browser nothing more specific than "not signed in".
var ErrBearerDisabled = errors.New("issuer: bearer tokens are not enabled")
ErrBearerDisabled is a bearer presented while Config.BearerAudiences is empty: the operator has not turned the bearer mode on.
ErrKeysUnavailable is a token that could not be checked because the issuer's JWKS could not be downloaded. It says nothing about the token, so the API answers 503 rather than "sign in again".
Functions ¶
func MarkKeyOutage ¶ added in v0.5.5
MarkKeyOutage records on a context from TrackKeyOutage that the keys could not be obtained, for a key set that finds its keys some other way first (an OpenID discovery document, say).
func NewKeySet ¶ added in v0.5.5
NewKeySet returns the JWKS published at url as a go-oidc key set, with the cache, the refresh cooldown and the size and time bounds the trusted issuer uses. It makes no network call until a signature is checked. Only algs are accepted. The CI OIDC issuers (ADR 0092) share it.
func TrackKeyOutage ¶ added in v0.5.5
TrackKeyOutage returns a context to verify a token with, and a function that reports, after the verification, whether it failed because the keys could not be downloaded rather than because the token is bad.
Types ¶
type Config ¶
type Config struct {
// Name identifies the issuer inside Dexaflow. Its users are linked by
// (Provider(), subject), so it must stay stable once users exist.
Name string
// Issuer is the exact `iss` the tokens carry.
Issuer string
// JWKSURL is where the issuer publishes its public signing keys.
JWKSURL string
// Audience is the `aud` the tokens must carry for this Dexaflow.
Audience string
// TenantClaim names the string claim carrying the Dexaflow tenant name.
TenantClaim string
// AllowedTenants lists the tenants this issuer may sign in to; "*" allows
// every tenant.
AllowedTenants []string
// MaxLifetime caps exp - iat; zero means DefaultMaxLifetime.
MaxLifetime time.Duration
// BearerAudiences are the `aud` values of tokens accepted as a bearer on
// every request (VerifyBearer). Empty turns the bearer mode off. They must
// differ from Audience, so a handoff token is never a bearer.
BearerAudiences []string
// BearerMaxLifetime caps exp - iat of a bearer; zero means
// DefaultBearerMaxLifetime.
BearerMaxLifetime time.Duration
// DeployAudience is the `aud` of the bearers that may deploy when the
// operator makes the issuer the only way to deploy (#1773). It is a
// bearer audience of its own, accepted even when BearerAudiences is
// empty, and VerifyBearer marks a token whose aud is it alone
// (Identity.DeployAudience).
// Empty means no deploy audience.
DeployAudience string
}
Config is one trusted issuer.
type Identity ¶
type Identity struct {
Subject string
Email string
Tenant string
// Scopes are a bearer token's OAuth scopes (ADR 0067); nil for a handoff
// token, whose session is not scoped.
Scopes []string
// DeployAudience is true for a bearer whose `aud` is Config.DeployAudience
// alone (#1773); a token that also names another audience is not one. It says where the token was minted for,
// not what it may do: its scopes still decide that.
DeployAudience bool
}
Identity is what a verified token says about the user.
type Verifier ¶
type Verifier struct {
// contains filtered or unexported fields
}
Verifier checks tokens against one trusted issuer.
func New ¶
New builds a Verifier. It makes no network call: the JWKS is fetched on the first Verify and cached, refreshed when a token names an unknown key id (at most once per KeyRefreshCooldown), so key rotation needs no restart and an issuer outage cannot block boot. The handoff and the bearer share the cache.
func (*Verifier) BearerEnabled ¶ added in v0.5.3
BearerEnabled reports whether any bearer audience, the deploy audience included, is configured.
func (*Verifier) Provider ¶
Provider is the key this issuer's users are linked under (the users table's oidc_provider). The "issuer:" prefix keeps it apart from OIDC provider names.
func (*Verifier) VerifyBearer ¶ added in v0.5.3
VerifyBearer checks a token sent as a bearer on an API request, the way a remote MCP client sends one on every call (ADR 0050 D9). It applies the handoff's checks (signature, issuer, expiry, subject, bounded lifetime, allowed tenant) with two differences: the audience must be one of BearerAudiences or the DeployAudience and never the handoff Audience, and there is no one-use rule, because the same token authenticates every request until it expires.