auth

package
v1.24.0 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT, MIT Imports: 6 Imported by: 0

Documentation

Overview

Package auth is the contract between a host's auth (the provider) and a library that guards its own routes with it (the consumer): the provider says who a request is (Authenticator), and the consumer decides what to admit from the Verified request, its optional permission and recent sign-in checks, and answers refusals the same way as every other consumer (Refuse). It contains no verifier or authorization policy.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrUnauthenticated: no valid credential (401).
	ErrUnauthenticated = errors.New("authentication required")
	// ErrForbidden: a valid credential the policy refuses (403).
	ErrForbidden = errors.New("authentication policy refused")
	// ErrUnavailable: the check could not run (503).
	ErrUnavailable = errors.New("authentication unavailable")
	// ErrSenderProofRequired: a sender-constrained token without its valid
	// proof (401).
	ErrSenderProofRequired = errors.New("sender proof required")
	// ErrExpired: the credential expired (401).
	ErrExpired = errors.New("credential expired")
	// ErrRevoked: the credential or its sign-in was revoked, or its account
	// banned or deleted (401).
	ErrRevoked = errors.New("credential revoked")
	// ErrStepUpRequired: the person must sign in again (401, RFC 9470).
	ErrStepUpRequired = errors.New("step-up required")
)

Failures are classified with errors.Is. Providers wrap their own errors in them; consumers never show provider error text to clients.

Functions

This section is empty.

Types

type Asserted

type Asserted interface {
	Asserted() bool
}

Asserted is an optional capability of a Verified request. Asserted is true for a credential minted from an application's assertion naming one of the application's own users (the RFC 7523 JWT bearer grant), such as a merchant backend's token for its customer, and false for any other: a session, an API key, a token exchanged for a resource, a trusted issuer's own token. Without this capability a credential is not asserted.

type Authenticator

type Authenticator interface {
	// Authenticate verifies r's credential (its Authorization header or
	// cookie, and any sender proof) and returns its Verified, or nil and an
	// error. It checks live: a credential whose sign-in was revoked, or whose
	// account is banned or deleted, is refused, not admitted until a token
	// expires. It admits people and applications alike.
	//
	// Its error matches ErrUnauthenticated when r carries no valid
	// credential, joined with ErrExpired, ErrRevoked or
	// ErrSenderProofRequired when that is why; ErrForbidden for a valid
	// credential the provider refuses here; ErrUnavailable when it could not
	// verify. It may be a *Challenge carrying the provider's headers.
	//
	// It is safe for concurrent use. A consumer calls it at most once per
	// request (a sender proof is spent once) and keeps the Verified for that
	// request alone; a provider whose own middleware already verified r's
	// credential reuses that verification.
	Authenticate(r *http.Request) (Verified, error)
}

Authenticator is the host's auth as a library takes it to guard its own routes. It only says who a request is; the library builds its gates from the Verified it returns, so the host writes no middleware.

type Bound

type Bound interface {
	BoundScope() Scope
}

Bound is an optional capability of a Verified request. BoundScope is the one scope the credential acts in, such as a group's API key or service token, a trusted issuer's token for its group, or a person's token exchanged for one group, and the zero Scope when it is bound to none, as a person's own sign-in is. A bound credential's Can is false outside it, with one exception: a person's (SubjectUser) may also hold, in the Authenticator's RootScope (Root), the root: permissions the person holds there, since a person keeps their root role whatever group a token names. An application's is false everywhere else. A consumer serving one scope's resources admits there only a credential bound to that scope; without this capability a credential is bound to none.

type Challenge

type Challenge struct {
	Err error
	// MaxAge is, with ErrStepUpRequired, how recent a sign-in the action
	// needs (RFC 9470 max_age); zero says nothing.
	MaxAge time.Duration
	// Header is set on the refusal, replacing Refuse's own values: a DPoP
	// challenge's WWW-Authenticate and DPoP-Nonce.
	Header http.Header
	// Metadata is the provider's challenge for its own client, such as its
	// step-up methods. Consumers return it unchanged and never read it.
	Metadata map[string]any
}

