authhttp

package
v0.19.0 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: MIT Imports: 37 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ActionUpdateUsername           = "update_username"
	ActionRequestPasswordReset     = "request_password_reset"
	ActionRequestEmailVerification = "request_email_verification"
	ActionRequestPhoneVerification = "request_phone_verification"
)
View Source
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.

View Source
const AccessTokenType = jwtkit.AccessTokenType

AccessTokenType is the canonical JOSE `typ` header value for an AuthKit service token.

View Source
const DelegatedAccessTokenType = jwtkit.DelegatedAccessTokenType

DelegatedAccessTokenType is the canonical JOSE `typ` header value for a delegated service token.

View Source
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

func DefaultRateLimits() map[string]Limit

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

func HasAnyTenantRole(roles []string, want ...string) bool

HasAnyTenantRole returns true if roles contains any of want (case-insensitive).

func HasRoleDBCheck

func HasRoleDBCheck(ctx context.Context, pg *pgxpool.Pool, userID, role string) (bool, error)

HasRoleDBCheck checks whether the given user has the provided role slug in Postgres. It also verifies the user is not deleted or banned.

func IsAdmin

func IsAdmin(ctx context.Context, pg *pgxpool.Pool, userID string) (bool, error)

IsAdmin checks whether the given user has the admin role in Postgres.

func JWKSHandler

func JWKSHandler(jwks jwtkit.JWKS) http.Handler

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. It stamps the `typ=delegated-access+jwt` JOSE header, writes the canonical `tenant`/`delegated_sub`/`permissions`/`attributes` claims, and NEVER sets `sub` — the sub-XOR-delegated_sub invariant is enforced by construction. Receiving services authorize by issuer/resource-account trust plus `permissions`; `roles` are not minted here because they are not authority for the receiving service.

func Optional

func Optional(v *Verifier) func(http.Handler) http.Handler

Optional validates when Authorization is present; otherwise passes through.

func RequireAdmin

func RequireAdmin(pg *pgxpool.Pool) func(http.Handler) http.Handler

RequireAdmin verifies admin role directly in Postgres.

func Required

func Required(v *Verifier) func(http.Handler) http.Handler

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 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 the target resource
	// account in TenantID (claim `tenant_id`, immutable uuid — the canonical
	// key) and Tenant (claim `tenant`, mutable slug — presentation/logging
	// only). It never carries `sub` (UserID stays empty), so the local-user
	// gate does not apply. TenantID is empty on tokens minted before the
	// tenant_id claim existed; fall back to resolving Tenant.
	Tenant           string
	TenantID         string
	DelegatedSubject string

	// Attributes is the `attributes` claim of a delegated service token: an
	// object of issuer-provided policy metadata (e.g. {"tier":"cozy_free"}).
	// Values are kept as raw JSON so the receiving service can decode each into
	// its own typed schema. Nil when the claim is absent.
	Attributes map[string]json.RawMessage

	// 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
}

Claims is a typed view of authenticated user information attached by middleware.

func ClaimsFromContext

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

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.

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 (c Claims) HasEntitlement(ent string) bool

func (Claims) HasPermission added in v0.12.0

func (c Claims) HasPermission(perm string) bool

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) HasRole

func (c Claims) HasRole(role string) bool

func (Claims) IsDelegated added in v0.9.6

func (c Claims) IsDelegated() bool

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

func (c Claims) IsDelegatedAccessToken() bool

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) IsService added in v0.11.0

func (c Claims) IsService() bool

IsService reports whether these claims represent a service principal (an Service Token), as opposed to a human user or delegated subject.

type ClientIPFunc

type ClientIPFunc func(r *http.Request) string

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 struct {
	// Issuer becomes the `iss` claim: the AuthKit issuer that signed the token.
	// signs the token. Must match a tenant issuer registered with the
	// validating resource server. Required.
	Issuer string
	// Audiences becomes the `aud` claim: the target resource API(s), e.g.
	// "openrails", "tensorhub", or "gen-orchestrator".
	Audiences []string
	// Tenant becomes the `tenant` claim: the target resource-service account's
	// mutable slug, e.g. "doujins" for OpenRails. Presentation/logging only —
	// receiving services must key on TenantID.
	Tenant string
	// TenantID becomes the `tenant_id` claim: the immutable uuid of the target
	// resource-service account. This is the canonical identifier receiving
	// services persist and authorize against. Required.
	TenantID string
	// DelegatedSubject becomes `delegated_sub`: the issuer-side user/actor id.
	// Required. No local account is implied in the receiving service.
	DelegatedSubject string
	// Permissions becomes the `permissions` claim: an array of resource-defined
	// permission strings (NOT OAuth's space-delimited `scope`). Receiving
	// services validate these against their own permission catalog.
	Permissions []string
	// Attributes becomes the `attributes` claim: an object of issuer-provided
	// policy metadata such as {"tier":"cozy_free"}, plan labels, budget classes,
	// or risk buckets. Values are arbitrary JSON.
	Attributes map[string]any
	// TTL is the token lifetime. Defaults to 15m when zero.
	TTL time.Duration
	// JTI, when set, becomes the `jti` claim (token identifier). Optional.
	JTI string
	// NotBefore, when set, becomes the `nbf` claim. Optional.
	NotBefore time.Time
}

DelegatedAccessParams describes a delegated service token to mint.

A delegated service token is AuthKit's standard primitive for resource-service federation: one AuthKit issuer signs a short-lived JWT for an external (delegated) actor, and a resource service accepts it after issuer/JWKS/ audience/resource-account validation. The token represents a delegated actor (DelegatedSubject) acting under a target resource account carried in the `tenant` JWT claim. It NEVER carries a normal `sub` — no local account is implied in the receiving service.

