httpapi

package
v1.0.2 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const (
	// 2FA-specific rate limit buckets
	RL2FASetupSMS        = "2fa_setup_sms"
	RL2FASetupTOTP       = "2fa_setup_totp"
	RL2FASetupEmail      = "2fa_setup_email"
	RL2FAEnable          = "2fa_enable"
	RL2FADisable         = "2fa_disable"
	RL2FARegenerateCodes = "2fa_regenerate_codes"
	RL2FAVerify          = "2fa_verify"

	RLTokenRefresh          = "token_refresh"
	RLRegisterCreate        = "register_create"
	RLRegisterAvailability  = "register_availability"
	RLRegisterAbandon       = "register_abandon"
	RLInviteCreate          = "invite_create"
	RLInviteRedeem          = "invite_redeem"
	RLAPIKeyCreate          = "api_key_create"
	RLPasswordLogin         = "password_login"
	RLStepUpPassword        = "step_up_password"
	RLPasswordlessStart     = "passwordless_start"
	RLPasswordlessConfirm   = "passwordless_confirm"
	RLPasskeyRegister       = "passkey_register"
	RLPasskeyLogin          = "passkey_login"
	RLDeviceKeyEnrollBegin  = "device_key_enroll_begin"
	RLDeviceKeyEnrollFinish = "device_key_enroll_finish"
	RLDeviceKeyLoginBegin   = "device_key_login_begin"
	RLDeviceKeyLoginFinish  = "device_key_login_finish"
	RLDeviceKeyManage       = "device_key_manage"
	RLSessionLogout         = "session_logout"
	RLSessionList           = "session_list"
	RLSessionRevoke         = "session_revoke"
	RLSessionRevokeAll      = "session_revoke_all"

	// #261 delegated-token mint (authenticated; bounds signing cost per IP).
	RLDelegatedTokenMint = "delegated_token_mint"

	RLPasswordResetRequest = "password_reset_request"
	RLPasswordResetConfirm = "password_reset_confirm"
	// #312: one bucket per contact flow, whichever channel the identifier names.
	RLVerifyRequest   = "verify_request"
	RLVerifyConfirm   = "verify_confirm"
	RLMeContactChange = "me_contact_change"

	RLOIDCStart    = "oidc_start"
	RLOIDCCallback = "oidc_callback"

	RLMePasswordChange = "me_password_change"
	RLMeRead           = "me_read"
	RLMeUpdate         = "me_update"
	RLStepUp2FASend    = "step_up_2fa_send"

	RLMeDelete         = "me_delete"
	RLMeProviderUnlink = "me_provider_unlink"

	RLAdminRead  = "admin_read"
	RLAdminWrite = "admin_write"

	// Solana SIWS authentication
	RLSolanaChallenge = "solana_challenge"
	RLSolanaLogin     = "solana_login"
	RLSolanaLink      = "solana_link"
)

Bucket names key HTTPConfig.RateLimits and name the action a rate_limited error reports. Each is <area>_<action>: the route family as its path spells it (me, session, 2fa, step_up, device_key, …), then what the route does.

View Source
const (
	CookieRefresh   cookieKind = "refresh"
	CookieOIDCState cookieKind = "oidc_state"
	OIDCStatePrefix            = "authkit_oauth_state_"
)
View Source
const OIDCPath = "/oidc"

Mount layout. The whole surface lives beneath one base path: the path of the issuer, so verifiers find JWKS at the issuer plus iam.JWKSPath. Beneath it, browser OIDC sits at OIDCPath and the JSON API at APIPath plus config.APIVersion. The surface is ONE handler.

Variables

View Source
var CookieRegistry = []CookieVariant{
	{Kind: CookieRefresh, Name: "authkit_rt", Path: "/", Current: true},
	{Kind: CookieRefresh, Name: "__Host-authkit_rt", Path: "/", Secure: true, Current: true},
	{Kind: CookieOIDCState, Name: OIDCStatePrefix, Path: "/", Current: true},
	{Kind: CookieOIDCState, Name: "__Host-" + OIDCStatePrefix, Path: "/", Secure: true, Current: true},
}

CookieRegistry is append-only.

Features lists every Feature a route can be mounted under.

View Source
var PathEnums = map[string][]string{"kind": {"users"}}

PathEnums are the values a path parameter takes, by name, for the generated contract: a member path's {kind} is the kind of subject it names.

Functions

func Conform added in v0.148.0

func Conform(t reflect.Type, v any) []string

Conform checks decoded JSON v against t's wire form and lists every difference: a missing or unknown member, a null where none is allowed, a wrong JSON type, a time not in UTC.

func DefaultRateLimits

func DefaultRateLimits() map[string]ratelimit.Limit

DefaultRateLimits returns AuthKit's built-in per-endpoint rate limits, per client IP; "default" applies to any bucket not listed. Hosts overlay them with HTTPConfig.RateLimits or replace the limiter.

func ErrorMetadata added in v0.149.0

func ErrorMetadata() map[errmodel.Code]any

ErrorMetadata is the metadata shape of every code that carries metadata (zero values); every other code's metadata is null. The contract generator publishes it, and the integration suites check every error against it.