Challenge is a provider's error with detail for the refusal. errors.Is and errors.As see through it to Err, which classifies it; Refuse reads the rest.

func (*Challenge) Error

func (c *Challenge) Error() string

func (*Challenge) Unwrap

func (c *Challenge) Unwrap() error

type Credential

type Credential struct {
	Kind CredentialKind
	// ID names the credential when it has one: the session, device key or
	// API key, or a token's jti.
	ID string
	// contains filtered or unexported fields
}

Credential is the mechanism that proved a request, never the subject: a subject's keys and tokens come and go while the subject stays.

func (Credential) State

func (c Credential) State() any

State is the provider's record of the credential's bounds; nil for a Credential the provider did not produce.

func (Credential) WithState

func (c Credential) WithState(state any) Credential

WithState is c carrying a provider's record of its bounds. The provider accepts only a state of its own type, which nobody else can construct, and it must be comparable (a pointer), as Identity is.

type CredentialKind

type CredentialKind string

CredentialKind is how a request proved which subject it acts as.

const (
	// CredentialSession is a token of a user's interactive sign-in.
	CredentialSession CredentialKind = "session"
	// CredentialDeviceKey is a token of a device key's sign-in.
	CredentialDeviceKey CredentialKind = "device_key"
	// CredentialAPIKey is an API key.
	CredentialAPIKey CredentialKind = "api_key"
	// CredentialSignedToken is a token an application signed with its own
	// registered keys.
	CredentialSignedToken CredentialKind = "signed_token"
	// CredentialAccessToken is a token the issuer or an authorization server
	// minted, with no sign-in of its own.
	CredentialAccessToken CredentialKind = "access_token"
)

type Headers

type Headers interface {
	// AllowedHeaders are the request headers a client sends credentials in
	// (Access-Control-Allow-Headers), such as Authorization and DPoP.
	AllowedHeaders() []string
	// ExposedHeaders are the response headers a client reads
	// (Access-Control-Expose-Headers), such as WWW-Authenticate and
	// DPoP-Nonce: every header a Challenge of the provider carries.
	ExposedHeaders() []string
}

Headers is an optional capability of an Authenticator: the header names its credentials use across origins. A consumer merges them into its CORS lists, so it never names a provider's headers itself.

type Identity

type Identity struct {
	Issuer        string
	Subject       string
	SubjectKind   SubjectKind
	Invoker       Invoker
	Credential    Credential
	Email         string
	Username      string
	EmailVerified bool
}

Identity is the authenticated request. Subject is the account native to Issuer whose authority and money the request uses: a user or an application. Invoker is who actually acts: always set, equal to the subject unless someone acts on its behalf. Credential is how the request was proven. Authorization is the subject's, narrowed by the credential; limits and budgets are per invoker within the subject; audit records all three. Contact fields are optional metadata, not authority.

func (Identity) SelfInvoked

func (i Identity) SelfInvoked() bool

SelfInvoked reports whether the subject acts for itself.

type Invoker

type Invoker struct {
	Issuer string
	ID     string
}

Invoker is who actually acts, in its own issuer's namespace. It is the subject itself ({Issuer, Subject}) unless someone acts on the subject's behalf, such as an application's user spending the application's authority, who may be foreign.

type PermissionCatalog

type PermissionCatalog interface {
	KnownPermission(permission string) bool
}

PermissionCatalog is an optional capability of an Authenticator: the permissions it knows. A consumer checks the permissions it is configured with when it mounts its routes, so a misspelled one fails then instead of refusing every request.

type PermissionChecker

type PermissionChecker interface {
	Can(ctx context.Context, scope Scope, permission string) (bool, error)
}