type DelegatedPrincipal added in v0.9.6

type DelegatedPrincipal struct {
	Issuer string
	// Tenant is the mutable resource-account slug (claim `tenant`);
	// TenantID is the immutable uuid (claim `tenant_id`) and is the
	// identifier to persist. TenantID is empty on legacy tokens.
	Tenant           string
	TenantID         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 issuer-provided policy metadata (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
}

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 IssuerKey

type IssuerKey struct {
	KID          string
	PublicKeyPEM string
}

IssuerKey is a public key for an issuer, identified by key ID.

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

	// TrustedResourceAccount optionally binds delegated service tokens from this
	// issuer to one resource-service account slug. Tenant issuers loaded from
	// the tenant_issuers store set this to that row's tenant slug, so a
	// trusted issuer cannot mint a delegated token for another resource account.
	TrustedResourceAccount string
}

IssuerOptions configures how keys are obtained for an issuer. Provide one of JWKSURI, Keys, or RawKeys.

type LanguageConfig

type LanguageConfig struct {
	Supported  []string
	Default    string
	QueryParam string
	CookieName string
}

type Limit

type Limit struct {
	Limit    int
	Window   time.Duration
	Cooldown time.Duration
}

Limit configures a named rate limit bucket.

type PermissionValidator added in v0.12.0

type PermissionValidator func(permissions []string) error

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

type RateLimiter interface {
	AllowNamed(bucket string, key string) (bool, error)
}

RateLimiter is a minimal interface used by adapters.

type RateLimiterWithResult added in v0.9.4

type RateLimiterWithResult interface {
	AllowNamedResult(bucket string, key string) (ratelimit.Result, error)
}

type RateLimiterWithRetryAfter added in v0.9.1

type RateLimiterWithRetryAfter interface {
	AllowNamedWithRetryAfter(bucket string, key string) (bool, time.Duration, error)
}

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

func (r Routes) DefaultAPI() []RouteSpec

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

func (r Routes) OIDCBrowser() []RouteSpec

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

func NewService(cfg core.Config) (*Service, error)

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

func (s *Service) APIHandler() http.Handler

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

func (s *Service) CheckSMSHealth(ctx context.Context) error

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) Core

func (s *Service) Core() *core.Service

func (*Service) DisableRateLimiter

func (s *Service) DisableRateLimiter() *Service

func (*Service) JWKSHandler

func (s *Service) JWKSHandler() http.Handler

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

func (s *Service) OIDCHandler() http.Handler

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

func (s *Service) Routes() Routes

Routes returns AuthKit's canonical route registry for this service.

func (*Service) SMSAvailable added in v0.15.4

func (s *Service) SMSAvailable() bool

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

func (s *Service) SMSHealthReason() string

SMSHealthReason returns why SMS was last found unhealthy, if any.

func (*Service) SMSHealthy added in v0.15.4

func (s *Service) SMSHealthy() bool

SMSHealthy reports the last CheckSMSHealth result (true until a check runs).

func (*Service) Verifier

func (s *Service) Verifier() *Verifier

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) WithPostgres

func (s *Service) WithPostgres(pg *pgxpool.Pool) *Service

func (*Service) WithRateLimiter

func (s *Service) WithRateLimiter(rl RateLimiter) *Service

func (*Service) WithRedis

func (s *Service) WithRedis(rd *redis.Client) *Service

func (*Service) WithSMSSender

func (s *Service) WithSMSSender(sender core.SMSSender) *Service

func (*Service) WithSolanaDomain

func (s *Service) WithSolanaDomain(domain string) *Service

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 TenantIssuerSource added in v0.12.4

type TenantIssuerSource interface {
	ListTenantIssuers(ctx context.Context, enabledOnly bool) ([]core.TenantIssuer, error)
	// GetTenantIssuer fetches a SINGLE tenant-tenant issuer by its
	// issuer, used by the lazy-load-on-miss path in keyForToken. *core.Service
	// already implements this.
	GetTenantIssuer(ctx context.Context, issuerID string) (*core.TenantIssuer, error)
}

TenantIssuerSource is the minimal store contract the Verifier needs to load tenant-tenant issuers. *core.Service satisfies it. An embedding app may supply its own implementation in tests or to source issuers from elsewhere.

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 tenant's issuer 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/tenant-issuers"). 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 {
	// Tenant is this issuer's resource account slug on the receiving service.
	Tenant 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 (#465). Mutually exclusive with JWKSURI.
	PublicKeys []core.TenantIssuerKey
}

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) LoadTenantIssuers added in v0.12.4

func (v *Verifier) LoadTenantIssuers(ctx context.Context, src TenantIssuerSource, audiences []string) error

LoadTenantIssuers loads the ACTIVE tenant-tenant issuers from authkit's OWN store (the tenant_issuers table) and registers each as a trusted issuer via AddIssuer with its JWKS URL. The Verifier's existing in-house JWKS fetch/refresh then handles the tenant 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 TenantIssuerSource); if nil, the Service provided via WithService is used.

func (*Verifier) RemoveIssuer

func (v *Verifier) RemoveIssuer(issuerID string)

RemoveIssuer removes a previously added issuer.

func (*Verifier) Verify

func (v *Verifier) Verify(tokenStr string) (Claims, error)

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

func (v *Verifier) VerifyClaims(tokenStr string) (jwt.MapClaims, error)

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.

func (*Verifier) WithService

func (v *Verifier) WithService(svc *core.Service) *Verifier

WithService enables best-effort enrichment hooks (roles/provider usernames) from Postgres, and wires the same *core.Service as the default tenant-issuer source for lazy-load-on-miss (see keyForToken).

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 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.

Jump to

Keyboard shortcuts

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