func IsPage added in v0.148.0

func IsPage(t reflect.Type) bool

IsPage reports whether t is iam.ListPage[T].

func PageItem added in v0.148.0

func PageItem(t reflect.Type) reflect.Type

PageItem is T of iam.ListPage[T].

func SanitizeReturnTo

func SanitizeReturnTo(value string) string

sanitizeReturnTo admits only a same-origin absolute path: a leading "/" but not "//" or "/\" (browsers read both as scheme-relative), no control characters, no scheme or host. Anything else becomes "/".

Types

type APIKeyCreateRequest added in v0.148.0

type APIKeyCreateRequest struct {
	Name      string     `json:"name"`
	Role      string     `json:"role"`
	ExpiresAt *time.Time `json:"expires_at"`
}

type AdminUserUpdateRequest added in v0.149.0

type AdminUserUpdateRequest struct {
	Email             *string `json:"email"`
	PhoneNumber       *string `json:"phone_number"`
	Username          *string `json:"username"`
	AvatarURL         *string `json:"avatar_url"`
	PreferredLanguage *string `json:"preferred_language"`
}

AdminUserUpdateRequest is PATCH /admin/users/{user_id}: an absent field is unchanged.

type AuthResult added in v0.149.0

type AuthResult struct {
	Status   AuthStatus    `json:"status"`
	TokenSet *iam.TokenSet `json:"token_set"`
	User     *iam.User     `json:"user"`
	// Created: this sign-in created the account.
	Created  bool    `json:"created"`
	ReturnTo *string `json:"return_to"`
	// FreshAuth: the session's step-up state after a re-authentication.
	FreshAuth *FreshAuth `json:"fresh_auth"`
	// DeviceKey: a device-key sign-in's key.
	DeviceKey    *iam.DeviceKey                        `json:"device_key"`
	SecondFactor *SecondFactorStep                     `json:"second_factor"`
	Enrollment   *EnrollmentStep                       `json:"enrollment"`
	Verification *VerificationStep                     `json:"verification"`
	Recovery     *authflow.AccountRecoveryConfirmation `json:"recovery"`
}

AuthResult is every sign-in and re-authentication answer: a session, or the one next step the status names. Only the members of that status are set; the rest are null.

type AuthStatus added in v0.149.0

type AuthStatus string

AuthStatus is where a sign-in stands.

const (
	// AuthComplete: signed in (or re-authenticated); token_set and user are set.
	AuthComplete AuthStatus = "complete"
	// AuthSecondFactorRequired: the first factor passed; answer second_factor
	// at POST /2fa/verify (or switch factor at POST /2fa/challenge).
	AuthSecondFactorRequired AuthStatus = "second_factor_required"
	// AuthEnrollmentRequired: the account must add a second factor first;
	// enrollment.token_set reaches only POST /me/2fa/setup and /me/2fa/factors.
	AuthEnrollmentRequired AuthStatus = "enrollment_required"
	// AuthVerificationRequired: a code went to verification.identifier; confirm
	// it at POST /verify/confirm.
	AuthVerificationRequired AuthStatus = "verification_required"
	// AuthAccountRecoveryRequired: the account is deleted and restorable;
	// confirm recovery.token at POST /account/recovery/confirm.
	AuthAccountRecoveryRequired AuthStatus = "account_recovery_required"
)

type Availability added in v0.148.0

type Availability struct {
	Username    *AvailabilityField `json:"username"`
	Email       *AvailabilityField `json:"email"`
	PhoneNumber *AvailabilityField `json:"phone_number"`
}

Availability answers each field asked for; null for a field not asked.

type AvailabilityField added in v0.148.0

type AvailabilityField struct {
	Available bool    `json:"available"`
	Error     *string `json:"error"`
}

AvailabilityField is one answer; Error is the wire code that makes the value unavailable.

type AvailabilityQuery added in v0.148.0

type AvailabilityQuery struct {
	Username    string `query:"username"`
	Email       string `query:"email"`
	PhoneNumber string `query:"phone_number"`
}

type Backend

type Backend interface {
	ops.Operations
	// contains filtered or unexported methods
}

Backend is the engine capability the HTTP layer drives: the operations the Client exposes (ops.Operations) plus the flows only the HTTP layer runs. The engine implements it; hosts never see it. Each domain's flow methods live in its own backend_<domain>.go.

type BackupCodes added in v0.148.0

type BackupCodes struct {
	BackupCodes []string `json:"backup_codes"`
}

type BanRequest added in v0.148.0

type BanRequest struct {
	Reason *string    `json:"reason"`
	Until  *time.Time `json:"until"`
}

BanRequest is the ban to put in force; a null until bans indefinitely.

type Capabilities added in v0.148.0