PermissionChecker is an optional capability of a Verified request. Can reports whether the request holds exactly permission (never a pattern) in exactly scope, checked live and without verifying the request again: a scope of another authority, or outside the scope the credential is bound to (Bound, with its one exception), is false, and the credential's ceilings hold. Consumers deny privileged access without this capability; identity metadata never implies a grant. An error never grants: one matching ErrExpired or ErrRevoked (with ErrUnauthenticated) means the credential ended after the request was verified (401); any other means the check could not run (503).

type RecentSignInChecker

type RecentSignInChecker interface {
	CheckRecentSignIn(ctx context.Context) error
}

RecentSignInChecker is an optional capability of a person's Verified request, for actions that move money or grant access. CheckRecentSignIn is nil when the credential's own sign-in is recent enough by the provider's policy, checked without verifying the request again. Otherwise its error matches ErrStepUpRequired when the person must sign in again (a *Challenge gives the policy's MaxAge and the provider's Metadata); ErrExpired or ErrRevoked (with ErrUnauthenticated) when the credential ended; ErrForbidden for a credential with no sign-in of its own (an application's, an API key); ErrUnavailable when the check could not run. Consumers refuse those actions to a person whose request lacks it.

type Refusal

type Refusal struct {
	// Status is 401, 403 or 503.
	Status int
	// Header is set on the response: a 401's WWW-Authenticate challenge and
	// the provider's own headers.
	Header http.Header
	// Metadata is the provider's Challenge.Metadata, for the body.
	Metadata map[string]any
}

Refusal is how a consumer answers a request it refuses for an error from Authenticate, Can or CheckRecentSignIn, or for ErrForbidden of its own (Can answered false, a capability is missing): the same status and challenge in every consumer, beside the consumer's own body.

func Refuse

func Refuse(r *http.Request, err error) Refusal

Refuse is the Refusal for err on r:

  • ErrUnavailable, or an error matching none below (nil too): 503, the check could not run.
  • ErrStepUpRequired: 401, error="insufficient_user_authentication" with the Challenge's max_age in seconds (RFC 9470).
  • ErrUnauthenticated, ErrExpired, ErrRevoked or ErrSenderProofRequired: 401. The challenge names no error when r has no Authorization header, else error="invalid_token", or "invalid_dpop_proof" for a sender proof (RFC 6750 §3, RFC 9449 §7.1).
  • ErrForbidden: 403.

A challenge uses r's scheme: DPoP for a DPoP-bound request, else Bearer. A Challenge's Header is set last.

type Root

type Root interface {
	RootScope(ctx context.Context) (Scope, error)
}

Root is an optional capability of an Authenticator. RootScope is the scope its root permissions (root:<resource>:<action>) are held in, which spans everything the deployment serves, such as AuthKit's root group. A consumer checks a root: permission there (PermissionChecker.Can), so its host configures no scope; without Root a consumer grants no root: permission. Its error matches ErrUnavailable when the scope could not be resolved.

type Scope

type Scope struct {
	Authority string
	ID        string
}

Scope names an authority-owned immutable resource, such as the group whose members administer a merchant: Authority is the issuer whose groups it is in, ID its id there. The consumer keeps it beside the resource, or asks the Authenticator's RootScope (Root); names and request selectors grant nothing.

type SubjectKind

type SubjectKind string

SubjectKind is what kind of native account a subject is.

const (
	// SubjectUser is a person's account.
	SubjectUser SubjectKind = "user"
	// SubjectApplication is an application's account: a registered
	// application or service.
	SubjectApplication SubjectKind = "application"
)

type Verified

type Verified interface {
	Identity() Identity
}

Verified is one request's verified credential. A consumer keeps it only for that request: never for another request, nor after the credential, method or signed URL changes. It may implement PermissionChecker, RecentSignInChecker, Bound and Asserted; an identity-only provider implements none.

Directories

Path Synopsis
Package authtest checks a host's auth.Authenticator in the host's own CI, against the contract the libraries that take it enforce.
Package authtest checks a host's auth.Authenticator in the host's own CI, against the contract the libraries that take it enforce.

Jump to

Keyboard shortcuts

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