Documentation
¶
Index ¶
- Constants
- func AllowNamed(r *http.Request, rl RateLimiter, bucket string) bool
- func CheckTenantAccess(ctx context.Context, svc *core.Service, userID, tenantSlug string) (canonicalTenant string, memberRoles []string, isMember bool, err error)
- func DefaultRateLimits() map[string]Limit
- func HasAnyTenantRole(roles []string, want ...string) bool
- func HasRoleDBCheck(ctx context.Context, pg *pgxpool.Pool, userID, role string) (bool, error)
- func HasRoleDBCheckInSchema(ctx context.Context, pg *pgxpool.Pool, schema, userID, role string) (bool, error)
- func IsAdmin(ctx context.Context, pg *pgxpool.Pool, userID string) (bool, error)
- func IsAdminInSchema(ctx context.Context, pg *pgxpool.Pool, schema, userID string) (bool, error)
- func JWKSHandler(jwks jwtkit.JWKS) http.Handler
- func LanguageMiddleware(cfg *LanguageConfig) func(http.Handler) http.Handler
- func MintDelegatedAccessToken(ctx context.Context, signer jwtkit.Signer, p DelegatedAccessParams) (string, error)
- func Optional(v *Verifier) func(http.Handler) http.Handler
- func RequireAdmin(pg *pgxpool.Pool) func(http.Handler) http.Handler
- func RequireAdminInSchema(pg *pgxpool.Pool, schema string) func(http.Handler) http.Handler
- func RequireAnyEntitlement(ents ...string) func(http.Handler) http.Handler
- func RequireEntitlement(ent string) func(http.Handler) http.Handler
- func Required(v *Verifier) func(http.Handler) http.Handler
- func RequiredServiceJWT(v *Verifier, opts ...ServiceJWTVerifyOption) func(http.Handler) http.Handler
- func ToMemoryLimits(in map[string]Limit) map[string]memorylimiter.Limit
- func ToRedisLimits(in map[string]Limit) map[string]redislimiter.Limit
- type ActionAvailability
- type AttributeDefResolver
- type AttributesValidator
- type Claims
- func (c Claims) Attribute(key string) (json.RawMessage, bool)
- func (c Claims) AttributeIsReference(key string) bool
- func (c Claims) AttributeReference(key string) (ref string, ok bool)
- func (c Claims) Delegated() (DelegatedPrincipal, bool)
- func (c Claims) DelegatedAccess() (DelegatedPrincipal, bool)
- func (c Claims) HasEntitlement(ent string) bool
- func (c Claims) HasPermission(perm string) bool
- func (c Claims) HasRole(role string) bool
- func (c Claims) IsDelegated() bool
- func (c Claims) IsDelegatedAccessToken() bool
- func (c Claims) IsRemoteApplication() bool
- func (c Claims) IsService() bool
- type ClientIPFunc
- type DelegatedAccessParams
- type DelegatedPrincipal
- type InternalErrorEvent
- type IssuerKey
- type IssuerOptions
- type LanguageConfig
- type Limit
- type PermissionValidator
- type RateLimitResult
- type RateLimiter
- type RateLimiterWithResult
- type RateLimiterWithRetryAfter
- type RemoteApplicationAuthoritySource
- type RemoteApplicationSource
- type RouteGroup
- type RouteSpec
- type Routes
- type Service
- func (s *Service) APIHandler() http.Handler
- func (s *Service) APIRoutes(groups ...RouteGroup) []RouteSpec
- func (s *Service) CheckSMSHealth(ctx context.Context) error
- func (s *Service) Core() *core.Service
- func (s *Service) DisableRateLimiter() *Service
- func (s *Service) JWKSHandler() http.Handler
- func (s *Service) OIDCBrowserRoutes(groups ...RouteGroup) []RouteSpec
- func (s *Service) OIDCHandler() http.Handler
- func (s *Service) Routes() Routes
- func (s *Service) SMSAvailable() bool
- func (s *Service) SMSHealthReason() string
- func (s *Service) SMSHealthy() bool
- func (s *Service) Verifier() *Verifier
- func (s *Service) WithAuthLogReader(r core.AuthEventLogReader) *Service
- func (s *Service) WithAuthLogger(l core.AuthEventLogger) *Service
- func (s *Service) WithClientIPFunc(fn ClientIPFunc) *Service
- func (s *Service) WithEmailSender(es core.EmailSender) *Service
- func (s *Service) WithEntitlements(p core.EntitlementsProvider) *Service
- func (s *Service) WithEphemeralStore(store core.EphemeralStore, mode core.EphemeralMode) *Service
- func (s *Service) WithErrorLogger(fn func(context.Context, InternalErrorEvent)) *Service
- func (s *Service) WithLanguageConfig(cfg LanguageConfig) *Service
- func (s *Service) WithPostgres(pg *pgxpool.Pool) *Service
- func (s *Service) WithRateLimiter(rl RateLimiter) *Service
- func (s *Service) WithRedis(rd *redis.Client) *Service
- func (s *Service) WithSMSSender(sender core.SMSSender) *Service
- func (s *Service) WithSolanaDomain(domain string) *Service
- type ServiceJWTPrincipal
- type ServiceJWTReplayChecker
- type ServiceJWTVerifyOption
- type TenantIssuersClient
- type TenantIssuersClientOption
- type TenantIssuersRegistration
- type Verifier
- func (v *Verifier) AddIssuer(issuerID string, audiences []string, opts IssuerOptions) error
- func (v *Verifier) LoadRemoteApplications(ctx context.Context, src RemoteApplicationSource, audiences []string) error
- func (v *Verifier) RemoveIssuer(issuerID string)
- func (v *Verifier) Verify(tokenStr string) (Claims, error)
- func (v *Verifier) VerifyClaims(tokenStr string) (jwt.MapClaims, error)
- func (v *Verifier) VerifyDelegatedAccess(tokenStr string) (Claims, DelegatedPrincipal, error)
- func (v *Verifier) VerifyServiceJWT(ctx context.Context, tokenStr string, opts ...ServiceJWTVerifyOption) (core.ServiceJWTClaims, ServiceJWTPrincipal, error)
- func (v *Verifier) WithService(svc *core.Service) *Verifier
- type VerifierOption
- func WithAlgorithms(algs ...string) VerifierOption
- func WithAttributeHydration(resolver AttributeDefResolver) VerifierOption
- func WithAttributesPolicy(fn AttributesValidator) VerifierOption
- func WithHTTPClient(c *http.Client) VerifierOption
- func WithPermissionCatalog(fn PermissionValidator) VerifierOption
- func WithServiceTokenPrefix(prefix string) VerifierOption
- func WithSkew(d time.Duration) VerifierOption
- func WithTenantMode(string) VerifierOptiondeprecated
Constants ¶
const ( ActionUpdateUsername = "update_username" ActionRequestPasswordReset = "request_password_reset" ActionRequestEmailVerification = "request_email_verification" ActionRequestPhoneVerification = "request_phone_verification" )
const ( // 2FA-specific rate limit buckets RL2FAStartPhone = "auth_2fa_start_phone" RL2FAEnable = "auth_2fa_enable" RL2FADisable = "auth_2fa_disable" RL2FARegenerateCodes = "auth_2fa_regenerate_codes" RL2FAVerify = "auth_2fa_verify" RLAuthToken = "auth_token" RLAuthRegister = "auth_register" RLAuthRegisterAvailability = "auth_register_availability" RLAuthRegisterResendEmail = "auth_register_resend_email" RLAuthRegisterResendPhone = "auth_register_resend_phone" RLAuthRegisterAbandon = "auth_register_abandon" RLPasswordLogin = "auth_password_login" RLAuthLogout = "auth_logout" RLAuthSessionsCurrent = "auth_sessions_current" RLAuthSessionsList = "auth_sessions_list" RLAuthSessionsRevoke = "auth_sessions_revoke" RLAuthSessionsRevokeAll = "auth_sessions_revoke_all" RLPasswordResetRequest = "auth_pwd_reset_request" RLPasswordResetConfirm = "auth_pwd_reset_confirm" RLEmailVerifyRequest = "auth_email_verify_request" RLEmailVerifyConfirm = "auth_email_verify_confirm" RLPhoneVerifyRequest = "auth_phone_verify_request" RLPhoneVerifyConfirm = "auth_phone_verify_confirm" RLOIDCStart = "auth_oidc_start" RLOIDCCallback = "auth_oidc_callback" RLUserPasswordChange = "auth_user_password_change" RLUserMe = "auth_user_me" RLUserUpdateUsername = "auth_user_update_username" RLUserPreferredLocale = "auth_user_preferred_locale" RLUserUpdateEmail = "auth_user_update_email" RLUserEmailChangeRequest = "auth_user_email_change_request" RLUserEmailChangeConfirm = "auth_user_email_change_confirm" RLUserEmailChangeResend = "auth_user_email_change_resend" RLUserEmailChangeCancel = "auth_user_email_change_cancel" RLUserPhoneChangeRequest = "auth_user_phone_change_request" RLUserPhoneChangeConfirm = "auth_user_phone_change_confirm" RLUserPhoneChangeResend = "auth_user_phone_change_resend" RLUserPhoneChangeCancel = "auth_user_phone_change_cancel" RLUserDelete = "auth_user_delete" RLUserUnlinkProvider = "auth_user_unlink_provider" RLAdminRolesGrant = "auth_admin_roles_grant" RLAdminRolesRevoke = "auth_admin_roles_revoke" RLAdminUserSessionsList = "auth_admin_user_sessions_list" RLAdminUserSessionsRevoke = "auth_admin_user_sessions_revoke" RLAdminUserSessionsRevokeAll = "auth_admin_user_sessions_revoke_all" RLAdminPasswordReset = "auth_admin_password_reset" // Solana SIWS authentication RLSolanaChallenge = "auth_solana_challenge" RLSolanaLogin = "auth_solana_login" RLSolanaLink = "auth_solana_link" )
Bucket names used by authkit endpoints.
const AccessTokenType = jwtkit.AccessTokenType
AccessTokenType is the canonical JOSE `typ` header value for an AuthKit service token.
const DefaultOutboundTimeout = 30 * time.Second
DefaultOutboundTimeout bounds AuthKit's first-party outbound HTTP calls that reach networked dependencies under partial attacker control — most notably the Verifier's JWKS fetches (the issuer/JWKS URL can come from tenant-issuer federation data) and the tenant-issuer registration POST. Without a timeout a slow or hostile endpoint can wedge a request goroutine indefinitely; when the caller also single-flights (as the Verifier does on first use of an issuer or after an unknown-kid refetch), one hung fetch stalls every concurrent waiter — a cheap denial-of-service amplifier.
const DelegatedAccessTokenType = jwtkit.DelegatedAccessTokenType
DelegatedAccessTokenType is the canonical JOSE `typ` header value for a delegated service token.
const RemoteApplicationAccessTokenType = jwtkit.RemoteApplicationAccessTokenType
RemoteApplicationAccessTokenType is the JOSE `typ` for a JWKS principal's SELF-token (#76): a remote_application signs a JWT whose subject is itself, and AuthKit grants it the STORED authority WE ASSIGNED (its tenant roles + direct permissions), never what the token self-claims.
const RemoteApplicationTokenType = "remote_application"
RemoteApplicationTokenType is the TokenType value carried by a JWKS principal SELF-token (#76): a remote_application acting AS ITSELF. Like a service principal it carries Permissions + TenantRoles (its STORED authority) but no UserID; the live-user enrichment/ban gate is skipped (there is no user).
const ServiceTokenType = "service"
ServiceTokenType is the TokenType value carried by an Tenant Access Token (service token) — a machine credential that acts as the tenant, not a user.
Variables ¶
This section is empty.
Functions ¶
func AllowNamed ¶
func AllowNamed(r *http.Request, rl RateLimiter, bucket string) bool
AllowNamed applies a per-IP limit using the provided bucket name. It fails open on limiter error.
func CheckTenantAccess ¶ added in v0.12.4
func CheckTenantAccess(ctx context.Context, svc *core.Service, userID, tenantSlug string) (canonicalTenant string, memberRoles []string, isMember bool, err error)
CheckTenantAccess resolves tenantSlug (slug or alias) to its canonical slug, verifies membership, and returns the member's tenant-scoped roles.
func DefaultRateLimits ¶
DefaultRateLimits returns AuthKit's built-in per-endpoint rate limits.
These limits are enforced per client IP (as determined by the Service's ClientIPFunc). Hosts can override by supplying their own limiter via WithRateLimiter(...).
func HasAnyTenantRole ¶ added in v0.12.4
HasAnyTenantRole returns true if roles contains any of want (case-insensitive).
func HasRoleDBCheck ¶
HasRoleDBCheck checks whether the given user has the provided role slug in Postgres. It also verifies the user is not deleted or banned. It assumes the default "profiles" schema; hosts that configure core.Config.Schema should use HasRoleDBCheckInSchema with svc.Schema().
func HasRoleDBCheckInSchema ¶ added in v0.26.0
func HasRoleDBCheckInSchema(ctx context.Context, pg *pgxpool.Pool, schema, userID, role string) (bool, error)
HasRoleDBCheckInSchema is HasRoleDBCheck against AuthKit tables in the given schema.
func IsAdmin ¶
IsAdmin checks whether the given user has the admin role in Postgres. It assumes the default "profiles" schema; hosts that configure core.Config.Schema should use IsAdminInSchema with svc.Schema().
func IsAdminInSchema ¶ added in v0.26.0
IsAdminInSchema is IsAdmin against AuthKit tables in the given schema.
func JWKSHandler ¶
JWKSHandler serves the public JWKS document for the given key set.
func LanguageMiddleware ¶
func LanguageMiddleware(cfg *LanguageConfig) func(http.Handler) http.Handler
LanguageMiddleware infers request language and attaches it to the request context.
func MintDelegatedAccessToken ¶ added in v0.12.0
func MintDelegatedAccessToken(ctx context.Context, signer jwtkit.Signer, p DelegatedAccessParams) (string, error)
MintDelegatedAccessToken signs a canonical delegated service token with an explicit signer. It is a thin re-export of core.MintDelegatedAccessToken; embedders holding a *core.Service should prefer (*core.Service).MintDelegatedAccessToken so they never construct a signer.
func RequireAdmin ¶
RequireAdmin verifies admin role directly in Postgres. It assumes the default "profiles" schema; hosts that configure core.Config.Schema should use RequireAdminInSchema with svc.Schema().
func RequireAdminInSchema ¶ added in v0.26.0
RequireAdminInSchema is RequireAdmin against AuthKit tables in the given schema (empty means the default "profiles").
func RequireAnyEntitlement ¶ added in v0.23.1
RequireAnyEntitlement gates a handler on the presence of at least one of the given entitlements. With no entitlements listed it denies all requests (fail-closed). It must run after Required.
func RequireEntitlement ¶ added in v0.23.1
RequireEntitlement gates a handler on the presence of a single entitlement in the verified claims (case-insensitive, see Claims.HasEntitlement). It must run after Required so claims are present. Service principals (OATs) and delegated tokens carry no entitlements and are therefore denied.
func Required ¶
Required validates the Bearer token (JWT), enforces iss/aud/exp, and stores claims in request context.
func RequiredServiceJWT ¶ added in v0.13.1
func RequiredServiceJWT(v *Verifier, opts ...ServiceJWTVerifyOption) func(http.Handler) http.Handler
RequiredServiceJWT verifies a Bearer service JWT and attaches its principal. It is intentionally separate from Required so service JWTs do not become valid on ordinary user/delegated-token routes by accident.
func ToMemoryLimits ¶
func ToMemoryLimits(in map[string]Limit) map[string]memorylimiter.Limit
func ToRedisLimits ¶
func ToRedisLimits(in map[string]Limit) map[string]redislimiter.Limit
Types ¶
type ActionAvailability ¶ added in v0.9.4
type ActionAvailability struct {
Action string `json:"action"`
Allowed bool `json:"allowed"`
Reason string `json:"reason,omitempty"`
RetryAfterSeconds int64 `json:"retry_after_seconds,omitempty"`
NextAllowedAt *time.Time `json:"next_allowed_at,omitempty"`
Limit *int `json:"limit,omitempty"`
Remaining *int `json:"remaining,omitempty"`
WindowSeconds *int64 `json:"window_seconds,omitempty"`
CooldownSeconds *int64 `json:"cooldown_seconds,omitempty"`
}
type AttributeDefResolver ¶ added in v0.27.0
type AttributeDefResolver func(ctx context.Context, issuer, key, ref string) (json.RawMessage, error)
AttributeDefResolver resolves a REFERENCE-mode attribute (#75) to its opaque definition, given the token's validated issuer, the attribute key, and the reference value the token carried. It returns the resolved definition (raw JSON) to substitute for the reference, or an error. *core.Service-backed resolvers map issuer -> remote_application -> registered definition.
type AttributesValidator ¶ added in v0.12.0
type AttributesValidator func(attributes map[string]json.RawMessage) error
AttributesValidator validates a delegated service token's `attributes` against the receiving service's policy schema. Return an error to reject the token. Called only for delegated service tokens.
type Claims ¶
type Claims struct {
UserID string
Email string
EmailVerified bool
Username string
DiscordUsername string
SessionID string
Roles []string
// GlobalRoles are the user's GLOBAL (platform-wide) roles, carried in the
// `global_roles` claim in both single and multi-tenant mode. Use these for
// global-admin authorization decisions.
GlobalRoles []string
// TenantRoles are the roles scoped to the tenant named in Tenant, carried in the
// `tenant_roles` claim on tenant-scoped tokens. Use these for tenant-scoped authz.
TenantRoles []string
Entitlements []string
Issuer string
UserTier string
JTI string
// Delegated/tenant fields. A delegated service token carries the external
// actor in DelegatedSubject (claim `delegated_sub`) and NO tenant claims of
// any kind: the VALIDATED Issuer is the tenant identity — receivers resolve
// their internal tenant record (slug + uuid) from their issuer registry. It
// never carries `sub` (UserID stays empty), so the local-user gate does not
// apply.
//
// Tenant carries the `tenant` claim of tenant-scoped ACCESS tokens (and the
// slug of opaque service tokens, resolved server-side); on delegated access
// tokens the claim is forbidden and Tenant stays empty. TenantID is
// populated ONLY for opaque service tokens via the receiver's own DB
// resolution — never from a JWT claim.
Tenant string
TenantID string
DelegatedSubject string
// Attributes is the `attributes` claim of a delegated service token: the
// canonical app-specific ESCAPE HATCH (#75). It is an object of issuer-
// asserted, NAMESPACED, OPAQUE key/values that AuthKit transports and
// optionally shape-validates (WithAttributesPolicy) but NEVER interprets —
// the semantics belong to the consuming app. Each value is in one of two
// modes (see Attribute / AttributeIsReference):
// INLINE — the value carries the full definition, e.g.
// {"tier":{"endpoints":[...],"caps":[...]}}.
// REFERENCE — the value is a short JSON string key, e.g. {"tier":"tier-1"},
// resolved against a definition the remote_application
// registered ahead of time (resolve via the attribute-def
// registry, or opt-in verify-time hydration).
// Reserved well-known keys: `tier` (opaque entitlement-tier string, surfaced
// as UserTier) and `roles` (uuid array, surfaced as DelegatedRoles).
// Everything else is free-form per consuming app. Values are kept as raw
// JSON so the receiver decodes each into its own typed schema; nil when the
// claim is absent.
Attributes map[string]json.RawMessage
// DelegatedRoles are the actor's role UUIDs carried by a delegated service
// token under `attributes.roles` (a JSON array of UUID strings). They are
// extracted and validated at verify (malformed entries dropped, count
// capped) and surfaced on DelegatedPrincipal.Roles. Downstream services use
// them as e.g. budget-scope keys; authkit treats them as opaque strings.
// Nil when absent. Distinct from the native-user Roles/TenantRoles claims,
// which a delegated token never carries.
DelegatedRoles []string
// TokenTyp is the JOSE `typ` header value. "access+jwt" identifies an
// AuthKit service token; "delegated-access+jwt" identifies a delegated access
// token.
TokenTyp string
// TokenType marks the credential class. Empty for ordinary user JWTs;
// "service" for an Service Token (service token) acting AS THE TENANT. A
// service principal carries Tenant + Permissions but no UserID, so the live-user
// ban/enrichment gate is skipped (there is no user to look up).
TokenType string
// Permissions are the app-defined permission strings a service principal
// (service token) carries directly — the PBAC grant. Empty for user principals, whose
// authority is expressed as TenantRoles that the resource server expands to
// permissions at request time. authkit treats permission strings as opaque.
Permissions []string
// Resources are opaque host-defined resource scopes carried by an
// Service Token. Empty means the service token has no AuthKit-stored
// resource constraints; resource-aware hosts decide whether to require them.
Resources []core.ServiceTokenResource
// RemoteApplicationID / RemoteApplicationSlug identify the JWKS PRINCIPAL a
// self-token (#76) authenticated as: a remote_application acting AS ITSELF.
// Populated ONLY for RemoteApplicationTokenType claims, resolved server-side
// from the validated `iss` (never from a self-asserted token claim). The
// principal's Permissions/TenantRoles carry its STORED, assigned authority.
RemoteApplicationID string
RemoteApplicationSlug string
}
Claims is a typed view of authenticated user information attached by middleware.
func (Claims) Attribute ¶ added in v0.12.0
func (c Claims) Attribute(key string) (json.RawMessage, bool)
Attribute returns the raw JSON value of a single delegated-service-token attribute and whether it was present. The value is opaque (#75): the caller decides whether it is an INLINE definition (a JSON object/array) or a REFERENCE (a JSON string key) — see AttributeIsReference / AttributeReference.
func (Claims) AttributeIsReference ¶ added in v0.27.0
AttributeIsReference reports whether attribute `key` is a REFERENCE (JSON string) rather than an INLINE definition. Convenience over AttributeReference.
func (Claims) AttributeReference ¶ added in v0.27.0
AttributeReference reports whether attribute `key` is in REFERENCE mode (a JSON string the consumer resolves against the remote_application's registered definition) and returns the reference key. ok is false for INLINE values (objects/arrays/other) or an absent key. This is the ref-vs-inline detector the consumer uses before resolving against the attribute-def registry.
func (Claims) Delegated ¶ added in v0.9.6
func (c Claims) Delegated() (DelegatedPrincipal, bool)
Delegated returns the typed DelegatedPrincipal when the claims are delegated.
func (Claims) DelegatedAccess ¶ added in v0.12.0
func (c Claims) DelegatedAccess() (DelegatedPrincipal, bool)
DelegatedAccess is the canonical accessor for a delegated service token's principal. It returns the typed DelegatedPrincipal and true only when the claims are a delegated service token (see IsDelegatedAccessToken).
func (Claims) HasEntitlement ¶
func (Claims) HasPermission ¶ added in v0.12.0
HasPermission reports whether the claims carry the exact permission string. Receiving services should layer scope semantics on top — string presence alone is not authorization.
func (Claims) IsDelegated ¶ added in v0.9.6
IsDelegated reports whether these claims represent a delegated principal (i.e. carry `delegated_sub` rather than a local `sub`).
func (Claims) IsDelegatedAccessToken ¶ added in v0.12.0
IsDelegatedAccessToken reports whether these claims represent a delegated service token. The canonical signal is the `typ=delegated-access+jwt` JOSE header plus a delegated subject and no local user subject.
func (Claims) IsRemoteApplication ¶ added in v0.28.0
IsRemoteApplication reports whether these claims represent a JWKS principal (a remote_application) authenticated via its SELF-token (#76).
type ClientIPFunc ¶
ClientIPFunc determines the client IP used for rate limiting and auditing.
Returning an empty string means "unknown" and causes rate limiting to fail open.
func ClientIPFromForwardedHeaders ¶
func ClientIPFromForwardedHeaders(trustedProxies []netip.Prefix) ClientIPFunc
ClientIPFromForwardedHeaders trusts CF-Connecting-IP and X-Forwarded-For only when the immediate peer (RemoteAddr) is in trustedProxies. Otherwise it falls back to DefaultClientIP behavior.
func DefaultClientIP ¶
func DefaultClientIP() ClientIPFunc
DefaultClientIP returns the immediate peer IP from RemoteAddr.
This intentionally includes private and loopback peers so embedded/local deployments still get default rate-limit protection. Hosts behind reverse proxies should use ClientIPFromForwardedHeaders with trusted proxy CIDRs when they need the original public client IP instead of the proxy peer.
func PublicRemoteAddrClientIP ¶ added in v0.9.1
func PublicRemoteAddrClientIP() ClientIPFunc
PublicRemoteAddrClientIP returns the older conservative client IP strategy:
- If RemoteAddr is a public IP, use it.
- If RemoteAddr is private/loopback/etc, return "" (fail open) so we don't accidentally rate-limit a reverse proxy/ingress as a single client.
type DelegatedAccessParams ¶ added in v0.12.0
type DelegatedAccessParams = core.DelegatedAccessParams
DelegatedAccessParams describes a delegated service token to mint. It is an alias for core.DelegatedAccessParams; the canonical definition (and the (*core.Service).MintDelegatedAccessToken mint method) live in package core so hosts can mint through the Service's internal signer without touching keys.
type DelegatedPrincipal ¶ added in v0.9.6
type DelegatedPrincipal struct {
// Issuer is the tenant identity: the receiving service resolves its
// internal tenant record (slug + uuid) from the VALIDATED Issuer via its
// issuer registry. The token carries no tenant claims.
Issuer string
DelegatedSubject string
// Permissions are the resource-defined permission strings the receiving
// service authorizes against its own catalog. This is the authority source.
Permissions []string
// Attributes is the issuer-asserted escape-hatch bag (#75): namespaced,
// OPAQUE, consumer-interpreted key/values, each INLINE or REFERENCE (see
// Claims.Attributes / Claims.AttributeReference). Reserved keys: `tier`
// (-> UserTier) and `roles` (-> Roles). Raw JSON values.
Attributes map[string]json.RawMessage
// JTI is the token identifier (`jti` claim), when present.
JTI string
// UserTier is the resolved tier, sourced from `attributes.tier`.
UserTier string
// Roles are the actor's role UUID strings, sourced from `attributes.roles`
// (each validated as a well-formed UUID at verify; malformed entries are
// dropped, count is capped). Kept as strings so consumers parse to uuid
// without forcing a uuid dependency on the principal. Nil when absent.
Roles []string
}
DelegatedPrincipal is the tenant identity carried by a delegated access token: an external actor (DelegatedSubject) acting under a canonical target resource account (Tenant). The subject does NOT exist as a local user in the validating service — authorization is by issuer/resource-account trust plus Permissions, not local-user lookup.
type InternalErrorEvent ¶ added in v0.8.7
type InternalErrorEvent struct {
Route string
Stage string
Code string
Method string
Path string
Err error
}
InternalErrorEvent captures a swallowed internal handler error so host apps can log it without exposing implementation details to clients.
func (InternalErrorEvent) Error ¶ added in v0.8.7
func (e InternalErrorEvent) Error() string
type IssuerOptions ¶
type IssuerOptions struct {
// JWKSURI is the URL to fetch JWKS from. If set, keys are fetched
// automatically and refreshed when they expire or an unknown kid appears.
JWKSURI string
// Keys are pre-provided public keys as PEM. The caller is responsible for
// refreshing by calling AddIssuer again with updated keys.
Keys []IssuerKey
// RawKeys are pre-provided public keys (e.g., from a co-located core.Service).
RawKeys map[string]crypto.PublicKey
// CacheTTL controls how long fetched JWKS keys are considered fresh.
// Default: 10 minutes.
CacheTTL time.Duration
// MaxStale controls how long stale keys may be used as fallback after
// a failed JWKS refresh. Default: 1 hour.
MaxStale time.Duration
// TenantSlug is the receiver-internal tenant slug this issuer is registered
// to — issuer-registry data, the single source of tenant identity for
// tokens signed by this issuer (tokens carry no tenant claims). It resolves
// the principal's tenant; it is never compared against token claims.
TenantSlug string
}
IssuerOptions configures how keys are obtained for an issuer. Provide one of JWKSURI, Keys, or RawKeys.
type LanguageConfig ¶
type PermissionValidator ¶ added in v0.12.0
PermissionValidator validates a delegated service token's `permissions` against the receiving service's own permission catalog. Return an error to reject the token. Called only for delegated service tokens.
type RateLimitResult ¶ added in v0.9.1
type RateLimitResult struct {
Allowed bool
RetryAfter time.Duration
Availability *ActionAvailability
}
type RateLimiter ¶
RateLimiter is a minimal interface used by adapters.
type RateLimiterWithResult ¶ added in v0.9.4
type RateLimiterWithRetryAfter ¶ added in v0.9.1
type RemoteApplicationAuthoritySource ¶ added in v0.28.0
type RemoteApplicationAuthoritySource interface {
ResolveRemoteApplicationAuthority(ctx context.Context, appID string) (memberships []core.TenantMembership, permissions []string, err error)
}
RemoteApplicationAuthoritySource resolves a JWKS principal's STORED authority (#76): its tenant memberships (slug + role names) and effective permission set (direct grants ∪ role-derived). *core.Service satisfies it.
type RemoteApplicationSource ¶ added in v0.27.0
type RemoteApplicationSource interface {
ListRemoteApplications(ctx context.Context, enabledOnly bool) ([]core.RemoteApplication, error)
// GetRemoteApplication fetches a SINGLE remote_application by its issuer,
// used by the lazy-load-on-miss path in keyForToken. *core.Service already
// implements this.
GetRemoteApplication(ctx context.Context, issuer string) (*core.RemoteApplication, error)
}
RemoteApplicationSource is the minimal store contract the Verifier needs to load remote_application principals (#74). *core.Service satisfies it. An embedding app may supply its own implementation in tests.
type RouteGroup ¶ added in v0.8.5
type RouteGroup string
RouteGroup identifies a prefix-neutral AuthKit route capability. Host applications can mount all default groups or select only the capabilities they want to expose.
const ( RouteCore RouteGroup = "core" RoutePassword RouteGroup = "password" RouteRegister RouteGroup = "register" RouteOwners RouteGroup = "owners" RouteEmailVerification RouteGroup = "email_verification" RoutePhoneVerification RouteGroup = "phone_verification" RouteTenants RouteGroup = "tenants" RouteUser RouteGroup = "user" RouteAccountOIDCLinking RouteGroup = "account_oidc_linking" RouteTwoFactor RouteGroup = "two_factor" RouteSolana RouteGroup = "solana" RouteAdmin RouteGroup = "admin" RouteOIDCBrowser RouteGroup = "oidc_browser" // RouteTenantIssuers exposes the inbound accept-side tenant-issuer registry // routes (the home for what tensorhub previously exposed as // `/api/v1/platform/issuers`). RouteTenantIssuers RouteGroup = "federation" )
type RouteSpec ¶ added in v0.8.5
type RouteSpec struct {
Method string
Path string
Group RouteGroup
Handler http.Handler
}
RouteSpec is a concrete, prefix-neutral route with its AuthKit handler attached. Path parameters use net/http ServeMux syntax, e.g. "/owners/{slug}".
type Routes ¶ added in v0.8.5
type Routes struct {
// contains filtered or unexported fields
}
Routes provides access to AuthKit's canonical route groups.
func (Routes) DefaultAPI ¶ added in v0.8.5
DefaultAPI returns every AuthKit JSON API route enabled by this service.
func (Routes) Groups ¶ added in v0.8.5
func (r Routes) Groups(groups ...RouteGroup) []RouteSpec
Groups returns every enabled AuthKit JSON API route in the requested groups.
func (Routes) OIDCBrowser ¶ added in v0.8.5
OIDCBrowser returns browser redirect OIDC routes without a mount prefix. Host applications choose where to mount them, commonly "/oidc".
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service wraps core.Service with net/http mounting helpers.
func NewService ¶
NewService constructs a core.Service and wraps it for net/http mounting. Returns an error if the core service fails to initialize (e.g., missing keys in production).
func (*Service) APIHandler ¶
APIHandler returns a handler that serves prefix-neutral JSON API routes. It is intended to be mounted under the host's mux/router at the host's chosen API prefix.
func (*Service) APIRoutes ¶ added in v0.8.5
func (s *Service) APIRoutes(groups ...RouteGroup) []RouteSpec
APIRoutes returns AuthKit's enabled JSON API routes. With no groups it returns the default API surface. With groups, it returns only matching routes.
func (*Service) CheckSMSHealth ¶ added in v0.15.4
CheckSMSHealth probes (without sending an SMS) whether the configured sender can actually deliver, caching the result to gate phone-based flows. Returns the probe error (nil = healthy) so the host app can log it at startup.
func (*Service) DisableRateLimiter ¶
func (*Service) JWKSHandler ¶
JWKSHandler returns a handler for GET /.well-known/jwks.json.
func (*Service) OIDCBrowserRoutes ¶ added in v0.8.5
func (s *Service) OIDCBrowserRoutes(groups ...RouteGroup) []RouteSpec
OIDCBrowserRoutes returns browser redirect routes with no mount prefix.
func (*Service) OIDCHandler ¶
OIDCHandler returns a handler that serves browser redirect flows: - GET /oidc/{provider}/login - GET /oidc/{provider}/callback - GET /oidc/{provider}/reauth/callback
func (*Service) Routes ¶ added in v0.8.5
Routes returns AuthKit's canonical route registry for this service.
func (*Service) SMSAvailable ¶ added in v0.15.4
SMSAvailable reports whether phone-based flows should be offered (a sender is configured and, if checked, found able to deliver).
func (*Service) SMSHealthReason ¶ added in v0.15.4
SMSHealthReason returns why SMS was last found unhealthy, if any.
func (*Service) SMSHealthy ¶ added in v0.15.4
SMSHealthy reports the last CheckSMSHealth result (true until a check runs).
func (*Service) WithAuthLogReader ¶
func (s *Service) WithAuthLogReader(r core.AuthEventLogReader) *Service
func (*Service) WithAuthLogger ¶
func (s *Service) WithAuthLogger(l core.AuthEventLogger) *Service
func (*Service) WithClientIPFunc ¶
func (s *Service) WithClientIPFunc(fn ClientIPFunc) *Service
func (*Service) WithEmailSender ¶
func (s *Service) WithEmailSender(es core.EmailSender) *Service
func (*Service) WithEntitlements ¶
func (s *Service) WithEntitlements(p core.EntitlementsProvider) *Service
func (*Service) WithEphemeralStore ¶
func (s *Service) WithEphemeralStore(store core.EphemeralStore, mode core.EphemeralMode) *Service
func (*Service) WithErrorLogger ¶ added in v0.8.7
func (s *Service) WithErrorLogger(fn func(context.Context, InternalErrorEvent)) *Service
func (*Service) WithLanguageConfig ¶
func (s *Service) WithLanguageConfig(cfg LanguageConfig) *Service
func (*Service) WithRateLimiter ¶
func (s *Service) WithRateLimiter(rl RateLimiter) *Service
func (*Service) WithSolanaDomain ¶
WithSolanaDomain sets the domain used in SIWS sign-in messages. If not set, the domain is derived from the request Origin or Host header.
type ServiceJWTPrincipal ¶ added in v0.13.1
type ServiceJWTPrincipal struct {
Issuer string
Subject string
Tenant string
Audiences []string
Permissions []string
Resources []core.ServiceTokenResource
JTI string
ExpiresAt time.Time
}
ServiceJWTPrincipal is the verified machine principal in a service JWT. The receiving host still owns authorization: intersect Permissions with its own server-side grants before allowing an action.
func ServiceJWTPrincipalFromContext ¶ added in v0.13.1
func ServiceJWTPrincipalFromContext(ctx context.Context) (ServiceJWTPrincipal, bool)
ServiceJWTPrincipalFromContext returns the verified service-JWT principal attached by RequiredServiceJWT.
type ServiceJWTReplayChecker ¶ added in v0.13.1
type ServiceJWTReplayChecker func(ctx context.Context, claims core.ServiceJWTClaims) error
ServiceJWTReplayChecker lets hosts reject already-seen jti values.
type ServiceJWTVerifyOption ¶ added in v0.13.1
type ServiceJWTVerifyOption func(*serviceJWTVerifyConfig)
ServiceJWTVerifyOption configures VerifyServiceJWT.
func WithServiceJWTMaxLifetime ¶ added in v0.13.1
func WithServiceJWTMaxLifetime(d time.Duration) ServiceJWTVerifyOption
WithServiceJWTMaxLifetime caps accepted service-JWT lifetime. Empty defaults to AuthKit's 15-minute service-JWT lifetime.
func WithServiceJWTReplayChecker ¶ added in v0.13.1
func WithServiceJWTReplayChecker(fn ServiceJWTReplayChecker) ServiceJWTVerifyOption
WithServiceJWTReplayChecker installs an optional jti replay hook.
type TenantIssuersClient ¶ added in v0.12.4
type TenantIssuersClient struct {
// contains filtered or unexported fields
}
TenantIssuersClient publishes THIS tenant's issuer registration to a resource server's inbound accept endpoint. It is the OUTBOUND (send-side) half of the AuthKit-owned federation handshake — the platform/IdP side (e.g. cozy-art) uses it to tell a resource server (e.g. tensorhub) "trust delegated tokens I mint with this issuer + JWKS URL". The resource server's handleTenantIssuerRegisterPOST stores the registration.
func NewTenantIssuersClient ¶ added in v0.12.4
func NewTenantIssuersClient(opts ...TenantIssuersClientOption) *TenantIssuersClient
NewTenantIssuersClient creates a TenantIssuersClient.
func (*TenantIssuersClient) RegisterIssuer ¶ added in v0.12.4
func (fc *TenantIssuersClient) RegisterIssuer(ctx context.Context, acceptURL string, reg TenantIssuersRegistration) error
RegisterIssuer POSTs this remote_application's registration to the resource server's accept endpoint (acceptURL is the fully-qualified URL of the inbound handler, e.g. "https://tensorhub.example/api/v1/remote-applications"). It returns an error for non-2xx responses.
type TenantIssuersClientOption ¶ added in v0.12.4
type TenantIssuersClientOption func(*TenantIssuersClient)
TenantIssuersClientOption configures a TenantIssuersClient.
func WithTenantIssuersAuthToken ¶ added in v0.12.4
func WithTenantIssuersAuthToken(token string) TenantIssuersClientOption
WithTenantIssuersAuthToken sets the Bearer token used to authenticate to the resource server's accept endpoint (owner/admin of the tenant being registered).
func WithTenantIssuersHTTPClient ¶ added in v0.12.4
func WithTenantIssuersHTTPClient(c *http.Client) TenantIssuersClientOption
WithTenantIssuersHTTPClient sets the HTTP client used for registration calls.
type TenantIssuersRegistration ¶ added in v0.12.4
type TenantIssuersRegistration struct {
// Slug is this remote_application's slug on the receiving service.
Slug string
// Issuer is THIS platform's issuer URL (the `iss` of delegated tokens).
Issuer string
// JWKSURI is where the resource server fetches THIS platform's public keys
// (jwks mode — preferred). Mutually exclusive with PublicKeys.
JWKSURI string
// PublicKeys is the static-mode key list for platforms without a JWKS
// endpoint (#74). Mutually exclusive with JWKSURI.
PublicKeys []core.RemoteAppKey
}
TenantIssuersRegistration is the payload published to a resource server.
type Verifier ¶
type Verifier struct {
// contains filtered or unexported fields
}
Verifier validates JWTs from one or more issuers.
For verify-only mode, create with NewVerifier and add issuers via AddIssuer. For issuing mode, authhttp.Service creates a Verifier internally.
func NewVerifier ¶
func NewVerifier(opts ...VerifierOption) *Verifier
NewVerifier creates a new Verifier. Add trusted issuers via AddIssuer.
func (*Verifier) AddIssuer ¶
func (v *Verifier) AddIssuer(issuerID string, audiences []string, opts IssuerOptions) error
AddIssuer registers (or updates) a trusted issuer. This is the single method for adding any issuer — whether at startup or at runtime, whether keys come from a JWKS URL or are pre-provided.
func (*Verifier) LoadRemoteApplications ¶ added in v0.27.0
func (v *Verifier) LoadRemoteApplications(ctx context.Context, src RemoteApplicationSource, audiences []string) error
LoadRemoteApplications loads the ACTIVE remote_applications from authkit's OWN store (the remote_applications table) and registers each as a trusted issuer via AddIssuer with its JWKS URL. The Verifier's in-house JWKS fetch/refresh then handles the keys — there is NO external push or sync of keys.
audiences, when non-empty, is applied to every loaded issuer (typically this resource server's own audience). Call this at startup, and re-call (e.g. on a ticker, or after an inbound registration) to pick up store changes. Pass the embedding app's core.Service (or any RemoteApplicationSource); if nil, the Service provided via WithService is used.
func (*Verifier) RemoveIssuer ¶
RemoveIssuer removes a previously added issuer.
func (*Verifier) Verify ¶
Verify parses + verifies a token and returns typed Claims. It enforces issuer/audience/expiry with the configured skew, plus authkit's user-token invariant, on top of VerifyClaims.
func (*Verifier) VerifyClaims ¶ added in v0.11.2
VerifyClaims parses and cryptographically verifies a token against the registered issuers and returns its RAW validated claims. It performs the generic, token-type-agnostic checks: JWKS key resolution + signature, issuer must be registered, audience match, and exp/nbf/iat with the configured skew. It does NOT apply authkit's user-token semantics (the sub/delegated_sub invariant) or map into the typed Claims struct.
Use it to verify CUSTOM token types (e.g. a host application's capability tokens) that should reuse authkit's single JWKS engine — registry, caching, rotation, lazy-load — while carrying their own claim shape. The caller registers the token's issuer via AddIssuer and parses the returned MapClaims itself. Verify() is built on top of this for authkit's own user tokens.
func (*Verifier) VerifyDelegatedAccess ¶ added in v0.12.0
func (v *Verifier) VerifyDelegatedAccess(tokenStr string) (Claims, DelegatedPrincipal, error)
VerifyDelegatedAccess verifies a token, requires it to be a delegated access token, and runs any configured permission/attributes validators. It returns the typed Claims and the DelegatedPrincipal. Use it on resource servers that only accept delegated service tokens and want catalog/policy enforcement.
func (*Verifier) VerifyServiceJWT ¶ added in v0.13.1
func (v *Verifier) VerifyServiceJWT(ctx context.Context, tokenStr string, opts ...ServiceJWTVerifyOption) (core.ServiceJWTClaims, ServiceJWTPrincipal, error)
VerifyServiceJWT verifies a first-party OIDC service JWT through the verifier's registered issuer/JWKS store and returns the requested permissions/resources. AuthKit does not grant those permissions; the host must intersect them with server-side grants for the issuer/subject/resource.
type VerifierOption ¶
type VerifierOption func(*Verifier)
VerifierOption configures a Verifier.
func WithAlgorithms ¶
func WithAlgorithms(algs ...string) VerifierOption
WithAlgorithms sets the allowed JWS algorithms. Default: ["RS256"].
func WithAttributeHydration ¶ added in v0.27.0
func WithAttributeHydration(resolver AttributeDefResolver) VerifierOption
WithAttributeHydration enables OPT-IN verify-time hydration (#75): after a delegated token verifies, VerifyDelegatedAccess resolves each REFERENCE-mode attribute (a JSON-string value) into its full definition via resolver, so the consumer sees a uniform INLINE shape whether the token used inline or reference. OFF by default. A resolver miss leaves that attribute untouched (the consumer can still resolve it itself); only a hard resolver error fails the call. Pass nil to use the Service-backed default resolver (requires WithService).
func WithAttributesPolicy ¶ added in v0.12.0
func WithAttributesPolicy(fn AttributesValidator) VerifierOption
WithAttributesPolicy installs a validator that VerifyDelegatedAccess runs against the token's `attributes`. Use it to enforce a policy schema (allowed keys, value shapes/ranges).
func WithHTTPClient ¶
func WithHTTPClient(c *http.Client) VerifierOption
WithHTTPClient sets the HTTP client used for JWKS fetching.
func WithPermissionCatalog ¶ added in v0.12.0
func WithPermissionCatalog(fn PermissionValidator) VerifierOption
WithPermissionCatalog installs a validator that VerifyDelegatedAccess runs against the token's `permissions`. Use it to ensure every permission string belongs to this resource server's catalog.
func WithServiceTokenPrefix ¶ added in v0.12.4
func WithServiceTokenPrefix(prefix string) VerifierOption
WithServiceTokenPrefix sets the host application's Service Token (service token) brand prefix used to detect service tokens in the middleware. Empty -> bare "st_".
func WithSkew ¶
func WithSkew(d time.Duration) VerifierOption
WithSkew sets the clock skew tolerance for exp/nbf/iat checks. Default: 60s.
func WithTenantMode
deprecated
added in
v0.12.4
func WithTenantMode(string) VerifierOption
WithTenantMode is a deprecated no-op compatibility shim (authkit issue 60): the global tenant mode was removed. Tenant claims are now parsed whenever present. Kept so existing callers compile; scheduled for deletion.
Deprecated: remove the call. Tenant claim handling no longer depends on a mode.
Source Files
¶
- admin_reserved_accounts.go
- admin_routes.go
- admin_signins.go
- admin_util.go
- audit.go
- auth_sessions_current_post.go
- auth_token_post.go
- auth_token_tenant_post.go
- availability.go
- buckets.go
- claims.go
- client_ip.go
- default_outbound_client.go
- delegation.go
- email_verify.go
- email_verify_confirm_link_post.go
- errors.go
- handlers.go
- internal_errors.go
- jwks_get.go
- language.go
- logout_delete.go
- me_permissions_get.go
- middleware.go
- oauth2_browser.go
- oauth2_http_client.go
- oauth2_provider.go
- oidc_browser.go
- oidc_handler.go
- oidc_link_start_post.go
- oidc_util.go
- password_login_post.go
- password_reset.go
- phone_password_reset.go
- phone_verify.go
- phone_verify_confirm_link_post.go
- provider_descriptors.go
- providers_get.go
- ratelimit.go
- ratelimit_defaults.go
- reauth.go
- register.go
- register_availability.go
- remote_application_client.go
- remote_application_handlers.go
- routes.go
- service.go
- service_jwt.go
- service_tokens_handlers.go
- siws_cache.go
- solana_siws.go
- tenant_authz.go
- tenant_helpers.go
- tenant_invites_handlers.go
- tenant_membership_roles_handlers.go
- tenant_memberships_handlers.go
- tenant_rbac_introspection_handlers.go
- tenant_role_permissions_handlers.go
- tenant_roles_handlers.go
- tenants_handlers.go
- user_2fa.go
- user_2fa_verify_post.go
- user_bootstrap_get.go
- user_me_get.go
- user_password_post.go
- user_routes.go
- user_sessions.go
- util.go
- validate.go
- verifier.go