type Capabilities struct {
	Registration           RegistrationCapabilities `json:"registration"`
	ExternalLoginProviders []ExternalLoginProvider  `json:"external_login_providers"`
	Username               UsernameCapabilities     `json:"username"`
	Password               PasswordCapabilities     `json:"password"`
	Passwordless           PasswordlessCapabilities `json:"passwordless"`
	Passkeys               PasskeyCapabilities      `json:"passkeys"`
	Solana                 SolanaCapabilities       `json:"solana"`
	Verification           VerificationCapabilities `json:"verification"`
	Channels               ChannelCapabilities      `json:"channels"`
	TwoFactor              TwoFactorCapabilities    `json:"two_factor"`
	Languages              []string                 `json:"languages"`
	Paths                  MountPaths               `json:"paths"`
}

Capabilities is the public, static feature discovery.

type ChannelCapabilities added in v0.148.0

type ChannelCapabilities struct {
	Email bool `json:"email"`
	SMS   bool `json:"sms"`
}

ChannelCapabilities says which contact channels can deliver now: a sender is configured and its latest health check, if any, passed.

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(trusted, cloudflare []netip.Prefix) ClientIPFunc

ClientIPFromForwardedHeaders derives the client IP behind proxies the host declared. A peer inside trusted or cloudflare enables the right-to-left X-Forwarded-For walk (hops in either set are skipped as our own). Only a peer inside cloudflare may additionally be trusted for CF-Connecting-IP, and only as a fallback when X-Forwarded-For yields nothing: a generic reverse proxy forwards CF-Connecting-IP verbatim, so honouring it from any trusted peer let a client pick its own rate-limit key (ak#298). Any other peer resolves to itself.

Hosts that pass a cloudflare set must also lock the origin down to Cloudflare ingress; otherwise a client that reaches the origin directly is its own peer and both headers are ignored, which is the safe outcome.

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.

type CodeOrLinkRequest added in v0.148.0

type CodeOrLinkRequest struct {
	Identifier string `json:"identifier"`
	Code       string `json:"code"`
	Token      string `json:"token"`
}

type CookieVariant

type CookieVariant struct {
	Kind   cookieKind
	Name   string
	Path   string
	Domain string // AuthKit never sets Domain: every variant is host-only
	Secure bool   // issued on HTTPS deployments (always true for __Host-)
	// Current marks the variant AuthKit issues now, per Secure mode.
	Current bool
}

CookieVariant is one cookie shape AuthKit issues. An OIDC state name is a prefix completed by stateCookieName.

func CurrentCookie

func CurrentCookie(kind cookieKind, secure bool) CookieVariant

func (CookieVariant) Identity

func (v CookieVariant) Identity() string

Identity names a variant in testdata/cookie-registry.golden.

type DelegatedTokenRequest added in v0.148.0

type DelegatedTokenRequest struct {
	// TTLSeconds is an optional override, clamped into the configured
	// floor/ceiling; absent or <= 0 mints the configured default.
	TTLSeconds int `json:"ttl_seconds"`
	// Audiences is an optional narrowing; every requested audience must be in
	// the configured allowlist. Absent mints the full configured list.
	Audiences []string `json:"audiences"`
	// DelegateCertificateDERB64URL is the delegate's public X.509 leaf as
	// unpadded base64url DER; the token is bound to exactly this certificate.
	// Omitted when a DPoP proof binds the token instead.
	DelegateCertificateDERB64URL string `json:"delegate_certificate_der_b64url"`
	// RequestedGrant is one host-schema JSON object passed to the authorizer
	// verbatim and never copied into the token.
	RequestedGrant json.RawMessage `json:"requested_grant"`
}

type DeviceKeyEnrollBeginRequest added in v0.148.0

type DeviceKeyEnrollBeginRequest struct {
	Email     string `json:"email"`
	PublicKey string `json:"public_key"`
	Label     string `json:"label"`
}

type DeviceKeyEnrollFinishRequest added in v0.148.0

type DeviceKeyEnrollFinishRequest struct {
	EnrollmentID string `json:"enrollment_id"`
	Code         string `json:"code"`
	Signature    string `json:"signature"`
	SecondFactor string `json:"code_2fa"`
}

type DeviceKeyEnrollment added in v0.148.0

type DeviceKeyEnrollment struct {
	EnrollmentID string    `json:"enrollment_id"`
	Challenge    string    `json:"challenge"`
	ExpiresAt    time.Time `json:"expires_at"`
}

DeviceKeyEnrollment is an enrollment ceremony in progress: the challenge to sign, beside the code emailed to the address.

type DeviceKeyLoginBeginRequest added in v0.148.0

type DeviceKeyLoginBeginRequest struct {
	DeviceKeyID string `json:"device_key_id"`
}

type DeviceKeyLoginChallenge added in v0.148.0

type DeviceKeyLoginChallenge struct {
	ChallengeID string    `json:"challenge_id"`
	Challenge   string    `json:"challenge"`
	ExpiresAt   time.Time `json:"expires_at"`
}

DeviceKeyLoginChallenge is the challenge a device key signs to sign in.

type DeviceKeyLoginFinishRequest added in v0.148.0

type DeviceKeyLoginFinishRequest struct {
	ChallengeID string `json:"challenge_id"`
	Signature   string `json:"signature"`
}

type EmailChangeRequest added in v0.149.0

type EmailChangeRequest struct {
	Email string `json:"email"`
}

type EnrollmentStep added in v0.149.0

type EnrollmentStep struct {
	TokenSet       iam.TokenSet          `json:"token_set"`
	AllowedMethods []iam.TwoFactorMethod `json:"allowed_methods"`
}

EnrollmentStep is a sign-in waiting on a first second factor. TokenSet is a restricted enrollment token, not a session.

type ExternalLoginProvider added in v0.148.0

type ExternalLoginProvider struct {
	ID                   string `json:"id"`
	Name                 string `json:"name"`
	SupportsLogin        bool   `json:"supports_login"`
	SupportsRegistration bool   `json:"supports_registration"`
	SupportsLink         bool   `json:"supports_link"`
}

type Feature added in v0.148.0

type Feature string

Feature is the configuration a route needs to be mounted.

const (
	Always              Feature = ""
	FeaturePasskeys     Feature = "passkeys"     // Passkeys.RPID set
	FeaturePasswordless Feature = "passwordless" // passwordless login on
	FeatureRegistration Feature = "registration" // registration not closed
	FeatureTwoFactor    Feature = "two_factor"   // two-factor authentication not disabled
	FeatureSolana       Feature = "solana"       // a Solana network set
	FeatureOIDC         Feature = "oidc"         // an identity provider configured
	FeatureDelegated    Feature = "delegated"    // delegated-token audiences declared
	FeatureDeviceKeys   Feature = "device_keys"  // device keys on
	FeatureGroups       Feature = "groups"       // a persona besides root
	FeatureAPIKeys      Feature = "api_keys"     // a persona whose groups hold API keys
)

type FreshAuth added in v0.148.0

type FreshAuth = authflow.FreshAuth

FreshAuth is the session's step-up state after a re-authentication.

type GroupOp

type GroupOp int

GroupOp is the operation a group route performs.

const (
	OpMembersList GroupOp = iota + 1
	OpMemberSet
	OpMemberRemove
	OpRolesList
	OpAPIKeysList
	OpAPIKeyMint
	OpAPIKeyRevoke
	OpInvitationsList
	OpInvitationCreate
	OpInvitationRevoke
)

func (GroupOp) Available

func (op GroupOp) Available(p rbac.Persona) bool

Available reports whether groups of persona p have the operation. Every group, root included, has members, roles and invitations.

func (GroupOp) Mutates added in v0.149.0

func (op GroupOp) Mutates() bool

Mutates reports whether the operation changes the group.

func (GroupOp) Perms

func (op GroupOp) Perms(p rbac.Persona) []iam.Perm

Perms returns the permissions of persona p that admit the operation: any one of them suffices. A root invitation without a role invites someone to register (root:users:invite); the engine tells the two apart.

type GroupQuery added in v0.148.0

type GroupQuery struct {
	GroupID string `query:"group_id"`
}

type IdentifierPasswordRequest added in v0.148.0

type IdentifierPasswordRequest struct {
	Identifier string `json:"identifier"`
	Password   string `json:"password"`
}

type IdentifierRequest added in v0.148.0

type IdentifierRequest struct {
	Identifier string `json:"identifier"`
}

type InvitationCreateRequest added in v0.148.0

type InvitationCreateRequest struct {
	Role      string     `json:"role"`
	Email     string     `json:"email"`
	ExpiresAt *time.Time `json:"expires_at"`
}

InvitationCreateRequest makes an invite link (no email), or emails an invitation. A root invitation with an email and no role invites someone to register.

type InvitationRedeemRequest added in v0.149.0

type InvitationRedeemRequest struct {
	Code string `json:"code"`
}

type LabelRequest added in v0.148.0

type LabelRequest struct {
	Label string `json:"label"`
}

type MemberListQuery added in v0.148.0

type MemberListQuery struct {
	PageQuery
	Kind   []string `query:"kind"`
	Role   []string `query:"role"`
	Expand []string `query:"expand"`
}

MemberListQuery filters a group's members; kind and role repeat, and expand=user adds each user member's PublicUser.

type MemberRoleRequest added in v0.149.0

type MemberRoleRequest struct {
	Role string `json:"role"`
}

MemberRoleRequest is the role a member holds in the group.

type Mount

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

Mount is the canonical HTTP handler and its route catalog. Framework adapters use the catalog to register native routes, delegating requests to ServeHTTP so AuthKit still owns path values, authentication, JSON and cookie guards.

func NewMount

func NewMount(svc *Service) (result *Mount, err error)

NewMount builds the full AuthKit surface — JSON API, browser OIDC and JWKS — as ONE net/http handler plus its route catalog, as Config.HTTP declares it. Every route keeps the gate its RouteSpec carries; the mount adds no auth and removes none. Excluding a route does not alter the MFA-enrollment exempt set, so a shadowed enroll route stays reachable through the host's replacement.

func (*Mount) Routes

func (m *Mount) Routes() []iam.Route

Routes returns a copy of the configured endpoints, including JWKS and enabled document/OIDC routes; GET endpoints also have a HEAD entry. It never advertises disabled or excluded endpoints.

func (*Mount) ServeHTTP

func (m *Mount) ServeHTTP(w http.ResponseWriter, r *http.Request)

type MountPaths added in v0.148.0

type MountPaths struct {
	API  string  `json:"api"`
	OIDC *string `json:"oidc"`
	JWKS *string `json:"jwks"`
}

MountPaths are the serving mount's anchors as full paths, so a client that knows one AuthKit URL finds the rest; null when not mounted.

type OIDCCallbackQuery added in v0.148.0

type OIDCCallbackQuery struct {
	State  string `query:"state"`
	Code   string `query:"code"`
	Error  string `query:"error"`
	Format string `query:"format"`
}

type OIDCExchangeRequest added in v0.149.0

type OIDCExchangeRequest struct {
	Code string `json:"code"`
}

OIDCExchangeRequest trades a browser OIDC result's one-time code.

type OIDCLoginQuery added in v0.148.0

type OIDCLoginQuery struct {
	UI         string `query:"ui"`
	PopupNonce string `query:"popup_nonce"`
	ReturnTo   string `query:"return_to"`
}

type OIDCLoginStartRequest added in v0.149.0

type OIDCLoginStartRequest struct {
	ReturnTo   string `json:"return_to"`
	InviteCode string `json:"invite_code"`
	UI         string `json:"ui"`
	PopupNonce string `json:"popup_nonce"`
}

type OIDCStart added in v0.148.0

type OIDCStart struct {
	AuthURL string `json:"auth_url"`
	State   string `json:"state"`
}

OIDCStart is where to send the browser to sign in with a provider.

type PageQuery added in v0.148.0

type PageQuery struct {
	Cursor string `query:"cursor"`
	Limit  *int   `query:"limit"`
}

PageQuery is ?cursor= and ?limit= of every paged list. The cursor is opaque; limit is 1-500 (default 50).

func (PageQuery) Page added in v0.148.0

func (q PageQuery) Page() (iam.PageRequest, error)

Page is the one page parser: an opaque cursor, and a limit of 1 to iam.MaxPageLimit (default iam.DefaultPageLimit). Any other limit is 400 invalid_request on param limit.

type PasskeyCapabilities added in v0.148.0

type PasskeyCapabilities struct {
	Login bool `json:"login"`
}

type PasswordCapabilities added in v0.148.0

type PasswordCapabilities struct {
	MinLength        int  `json:"min_length"`
	MaxLength        int  `json:"max_length"`
	RequireUppercase bool `json:"require_uppercase"`
	RequireLowercase bool `json:"require_lowercase"`
	RequireDigit     bool `json:"require_digit"`
	RequireSymbol    bool `json:"require_symbol"`
	AllowCommon      bool `json:"allow_common"`
}

PasswordCapabilities is everything a browser needs to pre-validate a new password except the blocklist itself. AllowCommon says the blocklist is off.

type PasswordChangeRequest added in v0.148.0

type PasswordChangeRequest struct {
	CurrentPassword string `json:"current_password"`
	NewPassword     string `json:"new_password"`
}

type PasswordLoginRequest added in v0.148.0

type PasswordLoginRequest struct {
	Identifier string `json:"identifier"` // email, phone number or username
	Password   string `json:"password"`
}

type PasswordRequest added in v0.148.0

type PasswordRequest struct {
	Password string `json:"password"`
}

PasswordRequest carries a password that re-authenticates the session.

type PasswordResetConfirmRequest added in v0.148.0

type PasswordResetConfirmRequest struct {
	Token       string `json:"token"`
	NewPassword string `json:"new_password"`
}

type PasswordlessCapabilities added in v0.148.0

type PasswordlessCapabilities struct {
	Enabled  bool     `json:"enabled"`
	Channels []string `json:"channels"`
}

type PasswordlessStartRequest added in v0.148.0

type PasswordlessStartRequest struct {
	Identifier        string `json:"identifier"`
	Mode              string `json:"mode"`
	ReturnTo          string `json:"return_to"`
	PreferredLanguage string `json:"preferred_language"`
	InviteCode        string `json:"invite_code"`
}

type PermissionSet added in v0.148.0

type PermissionSet struct {
	GroupID     string     `json:"group_id"`
	Role        *iam.Role  `json:"role"`
	Permissions []iam.Perm `json:"permissions"`
}

PermissionSet is the caller's role and effective permissions in one group, expanded over the persona's catalog: set membership, no pattern matching.

type PhoneChangeRequest added in v0.149.0

type PhoneChangeRequest struct {
	PhoneNumber string `json:"phone_number"`
}

type ProfileUpdateRequest added in v0.149.0

type ProfileUpdateRequest struct {
	Username          *string `json:"username"`
	PreferredLanguage *string `json:"preferred_language"`
	AvatarURL         *string `json:"avatar_url"`
}

ProfileUpdateRequest is PATCH /me: an absent field is unchanged; an empty avatar_url clears it.

type ProviderError added in v0.149.0

type ProviderError struct {
	ProviderError string `json:"provider_error"`
}

ProviderError is provider_error's metadata: the identity provider's own error code.

type RateLimitResult

type RateLimitResult struct {
	Allowed      bool
	RetryAfter   time.Duration
	Availability *authflow.ActionAvailability
}

type RateLimiter

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

RateLimiter is a minimal interface used by adapters.

type RateLimiterWithResult

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

type RegisterRequest added in v0.148.0

type RegisterRequest struct {
	Identifier string `json:"identifier"`
	Username   string `json:"username"`
	Password   string `json:"password"`
	InviteCode string `json:"invite_code"`
}

type RegistrationCapabilities added in v0.148.0

type RegistrationCapabilities struct {
	Mode                string `json:"mode"`
	InviteTokenRequired bool   `json:"invite_token_required"`
}

type Reply added in v0.148.0

type Reply struct {
	Status int
	Body   any
}

Reply is one success outcome of a route: its status and body. Body is a zero value of the body's type, nil for none.

type ReturnToRequest added in v0.148.0

type ReturnToRequest struct {
	ReturnTo string `json:"return_to"`
}

type RoleInfo added in v0.148.0

type RoleInfo struct {
	Name        iam.Role   `json:"name"`
	Permissions []iam.Perm `json:"permissions"`
}

RoleInfo is one role of a group's persona and every permission it grants, expanded from its patterns over the persona's catalog.

type RouteSpec

type RouteSpec struct {
	Method  string
	Path    string
	Surface Surface
	Group   iam.RouteGroup
	// Auth is the tier the route enforces before its handler runs.
	Auth iam.RouteAuthTier
	// Perm is the permission the route requires; `<persona>` stands for the
	// addressed group's persona. The route checks it when Auth is
	// AuthPermission; otherwise the operation does.
	Perm string
	// Bucket is the per-IP rate-limit bucket applied in front of the handler
	// ("" = none). Per-identifier and branch-specific buckets stay in the
	// handler.
	Bucket string
	// MountedWhen is the configuration the route needs.
	MountedWhen Feature
	// StepUp: the caller must have signed in recently (a step-up, MFA-fresh
	// when enrolled), checked after the session (M7).
	StepUp bool
	// MFAEnrollmentExempt marks the 2FA enroll/challenge/verify surface a
	// forced-enrollment-gated user must still reach (#243).
	MFAEnrollmentExempt bool
	// Query, Request: the query string and the JSON body (zero values; nil
	// for none). Responses: every success outcome.
	Query     any
	Request   any
	Responses []Reply

	// Handler is the mounted handler, set by APIRoutes and OIDCBrowserRoutes.
	Handler http.Handler
	// contains filtered or unexported fields
}

RouteSpec is one route of AuthKit's HTTP surface: the static catalog entry that mounts it, gates it and documents it. Paths are prefix-neutral, with ServeMux wildcards.

func Catalog added in v0.148.0

func Catalog() []RouteSpec

Catalog is AuthKit's whole HTTP surface, every route a configuration can mount. It needs no database: APIRoutes and OIDCBrowserRoutes select a Service's routes from it, and internal/cmd/contract generates openapi.json and the TypeScript wire types from it.

type SecondFactorStep added in v0.149.0

type SecondFactorStep struct {
	UserID    string            `json:"user_id"`
	Challenge string            `json:"challenge"`
	Factor    TwoFactorFactor   `json:"factor"`
	Factors   []TwoFactorFactor `json:"factors"`
}

SecondFactorStep is a sign-in waiting on its second factor: the challenge to answer, the factor its code went to, and the factors to switch to.

type Service

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

Service wraps the internal AuthKit engine with net/http mounting helpers.

func New

func New(client Backend, cfg config.Config, deps config.Deps) (*Service, error)

New assembles the HTTP layer over the engine, which also authenticates its requests, from the normalized configuration. authkit.New is the only production caller.

func (*Service) APIRoutes

func (s *Service) APIRoutes(groups ...iam.RouteGroup) []RouteSpec

APIRoutes returns this Service's JSON API routes: the catalog's API routes its configuration mounts, in the given groups (all when none), each wrapped in its gate, rate limit and language middleware.

func (*Service) Backend

func (s *Service) Backend() Backend

Backend returns the engine the service drives.

func (*Service) Capabilities

func (s *Service) Capabilities() Capabilities

func (*Service) Close

func (s *Service) Close()

Close stops the background work New started: the memory limiter sweep. The engine and Redis client are borrowed and remain owned by the host. Idempotent; safe on a nil Service.

func (*Service) GroupHandler

func (s *Service) GroupHandler(op GroupOp) http.HandlerFunc

GroupHandler returns the handler for one group route. It:

  1. derives the caller's actor (401 if none; 403 for a delegation);
  2. resolves :group_id (`root` is the root group) to a live group;
  3. refuses a group whose persona lacks the route, like an unknown group;
  4. authorizes the route's permission on the group with the engine's live Can, for every actor kind (403 on deny);
  5. for a change to the root group, requires a user who signed in recently (M7): step_up_required otherwise, 403 for any other actor;
  6. performs the operation, whose engine call applies its own rules.

func (*Service) JWKSHandler

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

JWKSHandler returns a handler for GET /.well-known/jwks.json. The key set is read per request so a hot-reloaded rotation or key removal is published immediately (ak#392).

func (*Service) OIDCBrowserRoutes

func (s *Service) OIDCBrowserRoutes(groups ...iam.RouteGroup) []RouteSpec

OIDCBrowserRoutes returns the browser OIDC routes, prefix-neutral.

type SessionEventQuery added in v0.149.0

type SessionEventQuery struct {
	PageQuery
	Kind []string `query:"kind"`
}

SessionEventQuery pages a session history, newest first; kind repeats.

type SignInKey added in v0.149.0

type SignInKey struct {
	ID         string        `json:"id"`
	Kind       SignInKeyKind `json:"kind"`
	Label      *string       `json:"label"`
	CreatedAt  time.Time     `json:"created_at"`
	LastUsedAt *time.Time    `json:"last_used_at"`
	Current    bool          `json:"current"`
}

SignInKey is one of the caller's passkeys or device keys. Current marks the device key behind the request's token.

type SignInKeyKind added in v0.149.0

type SignInKeyKind string

SignInKeyKind names a sign-in key's protocol.

const (
	SignInKeyPasskey   SignInKeyKind = "passkey"
	SignInKeyDeviceKey SignInKeyKind = "device_key"
)

type SolanaAccount added in v0.148.0

type SolanaAccount struct {
	Address   string `json:"address"`
	PublicKey string `json:"publicKey"`
}

type SolanaCapabilities added in v0.148.0

type SolanaCapabilities struct {
	Login bool `json:"login"`
}

type SolanaChallenge added in v0.148.0

type SolanaChallenge struct {
	Nonce    string    `json:"nonce"`
	IssuedAt time.Time `json:"issued_at"`
	// Message is the Sign-In-With-Solana text the wallet signs.
	Message string `json:"message"`
}

type SolanaChallengeRequest added in v0.148.0

type SolanaChallengeRequest struct {
	Address  string `json:"address"`
	Username string `json:"username"`
}

type SolanaSignInOutput added in v0.148.0

type SolanaSignInOutput struct {
	Account       SolanaAccount `json:"account"`
	Signature     string        `json:"signature"`
	SignedMessage string        `json:"signedMessage"`
}

type SolanaSignInRequest added in v0.148.0

type SolanaSignInRequest struct {
	Output SolanaSignInOutput `json:"output"`
}

SolanaSignInRequest is the wallet-standard sign-in output: the one camelCase body on the wire.

type Surface added in v0.148.0

type Surface string

Surface is where a route is anchored beneath the mount's base path.

const (
	SurfaceAPI  Surface = ""     // the JSON API, beneath the API path
	SurfaceOIDC Surface = "oidc" // browser OIDC navigations, beneath OIDCPath
	SurfaceBase Surface = "base" // the issuer's own paths (JWKS)
)

type TokenRefreshRequest added in v0.148.0

type TokenRefreshRequest struct {
	GrantType string `json:"grant_type"`
	// RefreshToken is empty on cookie mounts, where the cookie carries it.
	RefreshToken string `json:"refresh_token"`
}

type TokenRequest added in v0.148.0

type TokenRequest struct {
	Token string `json:"token"`
}

type TwoFactorCapabilities added in v0.148.0

type TwoFactorCapabilities struct {
	Mode    iam.TwoFactorMode     `json:"mode"`
	Methods []iam.TwoFactorMethod `json:"methods"`
}

TwoFactorCapabilities is the 2FA policy and the second factors a user can enroll now (Client.TwoFactorMethods).

type TwoFactorChallengeRequest added in v0.148.0

type TwoFactorChallengeRequest struct {
	UserID    string `json:"user_id"`
	Challenge string `json:"challenge"`
	FactorID  string `json:"factor_id"`
}

type TwoFactorFactor added in v0.148.0

type TwoFactorFactor struct {
	ID          string  `json:"id"`
	Method      string  `json:"method"`
	IsDefault   bool    `json:"is_default"`
	Destination *string `json:"destination"`
}

TwoFactorFactor is one second factor. Destination is the masked address its codes go to; null for an authenticator app.

type TwoFactorFactorCreateRequest added in v0.149.0

type TwoFactorFactorCreateRequest struct {
	Method      string  `json:"method"`
	Code        string  `json:"code"`
	PhoneNumber *string `json:"phone_number"`
	Default     bool    `json:"default"`
}

TwoFactorFactorCreateRequest adds the factor whose setup code it carries.

type TwoFactorFactorCreated added in v0.149.0

type TwoFactorFactorCreated struct {
	Factor      TwoFactorFactor `json:"factor"`
	BackupCodes []string        `json:"backup_codes"`
	Auth        *AuthResult     `json:"auth"`
}

TwoFactorFactorCreated is a factor added. BackupCodes are the first factor's, shown once ([] otherwise). Auth is the sign-in an enrollment token finished, or the session's fresh token when the code re-verified it; null otherwise.

type TwoFactorFactorUpdateRequest added in v0.149.0

type TwoFactorFactorUpdateRequest struct {
	Default bool `json:"default"`
}

type TwoFactorRequired added in v0.149.0

type TwoFactorRequired struct {
	Method string `json:"method"`
}

TwoFactorRequired is 2fa_required's metadata: the second factor a device-key ceremony must carry.

type TwoFactorSendRequest added in v0.149.0

type TwoFactorSendRequest struct {
	Method string `json:"method"`
}

TwoFactorSendRequest names the second factor a step-up code goes to (the default when empty).

type TwoFactorSetup added in v0.149.0

type TwoFactorSetup struct {
	Method      string  `json:"method"`
	Destination *string `json:"destination"`
	Secret      *string `json:"secret"`
	OTPAuthURI  *string `json:"otpauth_uri"`
}

TwoFactorSetup is a factor's setup under way: where its code went, or the authenticator app's secret.

type TwoFactorSetupRequest added in v0.149.0

type TwoFactorSetupRequest struct {
	Method      string  `json:"method"`
	PhoneNumber *string `json:"phone_number"`
}

TwoFactorSetupRequest starts a factor's setup: a code to the email or phone, or an authenticator app's secret.

type TwoFactorStatus added in v0.148.0

type TwoFactorStatus struct {
	Enabled              bool                  `json:"enabled"`
	Factors              []TwoFactorFactor     `json:"factors"`
	AllowedMethods       []iam.TwoFactorMethod `json:"allowed_methods"`
	BackupCodesRemaining int                   `json:"backup_codes_remaining"`
}

TwoFactorStatus is the caller's second factors.

type TwoFactorStepUpRequest added in v0.148.0

type TwoFactorStepUpRequest struct {
	Code       string `json:"code"`
	Method     string `json:"method"`
	BackupCode bool   `json:"backup_code"`
}

type TwoFactorVerifyRequest added in v0.148.0

type TwoFactorVerifyRequest struct {
	UserID     string `json:"user_id"`
	Code       string `json:"code"`
	Challenge  string `json:"challenge"`
	FactorID   string `json:"factor_id"`
	BackupCode bool   `json:"backup_code"`
}

type UserListQuery added in v0.148.0

type UserListQuery struct {
	PageQuery
	Search      string `query:"search"`
	RootRole    string `query:"root_role"`
	Status      string `query:"status"`
	Sort        string `query:"sort"`
	Order       string `query:"order"`
	Entitlement string `query:"entitlement"`
	Total       bool   `query:"total"`
}

UserListQuery is the admin user directory's query. total=true counts every match into the page's total, at the price of a count.

type UserProfile added in v0.148.0

type UserProfile = authflow.UserProfile

UserProfile is GET /me: the account and its sign-in and naming state.

type UserSecurity added in v0.149.0

type UserSecurity = authflow.UserSecurity

UserSecurity is GET /me/security: the session's freshness and the account's step-up and MFA state.

type UsernameCapabilities added in v0.148.0

type UsernameCapabilities struct {
	MinLength             int               `json:"min_length"`
	MaxLength             int               `json:"max_length"`
	Pattern               string            `json:"pattern"`
	Renames               bool              `json:"renames"`
	RenameIntervalSeconds int64             `json:"rename_interval_seconds"`
	FormerNames           naming.PolicyInfo `json:"former_names"`
}

UsernameCapabilities is the interactive username rule. Pattern is the fixed character rule; length is bounded separately. Renames says whether users may rename themselves, and how often.

type UsersQuery added in v0.149.0

type UsersQuery struct {
	IDs      string `query:"ids"`
	Username string `query:"username"`
}

UsersQuery looks public users up by id (comma-separated, at most 100) or by username (former names resolve too).

type VerificationCapabilities added in v0.148.0

type VerificationCapabilities struct {
	Registration string `json:"registration"`
}

type VerificationStep added in v0.149.0

type VerificationStep struct {
	Identifier string `json:"identifier"`
	Channel    string `json:"channel"`
}

VerificationStep is a sign-in waiting on a contact proof; the code went to Identifier over Channel ("email" or "phone").

type WebAuthnCredential added in v0.148.0

type WebAuthnCredential = json.RawMessage

WebAuthnCredential is a browser's WebAuthn credential response, passed through as the browser produced it.

type WireField added in v0.148.0

type WireField struct {
	Name string
	Type reflect.Type
	// Optional marks an omitempty member, absent when zero: only protocol
	// documents (JWKS) have them.
	Optional bool
	// Tag is the field's full json tag.
	Tag string
}

WireField is one JSON member of an object.

func Fields added in v0.148.0

func Fields(t reflect.Type) []WireField

Fields lists t's JSON members; embedded structs contribute theirs.

type WireKind added in v0.148.0

type WireKind int

WireKind is a Go type's JSON form.

const (
	WireString WireKind = iota
	WireInteger
	WireNumber
	WireBoolean
	WireTime  // RFC 3339 in UTC
	WireBytes // base64
	WireAny   // arbitrary JSON
	WireOpaque
	WireArray
	WireMap
	WireNullable
	WireObject // a named AuthKit struct
	WirePage   // iam.ListPage[T]
)

func KindOf added in v0.148.0

func KindOf(t reflect.Type) WireKind

KindOf is t's JSON form. A struct defined outside AuthKit is opaque.

Jump to

Keyboard shortcuts

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