Documentation
¶
Index ¶
- Constants
- func DefaultRateLimits() map[string]ratelimit.Limit
- func JWKSHandler(jwks jwtkit.JWKS) http.Handler
- func LanguageMiddleware(cfg *LanguageConfig) func(http.Handler) http.Handler
- func MountHandler(svc *Service, opts MountOptions) (http.Handler, error)
- type ActionAvailability
- type AuthCapabilities
- type AuthPasskeyCapabilities
- type AuthPasswordCapabilities
- type AuthPasswordlessCapabilities
- type AuthProviderSummary
- type AuthRegistrationCapabilities
- type AuthSolanaCapabilities
- type AuthUsernameCapabilities
- type AuthVerificationCapabilities
- type ClientIPFunc
- type Config
- type DocumentProvider
- type LanguageConfig
- type Mount
- type MountOptions
- type MountedRoute
- type RateLimitResult
- type RateLimiter
- type RateLimiterWithResult
- type RouteAuthTier
- type RouteGroup
- type RouteRef
- type RouteSpec
- type Service
- func (s *Service) APIRoutes(groups ...RouteGroup) []RouteSpec
- func (s *Service) CheckSMSHealth(ctx context.Context) error
- func (s *Service) Close()
- func (s *Service) JWKSHandler() http.Handler
- func (s *Service) OIDCBrowserRoutes(groups ...RouteGroup) []RouteSpec
- func (s *Service) PermissionGroupRoutes() []RouteSpec
- func (s *Service) SMSAvailable() bool
- func (s *Service) SMSHealthy() bool
- func (s *Service) Verifier() *verify.Verifier
Constants ¶
const ( ActionUpdateUsername = authkit.ActionUpdateUsername ActionRequestPasswordReset = authkit.ActionRequestPasswordReset ActionRequestVerification = authkit.ActionRequestVerification )
const ( // 2FA-specific rate limit buckets RL2FAStartPhone = "auth_2fa_start_phone" RL2FAStartTOTP = "auth_2fa_start_totp" RL2FAStartEmail = "auth_2fa_start_email" RL2FAEnable = "auth_2fa_enable" RL2FADisable = "auth_2fa_disable" RL2FARegenerateCodes = "auth_2fa_regenerate_codes" RL2FAVerify = "auth_2fa_verify" RLAuthToken = "auth_token" RLAuthRegister = "auth_register" RLAuthRegisterAvailability = "auth_register_availability" RLAuthRegisterAbandon = "auth_register_abandon" RLInviteCreate = "auth_invite_create" RLPasswordLogin = "auth_password_login" RLPasswordStepUp = "auth_password_step_up" RLPasswordlessStart = "auth_passwordless_start" RLPasswordlessConfirm = "auth_passwordless_confirm" RLPasskeyRegister = "auth_passkey_register" RLPasskeyLogin = "auth_passkey_login" RLDeviceKeyEnrollBegin = "auth_device_key_enroll_begin" RLDeviceKeyEnrollFinish = "auth_device_key_enroll_finish" RLDeviceKeyLoginBegin = "auth_device_key_login_begin" RLDeviceKeyLoginFinish = "auth_device_key_login_finish" RLDeviceKeysManage = "auth_device_keys_manage" RLAuthLogout = "auth_logout" RLAuthSessionsList = "auth_sessions_list" RLAuthSessionsRevoke = "auth_sessions_revoke" RLAuthSessionsRevokeAll = "auth_sessions_revoke_all" // #264 application self-registration (per-IP AND per-domain/slug keys). RLApplicationRegister = "application_register" // #264 anti-squat velocity: group settings (slug rename IS a claim), // keyed per-IP and per-user. RLGroupSettings = "group_settings" // #263 anti-squat velocity: generated persona-instance creation (a create // IS a claim), keyed per-IP and per-user. RLGroupCreate = "group_create" // #261 delegated-token mint (authenticated; bounds signing cost per IP). RLDelegatedTokenMint = "delegated_token_mint" RLPasswordResetRequest = "auth_pwd_reset_request" RLPasswordResetConfirm = "auth_pwd_reset_confirm" // #312: one bucket per contact flow, whichever channel the identifier names. RLVerifyRequest = "auth_verify_request" RLVerifyConfirm = "auth_verify_confirm" RLRegisterResend = "auth_register_resend" RLContactChangeRequest = "auth_contact_change_request" RLOIDCStart = "auth_oidc_start" RLOIDCCallback = "auth_oidc_callback" RLUserPasswordChange = "auth_user_password_change" RLUserMe = "auth_user_me" RLUserUpdateUsername = "auth_user_update_username" RLUserPreferredLanguage = "auth_user_preferred_language" RLUserDelete = "auth_user_delete" RLUserUnlinkProvider = "auth_user_unlink_provider" RLAdminUserSessionsList = "auth_admin_user_sessions_list" // The admin session route revokes ALL of a user's sessions; there is no // single-session admin revoke, so no RLAdminUserSessionsRevoke bucket. RLAdminUserSessionsRevokeAll = "auth_admin_user_sessions_revoke_all" // Solana SIWS authentication RLSolanaChallenge = "auth_solana_challenge" RLSolanaLogin = "auth_solana_login" RLSolanaLink = "auth_solana_link" )
Bucket names used by authkit endpoints.
const ( DefaultAPIPrefix = "/api/v1" DefaultOIDCPath = "/oidc" JWKSPath = "/.well-known/jwks.json" // DocumentsPath is the root-anchored published-document surface (#260). // Addressable in ExcludeRoutes as GET DocumentsPath (dropping GET+HEAD). DocumentsPath = "/.well-known/authkit/documents/{digest}" )
Mount anchors. JWKS and browser OIDC are root-anchored by spec/convention (verifiers derive the JWKS URL from the issuer; OIDC redirect URIs are registered with providers), while the JSON API is prefix-anchored. The resolution (#250): MountHandler is ONE handler mounted at the HOST ROOT — JWKS at JWKSPath, browser OIDC under DefaultOIDCPath, API under APIPrefix.
const AccessTokenType = jwtkit.AccessTokenType
AccessTokenType is the canonical JOSE `typ` header value for an AuthKit user access token.
const DelegatedAccessTokenType = jwtkit.DelegatedAccessTokenType
DelegatedAccessTokenType is the canonical JOSE `typ` header value for a delegated access token.
const InsecureRefreshCookieName = "authkit_rt"
InsecureRefreshCookieName is used only on plain-HTTP deployments (local development), where browsers refuse __Host- cookies.
const RefreshCookieName = "__Host-authkit_rt"
RefreshCookieName is the refresh cookie on HTTPS deployments. Browsers accept a __Host- cookie only when it is Secure, host-only and Path=/, so a sibling subdomain can neither plant nor shadow it. Every name and path AuthKit has used lives in the cookie registry (cookies.go).
const RemoteApplicationAccessTokenType = jwtkit.RemoteApplicationAccessTokenType
RemoteApplicationAccessTokenType is the JOSE `typ` for a remote application access token. AuthKit resolves authority from the stored remote_application assignment, never from role claims in the token.
Variables ¶
This section is empty.
Functions ¶
func DefaultRateLimits ¶
DefaultRateLimits returns AuthKit's built-in per-endpoint rate limits.
These limits are enforced per client IP (as determined by the Service's ClientIPFunc). Hosts can override by supplying their own limiter via WithRateLimiter(...).
func JWKSHandler ¶
JWKSHandler serves the public JWKS document for the given key set.
func LanguageMiddleware ¶
func LanguageMiddleware(cfg *LanguageConfig) func(http.Handler) http.Handler
LanguageMiddleware infers request language and attaches it to the request context.
func MountHandler ¶ added in v0.84.0
func MountHandler(svc *Service, opts MountOptions) (http.Handler, error)
MountHandler returns the full AuthKit surface — JSON API, browser OIDC, and JWKS — as ONE framework-neutral net/http handler. The host mounts it once (a gin host uses gin.WrapH) and rewrites nothing. Every route keeps the gate its RouteSpec carries; the mount adds no auth and removes none.
Types ¶
type ActionAvailability ¶
type ActionAvailability = authkit.ActionAvailability
type AuthCapabilities ¶
type AuthCapabilities struct {
Registration AuthRegistrationCapabilities `json:"registration"`
ExternalLoginProviders []AuthProviderSummary `json:"external_login_providers"`
Username AuthUsernameCapabilities `json:"username"`
Password AuthPasswordCapabilities `json:"password"`
Passwordless AuthPasswordlessCapabilities `json:"passwordless"`
Passkeys AuthPasskeyCapabilities `json:"passkeys"`
Solana AuthSolanaCapabilities `json:"solana"`
Verification AuthVerificationCapabilities `json:"verification"`
Languages []string `json:"languages,omitempty"`
}
AuthCapabilities is the public, static auth feature-discovery response.
type AuthPasskeyCapabilities ¶
type AuthPasskeyCapabilities struct {
Login bool `json:"login"`
}
type AuthPasswordCapabilities ¶
type AuthPasswordCapabilities struct {
Login bool `json:"login"`
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"`
RejectCommon bool `json:"reject_common"`
}
AuthPasswordCapabilities publishes everything a browser needs to pre-validate a new password except the blocklist itself.
type AuthProviderSummary ¶
type AuthSolanaCapabilities ¶
type AuthSolanaCapabilities struct {
Login bool `json:"login"`
}
type AuthUsernameCapabilities ¶ added in v0.130.0
type AuthUsernameCapabilities struct {
MinLength int `json:"min_length"`
MaxLength int `json:"max_length"`
Pattern string `json:"pattern"`
}
AuthUsernameCapabilities publishes the interactive username rule. Pattern is the fixed character rule; length is bounded separately.
type AuthVerificationCapabilities ¶
type AuthVerificationCapabilities struct {
Registration string `json:"registration"`
}
type ClientIPFunc ¶
ClientIPFunc determines the client IP used for rate limiting and auditing.
Returning an empty string means "unknown" and causes rate limiting to fail open.
func ClientIPFromForwardedHeaders ¶
func ClientIPFromForwardedHeaders(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 Config ¶ added in v0.98.0
type Config struct {
// Mount configures the complete HTTP inventory once on the local runtime.
// It is consumed by Runtime.ConfigureHTTP; framework mounting adds no policy.
Mount MountOptions
// DPoPRequestURL returns the externally visible delegation endpoint URL when
// a proxy rewrites its path. Nil uses embedded.Config.Token.Issuer's origin and the
// received escaped path. Never derive it from untrusted forwarding headers.
DPoPRequestURL func(*http.Request) string
// Redis overrides the engine's Redis client for the HTTP layer's OIDC/SIWS
// state caches and rate limiter. Nil reuses embedded.Deps.Redis (#210), so
// most hosts never set it.
Redis *redis.Client
// RateLimits overlays bucket-specific limits onto DefaultRateLimits (#242).
RateLimits map[string]ratelimit.Limit
// Limiter replaces AuthKit's automatic limiter. ADVANCED: normal
// deployments let AuthKit own the policy (Redis-backed when Redis is wired,
// in-memory otherwise). RateLimits are not applied to a custom limiter.
Limiter RateLimiter
// DisableRateLimiting turns rate limiting off. TESTS ONLY: it removes the
// brute-force and spam protection.
DisableRateLimiting bool
// Client-IP posture (ak#299). Exactly what sits in front of AuthKit must be
// declared — behind an undeclared proxy every client shares the proxy's one
// per-IP rate-limit bucket. One of the four is required.
//
// TrustedProxies are the CIDRs of reverse proxies / load balancers whose
// X-Forwarded-For is honoured (walked right-to-left past our own hops).
// CF-Connecting-IP is never trusted from these peers.
TrustedProxies []string
// CloudflareProxies are Cloudflare's published egress ranges: X-Forwarded-For
// like a trusted proxy plus CF-Connecting-IP when that header is absent.
// Set it ONLY where Cloudflare fronts the origin, and lock the origin down
// to Cloudflare ingress.
CloudflareProxies []string
// DirectPeerIP asserts nothing sits in front: RemoteAddr IS the end client.
DirectPeerIP bool
// ClientIP is a bespoke extraction strategy. ADVANCED: it replaces the
// proxy handling above entirely.
ClientIP ClientIPFunc
// Languages declares the supported UI languages; the zero value is
// English-only.
Languages LanguageConfig
// Documents are the published-document providers (normally
// *documents.Service values) served at the RouteDocuments mount and
// stamped by the delegated-token mint route (#260/#261). Requires
// embedded.Config.Documents.Readers.
Documents []DocumentProvider
}
Config is the HTTP layer's configuration. Engine data lives in embedded.Config and engine dependencies in embedded.Deps; this is only what the transport itself decides: client-IP posture, rate limiting, languages, published documents.
func (Config) BuildHTTP ¶ added in v0.115.0
func (cfg Config) BuildHTTP(runtime embedded.HTTPBackend) (embedded.HTTPSurface, error)
BuildHTTP implements embedded.HTTPConfiguration for a local Runtime. Hosts set embedded.Config.HTTP; construction and cleanup stay runtime-owned.
type DocumentProvider ¶ added in v0.91.0
type DocumentProvider interface {
// Reference is the process snapshot reference stamped into minted tokens.
Reference() documents.Reference
// Lookup serves any persisted digest for the publication route.
Lookup(ctx context.Context, digest string) (documents.SignedDocument, error)
// CurrentDigest re-validates (and repairs) the persisted snapshot artifact.
CurrentDigest(ctx context.Context) (string, error)
// EnsureSigningKID re-signs the artifact when it is not signed by the key
// that just minted a token referencing it.
EnsureSigningKID(ctx context.Context, tokenKID string) error
}
DocumentProvider is the published-document seam shared by the publication route (#260) and the delegated-token mint's document stamping (#261). *documents.Service implements it.
type LanguageConfig ¶
LanguageConfig declares the supported UI languages and default. The query parameter name is NOT configurable — hardcoded to langSelector ("lang") (#143). No language config means English-only (Supported ["en"], default "en").
type Mount ¶ added in v0.108.0
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 ¶ added in v0.108.0
func NewMount(svc *Service, opts MountOptions) (result *Mount, err error)
NewMount constructs the same handler as MountHandler and exposes the route catalog generated during registration. Hosts using a framework adapter can let that adapter call this internally; net/http hosts can use MountHandler.
func (*Mount) Routes ¶ added in v0.108.0
func (m *Mount) Routes() []MountedRoute
Routes returns a copy of the configured endpoints, including JWKS and enabled document/OIDC routes. It never advertises disabled or excluded endpoints.
type MountOptions ¶ added in v0.84.0
type MountOptions struct {
// Groups selects the mounted route groups. Nil mounts the default API
// surface plus browser OIDC. Non-nil mounts exactly the named groups —
// include RouteBrowserOIDC to keep the browser redirect flows.
Groups []RouteGroup
// APIPrefix anchors the JSON API routes. "" means DefaultAPIPrefix; "/"
// mounts the API at root.
APIPrefix string
// ExcludeRoutes drops routes the host shadows with its own handlers.
// Matched by method + prefix-neutral RouteSpec path. Exclusion does NOT
// alter the verifier's MFA-enrollment exempt-path set — that is derived
// from the full route registry at authhttp.New time, so a shadowed enroll
// route stays reachable through the host's replacement.
ExcludeRoutes []RouteRef
// Wrap decorates every RouteSpec-backed handler (API + browser OIDC) at
// mount time. JWKS is not wrapped (it carries no RouteSpec).
Wrap func(RouteSpec, http.Handler) http.Handler
// RefreshCookie (ak#271) delivers the rotating refresh token as an
// HttpOnly+Secure+SameSite=Lax cookie (RefreshCookieName) instead of a JSON
// body field, so an injected script cannot read the durable credential.
// OFF by default: a host that leaves this false gets byte-identical
// behaviour, refresh_token in every body as before.
//
// When on, every session-establishing response sets the cookie and omits
// refresh_token from its body/fragment/postMessage payload; POST /token
// requires the cookie and rejects body refresh tokens; DELETE /logout clears
// the cookie. Native mounts use body tokens and never consume cookies.
// The cookie is Path-scoped to this mount's POST /token — the only route
// that reads a refresh token — so it never rides the SPA document or assets.
//
// Browser-facing by construction: the host must serve the SPA and this
// mount on the SAME origin, or the cookie never reaches the refresh call.
RefreshCookie bool
}
MountOptions configures the combined AuthKit surface (MountHandler).
type MountedRoute ¶ added in v0.108.0
type MountedRoute struct {
Method string
Path string
Group RouteGroup
Auth RouteAuthTier
Permission authkit.Perm
}
MountedRoute describes an endpoint actually installed by NewMount. Path is the full anchored net/http path pattern; GET endpoints also have a HEAD entry. Auth and Permission describe the route-level gate, not every handler-specific authorization check.
type RateLimitResult ¶
type RateLimitResult struct {
Allowed bool
RetryAfter time.Duration
Availability *ActionAvailability
}
type RateLimiter ¶
RateLimiter is a minimal interface used by adapters.
type RateLimiterWithResult ¶
type RouteAuthTier ¶ added in v0.98.0
type RouteAuthTier string
RouteAuth is the authentication tier a route enforces before its handler runs (#328).
const ( AuthPublic RouteAuthTier = "public" // no principal AuthOptional RouteAuthTier = "optional" // principal used when present AuthRequired RouteAuthTier = "required" // valid principal AuthPermission RouteAuthTier = "permission" // valid principal holding RouteSpec.Permission AuthSigned RouteAuthTier = "signed" // per-message proof (domain fetch / JWS) )
type RouteGroup ¶
type RouteGroup string
RouteGroup identifies a prefix-neutral AuthKit route capability. Host applications can mount all default groups or select only the capabilities they want to expose.
const ( RouteAuth RouteGroup = "auth" // RouteDeviceKeys is the refreshless native-client login surface: email // enrollment plus Ed25519 challenge authentication. RouteDeviceKeys RouteGroup = "device_keys" RouteRegistration RouteGroup = "registration" RouteAccount RouteGroup = "account" RouteAdmin RouteGroup = "admin" RoutePermissionGroups RouteGroup = "permission_groups" RouteBrowserOIDC RouteGroup = "browser_oidc" // RouteApplications is the #264 application self-registration surface // (register / rotate / repoint). Mounted only when the host enables // Config.Applications.SelfRegistration. RouteApplications RouteGroup = "applications" // RouteDelegated is the #261 delegated-token mint surface // (POST /delegated/token). Mounted only when Config.Delegated declares an // audience allowlist. RouteDelegated RouteGroup = "delegated" // RouteDocuments is the #260 published signed-document surface // (GET|HEAD /.well-known/authkit/documents/{digest} — root-anchored like // JWKS, not under the API prefix). Mounted only when document providers // are wired via WithDocuments. RouteDocuments RouteGroup = "documents" )
type RouteRef ¶ added in v0.84.0
RouteRef identifies a route by HTTP method and prefix-neutral RouteSpec path (e.g. "/admin/users", NOT "/api/v1/admin/users"). JWKS is addressable as GET JWKSPath.
type RouteSpec ¶
type RouteSpec struct {
Method string
Path string
Group RouteGroup
Handler http.Handler
// Auth is the tier the handler wrapper enforces before the handler runs;
// Permission names the root/group permission for AuthPermission (#328).
Auth RouteAuthTier
Permission authkit.Perm
// Bucket is the per-IP rate-limit bucket APIRoutes applies in front of the
// handler ("" = none). Per-identifier and branch-specific buckets stay in
// the handler.
Bucket string
// MFAEnrollmentExempt marks a route as part of the 2FA enroll/challenge/
// verify surface a forced-enrollment-gated user (verify.WithRequireMFAEnrollment)
// must still be able to reach. authhttp.New derives the verifier's exempt-path
// allowlist from routes tagged here (#243) — the route table is the single
// source of truth, so a rename/add stays consistent by construction.
MFAEnrollmentExempt bool
}
RouteSpec is a concrete, prefix-neutral route with its AuthKit handler attached. Path parameters use net/http ServeMux syntax, e.g. "/namespaces/{slug}".
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service wraps the internal AuthKit engine with net/http mounting helpers.
func New ¶ added in v0.80.0
func New(client embedded.HTTPBackend, hcfg Config) (*Service, error)
New assembles a local HTTP transport inside HTTPConfiguration.BuildHTTP. Applications normally set embedded.Config.HTTP instead. Runtime and portable Clients deliberately do not implement HTTPBackend.
func (*Service) APIRoutes ¶
func (s *Service) APIRoutes(groups ...RouteGroup) []RouteSpec
APIRoutes returns AuthKit's enabled JSON API routes. With no groups it returns the default API surface. With groups, it returns only matching routes.
func (*Service) CheckSMSHealth ¶
CheckSMSHealth probes (without sending an SMS) whether the configured sender can actually deliver, caching the result to gate phone-based flows. Returns the probe error (nil = healthy) so the host app can log it at startup.
func (*Service) Close ¶ added in v0.98.0
func (s *Service) Close()
Close stops the background work New started: memory cache and limiter sweeps. The engine and Redis client are borrowed and remain owned by the host. Idempotent; safe on a nil Service.
func (*Service) JWKSHandler ¶
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 ...RouteGroup) []RouteSpec
OIDCBrowserRoutes returns browser redirect routes with no mount prefix.
func (*Service) PermissionGroupRoutes ¶
PermissionGroupRoutes returns the auto-generated management routes implied by this Service's declared permission-group schema, plus the cross-persona GET /me/groups discovery route. Mirrors APIRoutes: prefix-neutral RouteSpecs in the RoutePermissionGroups group, language-wrapped and auth-required. The set is fully config-derived from svc.PermissionGroupSchema().GeneratedRoutes(); a capability a profile disables is simply absent (=> 404).
func (*Service) SMSAvailable ¶
SMSAvailable reports whether phone-based flows should be offered (a sender is configured and, if checked, found able to deliver).
func (*Service) SMSHealthy ¶
SMSHealthy reports the last CheckSMSHealth result (true until a check runs).
Source Files
¶
- account_recovery.go
- admin_routes.go
- admin_signins.go
- applications.go
- audit.go
- auth_token_post.go
- auth_tokens.go
- availability.go
- browser_error.go
- buckets.go
- client_ip.go
- config.go
- confirm_errors.go
- contact_channel.go
- cookies.go
- delegated_token.go
- delegation.go
- device_keys.go
- documents_route.go
- errors.go
- internal_errors.go
- json_boundary.go
- jwks_get.go
- language.go
- login_continuation.go
- logout_delete.go
- mount.go
- oidc_browser.go
- oidc_handler.go
- oidc_util.go
- passkeys.go
- password_login_post.go
- passwordless.go
- permission_group_create.go
- permission_group_operations.go
- permission_group_routes.go
- providers.go
- providers_get.go
- ratelimit.go
- ratelimit_defaults.go
- refresh_cookie.go
- register.go
- register_availability.go
- routes.go
- runtime.go
- server.go
- service.go
- solana_siws.go
- step_up.go
- user_2fa.go
- user_2fa_verify_post.go
- user_me_get.go
- user_password_post.go
- user_routes.go
- user_sessions.go
- util.go