theauth.Config.
OAuth login hardening
Config.OAuth (*OAuthConfig) is optional. The zero value keeps v2 behavior
except for the always-on protections below.
Always on:
- Browser-bound state.
/startsets an HttpOnlytheauth_oauth_statecookie holding a secret that is separate from thestatequery parameter. The server stores only its SHA-256 next to the flow record and compares it in constant time at/callback. A login CSRF (attacker’sstateplus code delivered to a victim’s browser) fails. The state is single use and is burned even when the binding check fails. - PKCE S256 on every authorization-code flow.
- OIDC nonce for providers implementing
theauth.NonceProvider(provider/oidcdoes). The nonce is checked against the verified ID token. - Verified email to link. A sign-in whose provider email matches an existing account is refused unless the provider marks the email verified. Provider emails are lower-cased and trimmed before lookup.
The default signup policy is open, matching v2, so upgrading never locks out
an existing deployment. Set
Signup explicitly for any internal tool.
Generic OIDC provider
oidc.New runs issuer discovery, requires an https issuer (set
AllowInsecureHTTP for local IdPs only), and verifies ID token signature
(JWKS with rotation), issuer, audience, expiry, azp and nonce.
Passkey policy
WebAuthnConfig gained:
RequireUserVerification: registration and login demand UV, so a passkey is never a bare possession factor. Default false.CloneWarning:CloneWarningReject(default, refuses the login) orCloneWarningFlag(allows it and emitspasskey.clone_warning).
WebAuthnConfig; the request Host
and forwarded headers are never consulted.
New endpoints: PATCH /auth/webauthn/credentials/{id} (body
{"name": "..."}, needs WebAuthnRenameStorage), GET /auth/totp (status),
POST /auth/totp/recovery-codes (regenerate, needs RecoveryCodeStorage).
Memory, Postgres and MySQL implement both capabilities; other stores answer
501 on the rename and regenerate routes.
Auth event stream
SetConfig.AuthEventSink to receive a PII-minimal AuthEvent for each
security event, independent of Config.Audit:
login.success, login.failure, mfa.success, mfa.failure,
password.changed, password.reset_requested, password.reset_completed,
passkey.added, passkey.removed, passkey.renamed, passkey.clone_warning,
totp.enrolled, totp.disabled, totp.recovery_codes_regenerated,
session.revoked, token.minted, token.revoked, oauth.linked.
Token issuers call (*TheAuth).RecordTokenMinted and RecordTokenRevoked
to feed the stream. The same events also reach the audit log when
Config.Audit is set (actions login.failed, mfa.verified, mfa.failed,
passkey.renamed, passkey.clone_warning, totp.recovery_regenerated,
token.minted, token.revoked are new).