Documentation
¶
Overview ¶
Package config is the one definition of AuthKit's host configuration: Config (plain data), Deps (everything that reaches outside the process) and the Roles builder. The root package re-exports each type under the same name (authkit.Config is config.Config), so these field docs are the ones hosts read. Normalize applies every default and rule once.
Index ¶
- Constants
- func AuthorizationServerEnabled(a AuthorizationServerConfig) bool
- func CompileRoles(r *Roles) (*rbac.Schema, error)
- func GroupClientsEnabled(a AuthorizationServerConfig) bool
- func MountPath(field, p string) (string, error)
- func NormalizeClientURIs(uris []string) ([]string, error)
- func NormalizeRiverSchema(raw string) (string, error)
- func NormalizeSchema(raw string) (string, error)
- func OAuthClientAllows(c OAuthClientConfig, grant OAuthGrantType) bool
- func OAuthClientConfidential(c OAuthClientConfig) bool
- func OIDCScope(scope string) bool
- func ParseCIDRs(kind string, cidrs []string) ([]netip.Prefix, error)
- func SCIMResource(issuer string) string
- type APIKeysConfig
- type AgreementConfig
- type AuthorizationServerConfig
- type Config
- type CredentialPerms
- type DPoPMode
- type DatabaseConfig
- type Deps
- type DeviceKeysConfig
- type DirectoryPerms
- type EmailSender
- type FormerNamesConfig
- type FormerNamesMode
- type FrontendConfig
- type GroupClientScope
- type GroupClientsConfig
- type HTTPConfig
- type InvitationsConfig
- type KeysConfig
- type LanguageConfig
- type MemberPerms
- type OAuthClientConfig
- type OAuthGrantType
- type PasskeyConfig
- type PasswordPolicy
- type PersonaDef
- func (p *PersonaDef) All() iam.Perm
- func (p *PersonaDef) Declare(perms ...string) []iam.Perm
- func (p *PersonaDef) Expand(grants []iam.Perm) []iam.Perm
- func (p *PersonaDef) Permission(resource, action string) iam.Perm
- func (p *PersonaDef) Permissions() []iam.Perm
- func (p *PersonaDef) RequireMFA(perms ...iam.Perm)
- func (p *PersonaDef) Resource(name string) Resource
- func (p *PersonaDef) Role(name string, grants ...iam.Grant) iam.Role
- type PersonaOption
- type ProvisioningClientCredentials
- type ProvisioningConfig
- type ProvisioningTarget
- type RateLimit
- type RegistrationConfig
- type RemoteApplicationConfig
- type Resource
- type ResourceConfig
- type ResourceServerConfig
- type RolePerms
- type Roles
- type RootDef
- type SMSConfig
- type SMSSender
- type SignInConfig
- type TokenConfig
- type TwoFactorConfig
- type UserPerms
- type UsernameConfig
Constants ¶
const ( DefaultOAuthAccessTokenTTL = 5 * time.Minute MaxOAuthAccessTokenTTL = 15 * time.Minute )
DefaultOAuthAccessTokenTTL is AuthorizationServerConfig.AccessTokenTTL's default; MaxOAuthAccessTokenTTL its ceiling.
const ( DefaultOAuthRefreshTokenTTL = 12 * time.Hour MaxOAuthRefreshTokenTTL = 30 * 24 * time.Hour )
DefaultOAuthRefreshTokenTTL is AuthorizationServerConfig.RefreshTokenTTL's default; MaxOAuthRefreshTokenTTL its ceiling.
const ( DefaultAPIPath = "/api" // APIVersion is the version segment AuthKit owns beneath APIPath: the // JSON API is {BasePath}{APIPath}/v1. A breaking change mounts /v2 beside // it. APIVersion = "/v1" DefaultPasswordMinLength = 8 DefaultPasswordMaxLength = 128 PasswordMaxLengthCeiling = 1024 DefaultUsernameMinLength = 4 DefaultUsernameMaxLength = 30 UsernameMaxLengthCeiling = 64 DefaultRenameInterval = 72 * time.Hour DefaultFormerNameRetention = 90 * 24 * time.Hour DefaultAccountsPerDevice = 5 DefaultAccountsPerAddress = 20 DefaultNewDevicesPerAccount = 10 )
Defaults Normalize applies.
const ( DefaultProvisioningInterval = 5 * time.Minute DefaultProvisioningReconcileInterval = 24 * time.Hour )
DefaultProvisioningInterval and DefaultProvisioningReconcileInterval are ProvisioningConfig's defaults.
const GroupClientIDPrefix = "goc_"
GroupClientIDPrefix starts every group client's id; a declared client's id never does.
const SCIMReadScope = "scim:read"
SCIMReadScope is the scope a client-credentials token needs to read the SCIM service provider.
Variables ¶
This section is empty.
Functions ¶
func AuthorizationServerEnabled ¶ added in v1.5.0
func AuthorizationServerEnabled(a AuthorizationServerConfig) bool
AuthorizationServerEnabled reports whether the authorization server is on.
func CompileRoles ¶
CompileRoles checks the declared model and compiles it, once, into the schema the engine authorizes against; nil is root-only.
func GroupClientsEnabled ¶ added in v1.20.0
func GroupClientsEnabled(a AuthorizationServerConfig) bool
GroupClientsEnabled reports whether some persona registers group OAuth clients.
func MountPath ¶
MountPath normalizes a configured path: surrounding space and trailing slashes are dropped, so "/" is "" (root).
func NormalizeClientURIs ¶ added in v1.20.0
NormalizeClientURIs is the redirect URI rule for a client registered at run time: absolute https (http only on loopback), exact, no fragment.
func NormalizeRiverSchema ¶ added in v1.7.0
NormalizeRiverSchema defaults River's schema to public.
func NormalizeSchema ¶
NormalizeSchema trims and validates a PostgreSQL schema name, defaulting to "profiles". The name is spliced into SQL text, so this is the injection guard.
func OAuthClientAllows ¶ added in v1.5.0
func OAuthClientAllows(c OAuthClientConfig, grant OAuthGrantType) bool
OAuthClientAllows reports whether c may use grant.
func OAuthClientConfidential ¶ added in v1.5.0
func OAuthClientConfidential(c OAuthClientConfig) bool
OAuthClientConfidential reports whether c authenticates with a secret.
func ParseCIDRs ¶
ParseCIDRs parses proxy ranges.
func SCIMResource ¶ added in v1.12.0
SCIMResource is the SCIM service provider beneath issuer: its base URL, and the resource a client lists to get tokens for it.
Types ¶
type APIKeysConfig ¶
type APIKeysConfig struct {
// Prefix brands generated keys (one per deployment): lowercase
// alphanumeric, 1-16 characters. Empty gives the bare "st_" marker.
Prefix string `yaml:"prefix"`
// MaxTTL caps how far ahead a key may expire; a later or absent expiry is
// capped at creation. 0 means no cap.
MaxTTL time.Duration `yaml:"max_ttl"`
}
APIKeysConfig configures opaque permission-group-owned machine credentials.
type AgreementConfig ¶ added in v1.20.0
type AgreementConfig struct {
// Key names it: lowercase letters, digits, '-' and '_', such as "terms".
Key string `yaml:"key"`
// Version is its current version, such as its date. Accepting an
// earlier version does not accept this one.
Version string `yaml:"version"`
// URL is where it is read: an absolute http(s) URL.
URL string `yaml:"url"`
// Reaccept asks a user who accepted an earlier version to accept this one
// when they next sign in (AuthResult agreements_due).
Reaccept bool `yaml:"reaccept"`
}
AgreementConfig is one document users accept (Config.Agreements).
type AuthorizationServerConfig ¶ added in v1.5.0
type AuthorizationServerConfig struct {
// Clients are the registered OAuth clients. None leaves the
// authorization server off.
Clients []OAuthClientConfig `yaml:"clients"`
// Resources are the resource servers access tokens may be minted for
// (RFC 8707 resource indicators).
Resources []ResourceServerConfig `yaml:"resources"`
// AccessTokenTTL is the lifetime of the RFC 9068 access tokens it mints,
// and those a resource server (Config.Resource) mints for its remote
// applications' assertions, which may set it with no Clients. 0
// defaults to 5 minutes; at most 15.
AccessTokenTTL time.Duration `yaml:"access_token_ttl"`
// RefreshTokenTTL bounds a refresh token family: rotation never extends
// it, and the client signs the user in again (prompt=none) after it.
// 0 defaults to 12 hours; at most 30 days. A family also ends with the
// sign-in it was issued from.
RefreshTokenTTL time.Duration `yaml:"refresh_token_ttl"`
// GroupClients is the policy for the OAuth clients groups register at
// run time (personas declared with OAuthClients): third-party clients
// whose users consent to each scope.
GroupClients GroupClientsConfig `yaml:"group_clients"`
// contains filtered or unexported fields
}
AuthorizationServerConfig declares the OAuth clients this deployment signs users in for and the resource servers it mints access tokens for. Clients and resources are configuration only: there is no dynamic registration. Every client is first-party: a signed-in user is never asked to consent.
type Config ¶
type Config struct {
// Database names the PostgreSQL schemas AuthKit's and River's tables live
// in. New creates or upgrades them.
Database DatabaseConfig `yaml:"database"`
// Token is the JWT issuing/verification contract and session limits.
Token TokenConfig `yaml:"token"`
// SignIn limits how sign-ins spread across accounts and devices: one
// person signing in and out of many accounts, and one account shared by
// many people. The zero value is on, with generous limits.
SignIn SignInConfig `yaml:"sign_in"`
// Keys controls signing-key resolution when Deps.KeySource is nil.
Keys KeysConfig `yaml:"keys"`
// Frontend describes host-owned frontend routes used for absolute URLs.
Frontend FrontendConfig `yaml:"frontend"`
// Registration controls verification policy and public self-registration.
Registration RegistrationConfig `yaml:"registration"`
// Agreements are the documents users accept, such as terms and a privacy
// policy, each at its current version. Registration.Agreements names the
// ones every sign-up accepts; the host reads acceptances with
// Client.UserAgreements and gates its own features on them. Published by
// GET {api}/capabilities.
Agreements []AgreementConfig `yaml:"agreements"`
// SMS is the text-message policy: where messages may go.
SMS SMSConfig `yaml:"sms"`
// Password is the rule every password write enforces. The zero value is
// the default policy: 8..128 characters, no composition rules, common
// passwords rejected. Published by GET {api}/capabilities.
Password PasswordPolicy `yaml:"password"`
// Username is the username rule: length, and whether and how often users
// may rename themselves. Published by GET {api}/capabilities.
Username UsernameConfig `yaml:"username"`
// TwoFactor configures MFA.
TwoFactor TwoFactorConfig `yaml:"two_factor"`
// Passkeys configures WebAuthn/FIDO2 passkey ceremonies.
Passkeys PasskeyConfig `yaml:"passkeys"`
// DeviceKeys enables the refreshless native-client device-key surface.
// Off by default: enrollment is an email-code login, so hosts opt in
// explicitly before RouteDeviceKeys is mounted or the engine issues
// enrollment or login challenges.
DeviceKeys DeviceKeysConfig `yaml:"device_keys"`
// APIKeys configures opaque permission-group-owned machine credentials.
APIKeys APIKeysConfig `yaml:"api_keys"`
// AuthorizationServer makes this deployment an OAuth 2.0 authorization
// server and OpenID provider for its registered clients: they sign users
// in here and receive tokens for registered resource servers. The zero
// value leaves it off and its routes unmounted.
AuthorizationServer AuthorizationServerConfig `yaml:"authorization_server"`
// Resource makes this deployment a resource server: Client.Authenticator
// also admits the RFC 9068 access tokens minted for Resource.ID, by this
// deployment's authorization server and by its trusted issuers (remote
// applications). The zero value admits none.
Resource ResourceConfig `yaml:"resource"`
// Invitations turns invitations off. The zero value leaves them on.
Invitations InvitationsConfig `yaml:"invitations"`
// Provisioning pushes the accounts to SCIM 2.0 service providers. The
// zero value pushes nothing.
Provisioning ProvisioningConfig `yaml:"provisioning"`
// Roles is the permission model: personas, their permissions and roles
// (NewRoles). Nil is root-only.
Roles *Roles `yaml:"-"`
// RemoteApplications declares the remote applications root controls, as
// the whole set: New registers each one and disables any this deployment
// declared at an earlier boot and no longer does. A removed application
// is disabled, not deleted: its tokens stop at once, and it keeps its
// roles for when it is declared again. Nil leaves the stored applications
// alone. Applications registered through an operation
// (Client.UpsertRemoteApplication, the bootstrap manifest) or declared by
// a deployment sharing the account store are never touched.
RemoteApplications []RemoteApplicationConfig `yaml:"remote_applications"`
// Languages declares the supported languages: the HTTP surface negotiates
// the request's among them, and messages fall back to Default.
Languages LanguageConfig `yaml:"languages"`
// SolanaNetwork turns on Sign In With Solana for one chain; the zero value
// leaves it off. Solana Name Service resolution is built in.
SolanaNetwork iam.SolanaNetwork `yaml:"solana_network"`
// SenderHealthInterval is how often Start re-runs the senders'
// CheckHealth; 0 defaults to five minutes.
SenderHealthInterval time.Duration `yaml:"sender_health_interval"`
// SessionEventRetention is how long session-event history rows
// (sign-ins and revocations, with IP and user agent: personal data) are
// kept. 0 defaults to 365 days; a negative value keeps them forever.
SessionEventRetention time.Duration `yaml:"session_event_retention"`
// CleanupInterval is how often expired auth state is cleaned up; 0
// defaults to one hour.
CleanupInterval time.Duration `yaml:"cleanup_interval"`
// HTTP configures the HTTP surface. Nil keeps the Client headless:
// operations and Verifier only.
HTTP *HTTPConfig `yaml:"http"`
}
Config is the host configuration: plain data and policy. Everything that reaches outside the process (the pool, senders, keys, providers, hooks) is in Deps. authkit.New normalizes it once.
type CredentialPerms ¶
type CredentialPerms struct {
Resource
Read iam.Perm // list the group's API keys and OAuth clients
Manage iam.Perm // mint, revoke and re-role them; register and change clients
}
CredentialPerms are the credential permissions, registered with APIKeys, RemoteApplications or OAuthClients.
type DatabaseConfig ¶ added in v1.8.0
type DatabaseConfig struct {
// Schema is the PostgreSQL schema AuthKit's tables live in. Empty
// defaults to "profiles". Deployments that must not share accounts on one
// database use different schemas; deployments that share accounts use the
// same one (see TokenConfig.AccountIssuers). It must match
// ^[a-z_][a-z0-9_]*$ (max 63 bytes).
Schema string `yaml:"schema"`
// RiverSchema holds the River tables AuthKit's jobs (account lifecycle,
// events, cleanup) run in; empty defaults to "public". Start runs AuthKit's
// own River client there, and a host fleet passed to Start with
// WithRiverClient must use the same schema.
RiverSchema string `yaml:"river_schema"`
}
DatabaseConfig names the PostgreSQL schemas of AuthKit's tables. New creates them, and creates or upgrades the tables, before anything else touches the database: the pool in Deps.Postgres owns and uses them.
type Deps ¶
type Deps struct {
// Postgres is the durable store, required by every host-facing
// constructor. New creates or upgrades AuthKit's and River's tables
// through it, so its role owns and uses them. It also holds AuthKit's
// short-lived auth state (codes, ceremonies, attempt counters), shared by
// every replica.
Postgres *pgxpool.Pool
// KeySource signs and publishes tokens. Nil resolves keys from
// Config.Keys. Hosts never handle the private key: they hand AuthKit a
// source that signs.
KeySource keys.Source
// Providers are the external identity providers: provider.Google,
// Apple, Discord and GitHub, or provider.OIDC and OAuth2 for any other.
Providers []provider.Provider
// Email delivers email. Nil means no email: flows that need one fail
// unless Config.Registration.AllowMissingSenders is set. Start runs its
// CheckHealth now and every Config.SenderHealthInterval; while it fails,
// email flows are unavailable (Client.EmailAvailable).
Email EmailSender
// SMS delivers text messages, like Email (Client.SMSAvailable).
SMS SMSSender
// Entitlements returns the names of users' active entitlements (billing
// tiers), keyed by user id; ids without any are absent. Admin views show
// them all; Config.Token.EntitlementAllowlist selects which go into access
// tokens.
Entitlements func(ctx context.Context, userIDs []string) (map[string][]string, error)
// EntitlementHolders returns the ids of the users who hold entitlement,
// for ListUsers' Entitlement filter. Nil makes that filter fail with
// iam.ErrEntitlementFilterUnavailable.
EntitlementHolders func(ctx context.Context, entitlement string) ([]string, error)
// OnEvent receives account and group changes (iam.Event) durably through
// River: recorded in the change's transaction, delivered after commit at
// least once, in order per user (per group for group events). A failure
// is retried with backoff up to an hour apart and holds back that
// subject's later events. It must be idempotent on Event.ID, ignore kinds
// it does not know and never run in the change's transaction. Every
// account issuer with OnEvent receives the account events. Building a
// client with OnEvent subscribes its issuer: changes are recorded from
// then on, even while no fleet runs. Clients without it change nothing
// until one starts the issuer's fleet: that unsubscribes the issuer, and
// its fleet drains what is pending.
OnEvent func(context.Context, iam.Event) error
// OnPurge erases the host's data of a deleted account before AuthKit
// purges the account, 30 days after its deletion. It runs durably through
// River on every account issuer, and the purge waits until each has
// succeeded; a failure is retried. It must be idempotent and honor
// cancellation.
OnPurge func(context.Context, iam.UserDeletion) error
// DeletionCheck runs before a user deletes their own account: an
// iam.RefuseDeletion error refuses it with deletion_refused (409, the
// reason in metadata.reason), such as while the user's cards still pay
// subscriptions; any other error fails the request. Deleting someone
// else's account (staff, the host) does not run it.
DeletionCheck func(ctx context.Context, userID string) error
// ConsentRevocationCheck runs before a user withdraws their own consent
// to a group OAuth client: an iam.RefuseConsentRevocation error refuses
// it with consent_revocation_refused (409, metadata.reason), such as
// while the link it made still pays subscriptions; any other error
// fails the request. Client.RevokeConsent does not run it.
ConsentRevocationCheck func(ctx context.Context, userID, clientID string) error
// GroupName is a group's name, as the host knows it (a merchant's
// verified name): the consent screen and a user's connected apps show it
// beside a group OAuth client's own name. Nil shows the client's alone.
GroupName func(ctx context.Context, groupID string) (string, error)
// OAuthGrants decides each jwt-bearer grant of the authorization
// server: it may refuse or narrow a workload's capability. Required
// when a client declares AuthorizationDetailsTypes, as every jwt-bearer
// client does.
OAuthGrants iam.OAuthGrantAuthorizer
// NameAdmission is the host's side-effect-free username policy for
// account creation and renames; an error refuses the name.
NameAdmission func(context.Context, iam.NameAdmissionRequest) error
// Redis shares rate-limit counters and spent DPoP proofs across
// replicas; it holds no other AuthKit state. Without it, and while it
// fails, each process keeps its own: one node only.
Redis redis.UniversalClient
// ResourceHosts admits hosts besides Config.Resource.PublicURL's that the
// resource answers on (a host's per-tenant API hosts): a DPoP proof's htu
// may name https://<host> when it reports true for the request's Host.
// No header is trusted otherwise.
ResourceHosts func(ctx context.Context, host string) (bool, error)
// ClientIP extracts the client address, replacing the proxy handling of
// HTTPConfig.
ClientIP func(*http.Request) string
// Wrap decorates every API and browser-OIDC handler at mount time.
Wrap func(iam.Route, http.Handler) http.Handler
}
Deps is everything AuthKit reaches outside the process through: the store, keys, identity providers, senders and the host's hooks. Senders are provider objects; every hook is a func, so bind one late with a closure when it needs the Client first.
type DeviceKeysConfig ¶
type DeviceKeysConfig struct {
// Enabled mounts RouteDeviceKeys and lets the engine run enrollment and
// login ceremonies.
Enabled bool `yaml:"enabled"`
}
DeviceKeysConfig controls the native-client device-key surface.
type DirectoryPerms ¶ added in v1.18.0
type DirectoryPerms struct {
Resource
Read iam.Perm // read the directory
Manage iam.Perm // provision it: create, replace, patch and delete users
}
DirectoryPerms are the directory permissions, registered with RemoteApplications: the group's remote applications' users, provisioned over SCIM (docs/scim.md).
type EmailSender ¶ added in v0.149.0
type EmailSender interface {
Send(ctx context.Context, msg iam.EmailMessage) error
// CheckHealth reports, without sending, whether email can be delivered
// now: nil when healthy, or when the provider can't tell.
CheckHealth(ctx context.Context) error
}
EmailSender delivers email; adapters/smtp.New returns one.
type FormerNamesConfig ¶
type FormerNamesConfig struct {
// Mode is FormerNamesFinite (the default), FormerNamesForever or
// FormerNamesImmediate.
Mode FormerNamesMode `yaml:"mode"`
// Duration is how long a finite reservation lasts; 0 defaults to 90 days.
Duration time.Duration `yaml:"duration"`
}
FormerNamesConfig keeps a renamed-away username reserved for its owner, and resolving to them, for a while.
type FormerNamesMode ¶
type FormerNamesMode string
FormerNamesMode says how long a former username stays reserved.
const ( // FormerNamesFinite reserves it for FormerNamesConfig.Duration. FormerNamesFinite FormerNamesMode = "finite" // FormerNamesForever reserves it for good. FormerNamesForever FormerNamesMode = "forever" // FormerNamesImmediate frees it at once. FormerNamesImmediate FormerNamesMode = "immediate" )
type FrontendConfig ¶
type FrontendConfig struct {
// BaseURL builds absolute links (password reset, verification, invites).
// Empty defaults to Token.Issuer when that is a URL.
BaseURL string `yaml:"base_url"`
// OIDCReturnPath is the SPA route AuthKit redirects to after it finishes a
// browser sign-in with an identity provider (not the provider callback,
// which AuthKit owns). Empty defaults to "/login/callback".
OIDCReturnPath string `yaml:"oidc_return_path"`
// VerifyPath receives scanner-safe verification link landings. Empty
// defaults to "/verify".
VerifyPath string `yaml:"verify_path"`
// PasswordResetPath receives scanner-safe password reset link landings.
// Empty defaults to "/reset".
PasswordResetPath string `yaml:"password_reset_path"`
// PasswordlessPath receives passwordless sign-in links. Empty defaults to
// "/passwordless".
PasswordlessPath string `yaml:"passwordless_path"`
// InvitePath receives group invitation links (?code=…); the SPA posts the
// code to the redeem route. Empty defaults to "/accept-invite".
InvitePath string `yaml:"invite_path"`
// AuthorizePath receives an OAuth client's sign-in request
// (?authorization=…) when the authorization server is on: the SPA signs
// the user in, then approves the request through the API. Empty defaults
// to "/authorize".
AuthorizePath string `yaml:"authorize_path"`
}
FrontendConfig describes host-owned frontend routes.
type GroupClientScope ¶ added in v1.20.0
type GroupClientScope struct {
// Name is the scope; one of Resource's Scopes.
Name string `yaml:"name"`
// Resource is the resource server (ResourceServerConfig.ID) a token
// carrying it is for.
Resource string `yaml:"resource"`
// Description says what consenting allows, on the consent screen.
Description string `yaml:"description"`
}
GroupClientScope is one scope a group client may request.
func FindGroupClientScope ¶ added in v1.20.0
func FindGroupClientScope(a AuthorizationServerConfig, name string) (GroupClientScope, bool)
FindGroupClientScope returns the group-client scope named name.
type GroupClientsConfig ¶ added in v1.20.0
type GroupClientsConfig struct {
// Scopes are the scopes a group client may request beyond OpenID's
// (openid, email, phone, profile), each for one resource, with the
// description the consent screen shows.
Scopes []GroupClientScope `yaml:"scopes"`
// Agreements are keys of Config.Agreements a user accepts, at their
// current versions, before approving any group client.
Agreements []string `yaml:"agreements"`
}
GroupClientsConfig is what a group's OAuth client may ask of a user.
type HTTPConfig ¶
type HTTPConfig struct {
// Groups selects the mounted route groups. Nil mounts the default API
// surface plus browser OIDC; non-nil mounts exactly the named groups.
Groups []iam.RouteGroup `yaml:"groups"`
// BasePath roots the whole surface. Empty derives it from Token.Issuer's
// path ("https://example.com/auth" gives "/auth"); when the issuer is a
// URL a set value must equal that path, because verifiers find JWKS at
// the issuer plus iam.JWKSPath. Serve the paths unchanged: no StripPrefix
// in front.
BasePath string `yaml:"base_path"`
// APIPath is the JSON API's prefix beneath BasePath; AuthKit adds the
// version segment, /v1, after it. Empty means "/api"; "/" puts /v1 right
// beneath BasePath.
APIPath string `yaml:"api_path"`
// PublicURL is where clients reach BasePath when a proxy in front changes
// the origin or the path, such as "https://shop.example.com/sso". DPoP
// proofs sent to the token endpoint, and jwt-bearer assertions' aud, must
// name PublicURL plus its path beneath BasePath. Empty defaults to Token.Issuer's origin plus
// BasePath.
PublicURL string `yaml:"public_url"`
// Exclude drops routes the host serves itself, named as iam.Route.Pattern
// names them ("GET /.well-known/jwks.json"). An entry matching no route is
// an error.
Exclude []string `yaml:"exclude"`
// RefreshCookie delivers the rotating refresh token as an HttpOnly cookie
// (iam.RefreshCookieName) instead of a JSON field. Browser mounts only:
// the SPA and this handler must share an origin.
RefreshCookie bool `yaml:"refresh_cookie"`
// RateLimits overlays bucket limits onto authkit.DefaultRateLimits;
// unknown buckets are refused. Limits are in memory and per process unless
// Deps.Redis shares them.
RateLimits map[string]RateLimit `yaml:"rate_limits"`
// RedisKeyPrefix namespaces the rate-limit keys in Deps.Redis so
// deployments can share one Redis. Empty derives "authkit:<schema>:".
RedisKeyPrefix string `yaml:"redis_key_prefix"`
// TrustedProxies are the CIDRs of reverse proxies whose X-Forwarded-For
// is honoured.
TrustedProxies []string `yaml:"trusted_proxies"`
// CloudflareProxies are Cloudflare's egress ranges: X-Forwarded-For plus
// CF-Connecting-IP. Set them only where Cloudflare fronts an origin locked
// down to it.
CloudflareProxies []string `yaml:"cloudflare_proxies"`
// DirectPeerIP asserts nothing sits in front: RemoteAddr is the client.
DirectPeerIP bool `yaml:"direct_peer_ip"`
}
HTTPConfig configures the HTTP surface: one handler serving the JSON API, browser OIDC and JWKS, every route beneath BasePath:
{BasePath}{APIPath}/v1/... JSON API
{BasePath}/oidc/{provider}/... browser OIDC
{BasePath}/.well-known/jwks.json JWKS
Exactly what sits in front of AuthKit must be declared (TrustedProxies, CloudflareProxies, DirectPeerIP or Deps.ClientIP), or every client shares one proxy's per-IP rate-limit bucket.
type InvitationsConfig ¶ added in v1.3.0
type InvitationsConfig struct {
// Disabled turns them off: no invitation is issued or honoured. The
// invitation routes are not mounted, GET {api}/capabilities reports
// invitations.enabled false, and CreateInvitation, redeeming a code and
// registering with one return iam.ErrInvitationsDisabled. Listing and
// revoking earlier invitations still work. Registration.NativeUserMode
// "invite_only" cannot be combined with it.
Disabled bool `yaml:"disabled"`
}
InvitationsConfig controls invitations: invite links and emailed invitations into a group, and emailed invitations to register.
type KeysConfig ¶
type KeysConfig struct {
// Path is the directory holding keys.json (hot-reloaded on rotation) and
// totp.key. Empty defaults to /vault/auth. With no keys.json, New fails
// unless AllowEphemeralDevKeys or VerifyOnly is set.
Path string `yaml:"path"`
// AllowEphemeralDevKeys generates an RSA signing key when Path holds no
// keys.json, and a TOTP key when it holds no totp.key: in memory, or
// written to Path when it is set so restarts reuse them. Development only.
AllowEphemeralDevKeys bool `yaml:"allow_ephemeral_dev_keys"`
// VerifyOnly builds AuthKit with no signer: minting returns
// iam.ErrSigningNotConfigured, verification and permission reads work, and
// JWKS serves an empty set. Key resolution is skipped.
VerifyOnly bool `yaml:"verify_only"`
}
KeysConfig controls signing-key resolution when Deps.KeySource is nil. AuthKit reads no environment variables: binaries read their environment once and set these fields.
type LanguageConfig ¶
type LanguageConfig struct {
// Supported are the languages requests may select; empty accepts any.
Supported []string `yaml:"supported"`
// Default is the language when neither the account nor the request
// chooses one; empty defaults to "en".
Default string `yaml:"default"`
}
LanguageConfig declares the supported languages as two-letter codes. The zero value is English only.
type MemberPerms ¶
type MemberPerms struct {
Resource
Read iam.Perm // see who holds which role, and the role catalog
Manage iam.Perm // give someone a role, change it or take it away; invites
}
MemberPerms are a persona's built-in membership permissions.
type OAuthClientConfig ¶ added in v1.5.0
type OAuthClientConfig struct {
// ID is the client_id: 1-128 characters of letters, digits, '.', '_',
// '-' and ':'.
ID string `yaml:"id"`
// Name is shown to the user while they sign in for it; empty uses ID.
Name string `yaml:"name"`
// SecretSHA256 makes the client confidential: the lowercase hex SHA-256
// of its secret, which must be at least 32 random bytes. AuthKit never
// holds the secret. Empty makes the client public (a browser or native
// app, or a fleet of workloads using the jwt-bearer grant), which must
// use DPoP and cannot use client credentials.
SecretSHA256 string `yaml:"secret_sha256"`
// RedirectURIs are the exact redirect_uri values the client may use:
// absolute https URLs, or http on a loopback host, without a fragment.
RedirectURIs []string `yaml:"redirect_uris"`
// PostLogoutRedirectURIs are the exact post_logout_redirect_uri values
// RP-initiated logout may return to; the same rules apply.
PostLogoutRedirectURIs []string `yaml:"post_logout_redirect_uris"`
// GrantTypes are the grants the client may use. Empty allows
// authorization_code.
GrantTypes []OAuthGrantType `yaml:"grant_types"`
// Resources are the resource identifiers (ResourceServerConfig.ID) the
// client may request tokens for. A request names one with the resource
// parameter; with none, the access token is good for userinfo only.
Resources []string `yaml:"resources"`
// Permissions are a client-credentials client's own grants, as grant
// patterns: its tokens carry them within the resource's ceiling.
Permissions []string `yaml:"permissions"`
// Origins are browser origins ("https://admin.example.com") the client
// calls the token endpoint from, besides its redirect URIs' origins: a
// host frontend using token exchange.
Origins []string `yaml:"origins"`
// AuthorizationDetailsTypes are the RFC 9396 authorization_details types
// a jwt-bearer client's capabilities may carry ("hub_operation"). The
// host's grant authorizer (Deps.OAuthGrants) decides each grant, so
// declaring any needs one.
AuthorizationDetailsTypes []string `yaml:"authorization_details_types"`
// Agreements are keys of Config.Agreements a user accepts, at their
// current versions, before approving the client's sign-in: approval
// answers agreement_required until they do.
Agreements []string `yaml:"agreements"`
}
OAuthClientConfig registers one OAuth client.
func FindOAuthClient ¶ added in v1.5.0
func FindOAuthClient(a AuthorizationServerConfig, id string) (OAuthClientConfig, bool)
FindOAuthClient returns the registered client with id.
type OAuthGrantType ¶ added in v1.5.0
type OAuthGrantType string
OAuthGrantType is an OAuth 2.0 grant type a client may use.
const ( // GrantAuthorizationCode is the authorization code grant with PKCE. GrantAuthorizationCode OAuthGrantType = "authorization_code" // GrantRefreshToken issues rotating refresh tokens with the code grant. GrantRefreshToken OAuthGrantType = "refresh_token" // GrantTokenExchange is RFC 8693 token exchange: a frontend trades the // user's AuthKit access token for a resource's access token. GrantTokenExchange OAuthGrantType = "urn:ietf:params:oauth:grant-type:token-exchange" // GrantClientCredentials is a confidential client acting for itself. GrantClientCredentials OAuthGrantType = "client_credentials" // GrantJWTBearer is the RFC 7523 JWT-bearer grant: a workload's key // signs an assertion carrying a capability one of the user's device keys // signed for it, and proves itself with DPoP. GrantJWTBearer OAuthGrantType = "urn:ietf:params:oauth:grant-type:jwt-bearer" )
type PasskeyConfig ¶
type PasskeyConfig struct {
RPID string `yaml:"rp_id"`
RPDisplayName string `yaml:"rp_display_name"`
Origins []string `yaml:"origins"`
UserVerification string `yaml:"user_verification"`
}
PasskeyConfig configures the WebAuthn relying party. Empty fields derive from Frontend.BaseURL.
type PasswordPolicy ¶
type PasswordPolicy struct {
MinLength int `yaml:"min_length"`
MaxLength int `yaml:"max_length"`
RequireUppercase bool `yaml:"require_uppercase"`
RequireLowercase bool `yaml:"require_lowercase"`
RequireDigit bool `yaml:"require_digit"`
RequireSymbol bool `yaml:"require_symbol"`
// AllowCommon admits passwords on AuthKit's embedded common-password
// blocklist, which the zero value refuses.
AllowCommon bool `yaml:"allow_common"`
}
PasswordPolicy is the password rule, NIST SP 800-63B-style by default. Lengths count Unicode code points; 0 defaults to 8 and 128, and MaxLength is at most 1024. Composition rules are opt-in: uppercase, lowercase and digit use Unicode categories, and a symbol is any rune that is neither a letter nor a digit.
func NormalizePassword ¶
func NormalizePassword(out PasswordPolicy) (PasswordPolicy, error)
NormalizePassword returns the policy with its zero lengths defaulted.
type PersonaDef ¶
type PersonaDef struct {
Persona iam.Persona
// Owner is the role every persona has: it holds All(). Root's also holds
// every other persona's All(). A group's creator can be seeded with it
// (iam.NewGroup.Owner).
Owner iam.Role
Members MemberPerms
Credentials CredentialPerms
Directory DirectoryPerms
Roles RolePerms
// contains filtered or unexported fields
}
PersonaDef is one declared persona: the permissions and roles of its groups. AuthKit registers the built-in permission fields: Members always, Credentials with APIKeys, RemoteApplications or OAuthClients, Directory with RemoteApplications, Roles with CustomRoles. A role holding one that is not registered fails New.
func (*PersonaDef) All ¶
func (p *PersonaDef) All() iam.Perm
All is `<persona>:*`: every permission of the persona.
func (*PersonaDef) Declare ¶ added in v1.7.0
func (p *PersonaDef) Declare(perms ...string) []iam.Perm
Declare declares permissions given whole, `<persona>:<resource>:<action>`, such as strings read from configuration, and returns them in order. A built-in among them is returned as it is; any other follows Permission's rules.
func (*PersonaDef) Expand ¶ added in v1.1.0
func (p *PersonaDef) Expand(grants []iam.Perm) []iam.Perm
Expand lists every catalog permission some grant covers, in catalog order, such as a role's grants (Client.RolePermissions) or an identity's (Client.EffectivePermissions): the owner's `<persona>:*` lists each permission. GET /me/permissions answers the same expansion. It reads no database.
func (*PersonaDef) Permission ¶
func (p *PersonaDef) Permission(resource, action string) iam.Perm
Permission declares the permission `<persona>:<resource>:<action>` and returns it.
func (*PersonaDef) Permissions ¶ added in v1.1.0
func (p *PersonaDef) Permissions() []iam.Perm
Permissions is the persona's catalog: the permissions declared with Permission and the built-ins AuthKit registers, sorted.
func (*PersonaDef) RequireMFA ¶
func (p *PersonaDef) RequireMFA(perms ...iam.Perm)
RequireMFA marks permissions, or patterns over the persona's catalog, that need a second factor: a subject holding a grant that reaches one, through any role, include or root role, must have MFA enrolled, and no API key or application may hold it. root:members:manage and root:users:manage always need MFA.
func (*PersonaDef) Resource ¶
func (p *PersonaDef) Resource(name string) Resource
Resource is one resource of the persona, for the pattern over all its actions.
func (*PersonaDef) Role ¶
Role declares a role held in the persona's groups and returns it. Each grant is a permission or pattern (Resource.All, All), or a role of this persona whose permissions the new role includes. A persona role holds only its own persona's permissions; a root role may hold any persona's, and applies in every group of that persona. A name starting `custom-` is a custom role's, never a declared one's.
type PersonaOption ¶
type PersonaOption uint8
PersonaOption switches on a persona capability.
const ( // APIKeys mounts the group API-key routes. It registers Credentials. APIKeys PersonaOption = iota + 1 // RemoteApplications lets the persona's groups control remote // applications (Client.UpsertRemoteApplication). It registers Credentials. RemoteApplications // CustomRoles lets the persona's groups define roles of their own // (Client.CreateGroupRole). It registers Roles. CustomRoles // OAuthClients lets the persona's groups register OAuth clients that // sign their users in here, with their consent // (Client.CreateGroupOAuthClient). It registers Credentials. OAuthClients )
type ProvisioningClientCredentials ¶ added in v1.12.0
type ProvisioningClientCredentials struct {
TokenURL string `yaml:"token_url"`
ClientID string `yaml:"client_id"`
ClientSecret string `yaml:"client_secret"`
// Scopes and Resource (RFC 8707) are sent with the token request when
// set.
Scopes []string `yaml:"scopes"`
Resource string `yaml:"resource"`
}
ProvisioningClientCredentials is an OAuth 2.0 client-credentials client (RFC 6749 §4.4) whose access tokens authenticate to a target.
type ProvisioningConfig ¶ added in v1.12.0
type ProvisioningConfig struct {
// Targets are the service providers. A target removed from the list is
// forgotten, with its pending changes, when this issuer's River fleet
// starts.
Targets []ProvisioningTarget `yaml:"targets"`
// Interval is how often the pending changes are sent; 0 defaults to five
// minutes.
Interval time.Duration `yaml:"interval"`
// ReconcileInterval is how often each target's users are listed and
// compared with the accounts, repairing what drifted; 0 defaults to a
// day, and a negative value turns reconciliation off.
ReconcileInterval time.Duration `yaml:"reconcile_interval"`
}
ProvisioningConfig pushes the accounts to SCIM 2.0 service providers (RFC 7643, RFC 7644): each target receives every account and keeps it current. A change to what a SCIM User shows (email, username, display name, deletion, ban) is recorded in the change's transaction, and every Interval a River job sends each target its pending users' latest state in SCIM bulk requests. It needs Deps.Postgres and Start.
type ProvisioningTarget ¶ added in v1.12.0
type ProvisioningTarget struct {
// Name identifies the target in its status and logs: 1-64 lowercase
// letters, digits, '-' and '_'. Renaming a target makes a new one,
// which gets a full initial sync.
Name string `yaml:"name"`
// URL is the SCIM base URL, beneath which /Users and /Bulk are served
// ("https://billing.example.com/billing/v1/app/scim/v2").
URL string `yaml:"url"`
// Handler serves the SCIM endpoints in process instead of URL, so an
// embedded service provider is called with no network. Requests reach it
// with paths relative to the base ("/Users", "/Bulk").
Handler http.Handler `yaml:"-"`
// BearerToken is a static credential sent as Authorization: Bearer.
BearerToken string `yaml:"bearer_token"`
// ClientCredentials gets the access token from an OAuth 2.0 token
// endpoint instead.
ClientCredentials *ProvisioningClientCredentials `yaml:"client_credentials"`
}
ProvisioningTarget is one SCIM service provider: its base URL or an in-process handler, and how AuthKit authenticates to it.
type RateLimit ¶
RateLimit allows at most Limit requests per Window in one bucket, with an optional Cooldown between accepted requests.
type RegistrationConfig ¶
type RegistrationConfig struct {
// Verification is "none" (the default), "optional" or "required". Every
// policy stores the address unverified until proven; "optional" also
// sends a code at registration. Unproven accounts cannot add sign-in
// methods.
Verification iam.RegistrationVerificationPolicy `yaml:"verification"`
// NativeUserMode controls public self-registration: "open" (the default),
// "invite_only" or "closed". The host operations (CreateUser, bootstrap,
// import) work in every mode.
NativeUserMode iam.RegistrationMode `yaml:"native_user_mode"`
// PasswordlessLogin enables contact-based passwordless sessions.
PasswordlessLogin bool `yaml:"passwordless_login"`
// PasswordlessAutoRegistration lets a verified unknown contact create a
// passwordless account during passwordless confirmation.
PasswordlessAutoRegistration bool `yaml:"passwordless_auto_registration"`
// AllowMissingSenders lets flows that deliver codes and links proceed with
// no email or SMS sender: nothing is delivered and the engine hands the
// code back to its caller (dev rigs read it there). By default a missing
// sender is an error.
AllowMissingSenders bool `yaml:"allow_missing_senders"`
// VerificationSendTimeout bounds each in-line email or SMS send so an
// unreachable provider cannot hang the request. 0 defaults to 15s.
VerificationSendTimeout time.Duration `yaml:"verification_send_timeout"`
// Agreements are the keys of Config.Agreements every self-registration
// accepts at their current version: a sign-up by password, code or
// identity provider without them is refused with agreement_required, and
// a passwordless code stays valid for the retry that accepts them. A
// Solana or device-key sign-up carries none, so it creates no account
// while this is set. Host operations (CreateUser, imports, SCIM) record
// none.
Agreements []string `yaml:"agreements"`
}
RegistrationConfig controls verification policy and public self-registration.
type RemoteApplicationConfig ¶ added in v1.3.0
type RemoteApplicationConfig struct {
// Issuer is the iss of the tokens it signs: an absolute http(s) URL.
Issuer string `yaml:"issuer"`
// JWKSURI is where its keys are fetched; PublicKeys is a static key list
// instead. Set exactly one.
JWKSURI string `yaml:"jwks_uri"`
PublicKeys []iam.RemoteApplicationKey `yaml:"public_keys"`
// Disabled keeps it registered and refuses its tokens.
Disabled bool `yaml:"disabled"`
// Role is the role it holds in its group: the ceiling of what its tokens
// may do there. Zero holds none.
Role iam.Role `yaml:"role"`
// RoleMap maps a role name its tokens carry (RFC 9068 §2.2.3.1 roles) to
// a role of its group, for an issuer that cannot mint the group's
// permissions.
RoleMap map[string]iam.Role `yaml:"role_map"`
}
RemoteApplicationConfig declares one remote application, keyed by Issuer: an issuer whose access tokens this deployment accepts for the group that declares it (root for Config.RemoteApplications), within Role. Only the system changes it (trust root manual).
type Resource ¶
type Resource struct {
// contains filtered or unexported fields
}
Resource is one resource of a persona.
type ResourceConfig ¶ added in v1.18.0
type ResourceConfig struct {
// ID is the resource identifier (RFC 8707): an accepted access token's
// aud must contain it. An absolute URI without a fragment, usually the
// API's base URL.
ID string `yaml:"id"`
// PublicURL is where clients reach the API, the origin a DPoP proof's
// htu names (RFC 9449 §4.3): "https://api.example.com", or with the path
// a proxy strips. Empty is ID's origin. Deps.ResourceHosts admits more
// hosts.
PublicURL string `yaml:"public_url"`
// Scopes are the resource's scopes and the permission ceiling each one
// grants (RFC 6749 §3.3), as grant patterns: an access token's
// permissions count only within the ceilings of the scopes it was
// granted. A scope with no permissions grants none. Empty applies no
// scope ceiling.
Scopes map[string][]string `yaml:"scopes"`
}
ResourceConfig makes this deployment a resource server (RFC 9068): its Authenticator admits the access tokens (at+jwt) minted for ID by this deployment's authorization server and by its trusted issuers, the remote applications. The zero value admits none.
func (ResourceConfig) Enabled ¶ added in v1.18.0
func (r ResourceConfig) Enabled() bool
Enabled reports whether this deployment accepts access tokens as a resource server.
type ResourceServerConfig ¶ added in v1.5.0
type ResourceServerConfig struct {
// ID is the resource identifier, the access token's aud: an absolute URI
// without a fragment, usually the API's base URL.
ID string `yaml:"id"`
// Scopes are the OAuth scopes the resource defines; a client may request
// any of them for it.
Scopes []string `yaml:"scopes"`
// Permissions is the resource's permission ceiling, as grant patterns in
// its own namespace ("merchant:*", "merchant:subscriptions:update"). An
// access token for it carries, as permissions, the user's live grants on
// the root group (what this deployment's roles assign them) intersected
// with this ceiling, so the resource server authorizes from the token.
// Empty mints tokens with no permissions.
Permissions []string `yaml:"permissions"`
// ContactClaims puts the user's contact in every access token for the
// resource, whatever scopes it carries: the OIDC claims email and
// email_verified, preferred_username, name and updated_at (seconds since
// the epoch, when one of them last changed). A resource that keeps its
// own copy of who a user is learns a new user from the first request.
// Other resources' tokens carry only what their scopes grant.
ContactClaims bool `yaml:"contact_claims"`
}
ResourceServerConfig registers one resource server: an API that accepts this deployment's RFC 9068 access tokens.
func FindResourceServer ¶ added in v1.5.0
func FindResourceServer(a AuthorizationServerConfig, id string) (ResourceServerConfig, bool)
FindResourceServer returns the registered resource server with id.
type RolePerms ¶ added in v1.19.0
type RolePerms struct {
Resource
Read iam.Perm // read what the group's roles grant
Manage iam.Perm // create, change and delete the group's custom roles
}
RolePerms are the role permissions, registered with CustomRoles.
type Roles ¶
type Roles struct {
// Root is the persona with exactly one group, the whole site. A role held
// on root applies in every group and may hold any persona's permissions.
Root *RootDef
// contains filtered or unexported fields
}
Roles is the app's permission model: its personas, their permissions and their roles. Every declaration returns a typed value (iam.Persona, iam.Perm, iam.Role) that the app then passes to AuthKit, so a misspelled name is a compile error, not a silent deny. Declare it once, typically in a package-level var block, and pass it as Config.Roles. New reads it and reports every declaration error; changes after New have no effect.
A persona is a type of permission group (channel, org, merchant). A permission group is one instance of a persona, created at run time by the host (Client.CreateGroup) for an entity of its own, such as the channel /c/golang. root is the persona with exactly one group, the whole site; it always exists. A permission is `<persona>:<resource>:<action>`; `*` may replace the action (`channel:posts:*`) or everything after the persona (`channel:*`, the owner).
func NewRoles ¶
func NewRoles(opts ...PersonaOption) *Roles
NewRoles starts a permission model holding only root; opts switch on root's capabilities.
func (*Roles) Persona ¶
func (r *Roles) Persona(name string, opts ...PersonaOption) *PersonaDef
Persona declares a persona and returns its definition. name is the first segment of every permission of its groups: `[a-z][a-z0-9-]*`.
type RootDef ¶
type RootDef struct {
*PersonaDef
Users UserPerms
}
RootDef is root: a persona, plus the account administration permissions AuthKit registers on it.
type SMSConfig ¶ added in v1.20.0
type SMSConfig struct {
// AllowedCountries are the ISO 3166-1 alpha-2 regions text messages may
// go to, such as "US" and "CA"; a number elsewhere is refused with
// phone_country_not_allowed before anything is sent. Empty allows every
// region.
AllowedCountries []string `yaml:"allowed_countries"`
}
SMSConfig is the text-message policy. Every message also passes the send limits of HTTPConfig.RateLimits' sms_* buckets (per number, account, client address and destination country) when the HTTP surface is mounted.
type SMSSender ¶ added in v0.149.0
type SMSSender interface {
Send(ctx context.Context, msg iam.SMSMessage) error
// CheckHealth reports, without sending, whether messages can be delivered
// now: nil when healthy, or when the provider can't tell.
CheckHealth(ctx context.Context) error
}
SMSSender delivers text messages; adapters/twilio.NewSMS returns one.
type SignInConfig ¶ added in v1.3.0
type SignInConfig struct {
// AccountsPerDevice caps the distinct accounts that sign in, or are
// registered, from one device in 24 hours. Signing back into one of them
// is always allowed; the next other account is refused with 429
// too_many_accounts. 0 defaults to 5; negative turns it off.
AccountsPerDevice int `yaml:"accounts_per_device"`
// AccountsPerAddress is AccountsPerDevice for a client without a device
// cookie, counted per client address, which many people may share. 0
// defaults to 20; negative turns it off.
AccountsPerAddress int `yaml:"accounts_per_address"`
// NewDevicesPerAccount caps the new devices that sign in to one account
// in 24 hours. A device that signed in to it within 30 days is not new.
// Past the cap, a new device enters a code sent to the account's proven
// email or phone (status device_verification_required); an account with
// neither is refused with 429 too_many_devices. A sign-in that proved the
// owner's email or phone, or a second factor, needs no code. 0 defaults
// to 10; negative turns it off.
NewDevicesPerAccount int `yaml:"new_devices_per_account"`
// DPoP is how this deployment issues tokens to its own users (RFC 9449):
// their sign-in sessions and its authorization server's user grants.
// Optional, the default, lets each client choose at sign-in: a DPoP key
// binds the session for good, none gives bearer tokens. Required refuses
// a sign-in, a user grant or a refresh without a proof. It never changes
// how tokens are validated: a bound token needs its proof, an unbound one
// is a bearer token, whoever issued it. API keys, client credentials and
// service tokens are never covered.
DPoP DPoPMode `yaml:"dpop"`
}
SignInConfig limits distinct accounts and devices over a rolling 24 hours. A device is a browser's device cookie (set by the HTTP surface); a client without one is known by its address (per /64 for IPv6). The counts live in the short-lived store every replica shares, never in a history.
func NormalizeSignIn ¶ added in v1.3.0
func NormalizeSignIn(c SignInConfig) SignInConfig
NormalizeSignIn applies the sign-in limit defaults; a negative limit is off and stays negative.
type TokenConfig ¶
type TokenConfig struct {
// Issuer is this deployment's JWT issuer (required), for example
// "https://myapp.com". Its path, if any, is where the HTTP surface lives.
Issuer string `yaml:"issuer"`
// IssuedAudiences are the audiences every issued token carries (at least
// one).
IssuedAudiences []string `yaml:"issued_audiences"`
// ExpectedAudiences are the audiences verification accepts; empty
// defaults to IssuedAudiences.
ExpectedAudiences []string `yaml:"expected_audiences"`
// AccessTokenDuration is the access-token lifetime; 0 defaults to 15
// minutes, the longest a revoked session's token passes stateless checks.
AccessTokenDuration time.Duration `yaml:"access_token_duration"`
// RefreshTokenDuration is the refresh-session lifetime; 0 or less means
// sessions do not expire by age.
RefreshTokenDuration time.Duration `yaml:"refresh_token_duration"`
// SessionMaxPerUser caps concurrent refresh sessions per user, evicting
// the oldest. 0 defaults to 3; a negative value means unlimited.
SessionMaxPerUser int `yaml:"session_max_per_user"`
// RefreshRotationGrace is how long a just-rotated refresh token keeps being
// answered with the successor it rotated into instead of being read as
// reuse and ending the session. It covers two holders of one token
// refreshing at once (a shared credential file, a retried request). 0
// defaults to 30s; a negative value makes rotation strictly single-use.
RefreshRotationGrace time.Duration `yaml:"refresh_rotation_grace"`
// EntitlementAllowlist selects the provider-granted entitlement names
// (Deps.Entitlements) that access tokens carry. Empty skips the mint-time
// lookup and omits the claim.
EntitlementAllowlist []string `yaml:"entitlement_allowlist"`
// AccountIssuers lists every issuer whose deployment shares this account
// store (the same Schema on the same database), e.g. two sites with
// separate logins over one set of accounts. Account-level revocations
// (admin emergency revoke, password or contact changes, ban, deletion)
// cover refresh sessions on all of them, and they share membership: who
// holds which role, root included. Each declares its own Roles: a role's
// permissions are per app, and each app re-checks only the credentials it
// issued. Issuer is always included; empty means Issuer alone. Every
// deployment sharing the store should list the same set.
AccountIssuers []string `yaml:"account_issuers"`
// AllowPrivateNetworkJWKS permits http and private or loopback JWKS URLs
// for remote applications and the issuers verifiers trust, and turns off
// the SSRF guard on remote applications' JWKS URLs. Local development only.
AllowPrivateNetworkJWKS bool `yaml:"allow_private_network_jwks"`
}
TokenConfig is the JWT issuing/verification contract plus session limits.
type TwoFactorConfig ¶
type TwoFactorConfig struct {
// Mode is the account-wide policy: iam.TwoFactorDisabled,
// iam.TwoFactorOptional (the default) or iam.TwoFactorRequired (every user
// enrolls before normal session use). Persona.RequireMFA enforces MFA per
// permission; the root owner always needs it.
Mode iam.TwoFactorMode `yaml:"mode"`
// Methods are the enabled second-factor channels; empty enables email,
// SMS and TOTP. A method whose dependency is missing (SMS with no sender)
// is unavailable regardless. Unless Mode is disabled, New refuses a
// deployment with none available: the root owner always needs MFA.
Methods []iam.TwoFactorMethod `yaml:"methods"`
// TOTPSecretKey encrypts stored authenticator-app secrets: 16, 24 or 32 raw
// bytes. It overrides <Keys.Path>/totp.key; with neither, TOTP enrollment
// is unavailable.
TOTPSecretKey []byte `yaml:"totp_secret_key"`
}
TwoFactorConfig configures MFA.
type UserPerms ¶
type UserPerms struct {
Resource
Read iam.Perm // look through accounts and their sign-in history
Ban iam.Perm // ban and unban
Delete iam.Perm // delete an account, or restore it within its 30 days
Manage iam.Perm // edit someone else's account and sign them out everywhere
Invite iam.Perm // invite someone to create an account
}
UserPerms are root's account administration permissions.
type UsernameConfig ¶
type UsernameConfig struct {
// MinLength and MaxLength bound the length; 0 defaults to 4 and 30, and
// MaxLength is at most 64.
MinLength int `yaml:"min_length"`
MaxLength int `yaml:"max_length"`
// Renames lets users change their own username; off by default.
Renames bool `yaml:"renames"`
// RenameInterval is the least time between two renames of one account. 0
// defaults to 72 hours; a negative value means no wait.
RenameInterval time.Duration `yaml:"rename_interval"`
// FormerNames is what happens to a username its owner renamed away from.
FormerNames FormerNamesConfig `yaml:"former_names"`
}
UsernameConfig is the username rule. The characters are fixed: a letter, then letters, digits and underscores.
func NormalizeUsername ¶
func NormalizeUsername(u UsernameConfig) (UsernameConfig, error)
NormalizeUsername applies the username defaults and rules.