Documentation
¶
Overview ¶
Package authentication provides immutable principals, typed credentials and classified failures for authentication-only composition. Start with NewPrincipal and concrete authenticators or NewComposite; authorization, request decoding, provider IO/lifecycle and deployment TLS policy remain outside core. Credential accessors and explicit causes are sensitive despite redacted formatting. Root v2 admission bounds are not automatically inherited by optional modules pinned to published root v1.2.2. See docs/specification-decisions.md for protocol scope.
Index ¶
- Constants
- Variables
- func ContextWithPrincipal(ctx context.Context, principal Principal) context.Context
- type APIKeyCredential
- type Authenticator
- type BasicCredential
- type BearerCredential
- type BeginInstrumenter
- type Binding
- type Challenge
- type Clockdeprecated
- type Composite
- type Credential
- type CredentialKind
- type Event
- type Failure
- type FailureKind
- type FailureOption
- type Instrumented
- type Instrumenterdeprecated
- type Outcome
- type Principal
- func (p Principal) Audiences() []string
- func (p Principal) AuthenticatedAt() time.Time
- func (p Principal) Claims() map[string]any
- func (p Principal) IsAnonymous() bool
- func (p Principal) Issuer() string
- func (p Principal) Method() string
- func (p Principal) Scopes() []string
- func (p Principal) Subject() string
- func (p Principal) TenantHints() []string
- type PrincipalOption
- type PrincipalSpec
- type Result
- type ResultState
Examples ¶
Constants ¶
const ( // MaxChallengeParameters bounds authentication challenge metadata. MaxChallengeParameters = 16 // MaxChallengeSchemeBytes bounds an authentication scheme token. MaxChallengeSchemeBytes = 64 // MaxChallengeNameBytes bounds an authentication parameter name. MaxChallengeNameBytes = 64 // MaxChallengeValueBytes bounds an authentication parameter value. MaxChallengeValueBytes = 1024 )
const ( // MaxClaims is the maximum number of entries in a principal claim map. MaxClaims = 128 // MaxClaimDepth is the maximum nesting depth accepted in principal claims. MaxClaimDepth = 8 // MaxClaimCollection is the maximum number of elements in a nested claim // map, slice, or array. MaxClaimCollection = 256 )
const ( // MaxPrincipalStringBytes is the default and ceiling for each retained string. MaxPrincipalStringBytes = 8 * 1024 // MaxPrincipalIdentityEntries is the default and ceiling for each identity list. MaxPrincipalIdentityEntries = 256 // MaxPrincipalTotalStringBytes is the default and ceiling for retained string bytes. MaxPrincipalTotalStringBytes = 64 * 1024 // MaxPrincipalClaimNodes is the default and ceiling for recursive claim values. MaxPrincipalClaimNodes = 4096 )
Variables ¶
var ( // ErrCredentialsAbsent means no credential was supplied by an enabled source. ErrCredentialsAbsent = errors.New("authentication: credentials absent") // ErrCredentialsInvalid means credential syntax or protocol data was invalid. ErrCredentialsInvalid = errors.New("authentication: credentials invalid") // ErrCredentialsRejected means a validly formed credential was not accepted. ErrCredentialsRejected = errors.New("authentication: credentials rejected") // to a transient dependency or infrastructure failure. ErrAuthenticationUnavailable = errors.New("authentication: validation unavailable") // ErrAmbiguousCredentials means more than one credential was supplied where // exactly one was required. ErrAmbiguousCredentials = errors.New("authentication: ambiguous credentials") // ErrInvalidChallenge identifies invalid challenge protocol data. ErrInvalidChallenge = errors.New("authentication: invalid challenge") // ErrInvalidConfiguration identifies unsafe or incomplete authenticator // configuration. ErrInvalidConfiguration = errors.New("authentication: invalid configuration") )
var ErrInvalidPrincipal = errors.New("authentication: invalid principal")
ErrInvalidPrincipal identifies a principal that violates an identity invariant, exceeds its finite limits, or contains claims that cannot be copied safely. Errors never include supplied identity or claim values.
Functions ¶
func ContextWithPrincipal ¶
ContextWithPrincipal stores the immutable Principal value in a child of a nonnil context, including anonymous values. It does not authenticate that value or make claims authoritative. Nil parent panics through context.WithValue.
Types ¶
type APIKeyCredential ¶
type APIKeyCredential struct {
// contains filtered or unexported fields
}
APIKeyCredential is an API key with an optional non-secret key identifier. Its formatted representation is always redacted.
func NewAPIKeyCredential ¶
func NewAPIKeyCredential(keyID, key string) APIKeyCredential
NewAPIKeyCredential retains raw ID/key strings without validation or backing- storage cloning. The ID is application-asserted non-secret; no confidentiality policy or secure-erasure lifecycle is enforced by this value.
func (APIKeyCredential) GoString ¶
func (APIKeyCredential) GoString() string
GoString returns a fixed redacted Go-syntax representation.
func (APIKeyCredential) Key ¶
func (c APIKeyCredential) Key() string
Key returns the plaintext API key; never project it into logs or diagnostics.
func (APIKeyCredential) KeyID ¶
func (c APIKeyCredential) KeyID() string
KeyID returns the raw application-asserted non-secret key identifier.
func (APIKeyCredential) Kind ¶
func (APIKeyCredential) Kind() CredentialKind
Kind returns CredentialAPIKey even for an empty zero-value credential.
func (APIKeyCredential) String ¶
func (APIKeyCredential) String() string
String returns fixed redacted prose without exposing stored values.
type Authenticator ¶
type Authenticator interface {
// Authenticate borrows a nonnil caller context and credential. Implementations
// must bound/cooperate with IO, protect secret-bearing errors and support any
// concurrent reuse. A nil error must accompany a meaningful Result; no generic
// panic containment, input copy or provider shutdown is imposed by this interface.
Authenticate(context.Context, Credential) (Result, error)
}
Authenticator validates one typed credential.
Example (BackgroundConsumer) ¶
package main
import (
"context"
"fmt"
authentication "github.com/faustbrian/go-authentication/v2"
"github.com/faustbrian/go-authentication/v2/apikey"
)
func main() {
authenticator, _ := apikey.NewStatic([]apikey.Entry{{
ID: "worker", Key: "secret",
Principal: authentication.PrincipalSpec{Subject: "invoice-worker"},
}})
result, err := authenticator.Authenticate(
context.Background(),
authentication.NewAPIKeyCredential("worker", "secret"),
)
principal, authenticated := result.Principal()
fmt.Println(err, authenticated, principal.Subject())
}
Output: <nil> true invoice-worker
type BasicCredential ¶
type BasicCredential struct {
// contains filtered or unexported fields
}
BasicCredential is a username and password extracted from Basic authentication. Its formatted representation is always redacted.
func NewBasicCredential ¶
func NewBasicCredential(username, password string) BasicCredential
NewBasicCredential retains raw strings without validation, normalization or cloning backing storage. Empty values are representable; extraction and authentication apply separate bounds. Strings cannot be securely erased here.
func (BasicCredential) GoString ¶
func (BasicCredential) GoString() string
GoString returns a fixed redacted Go-syntax representation.
func (BasicCredential) Kind ¶
func (BasicCredential) Kind() CredentialKind
Kind returns CredentialBasic even for an empty zero-value credential.
func (BasicCredential) Password ¶
func (c BasicCredential) Password() string
Password returns the plaintext password; never project it into logs or diagnostics.
func (BasicCredential) String ¶
func (BasicCredential) String() string
String returns fixed redacted prose without exposing stored values.
func (BasicCredential) Username ¶
func (c BasicCredential) Username() string
Username returns the raw username, which the application must classify for disclosure.
type BearerCredential ¶
type BearerCredential struct {
// contains filtered or unexported fields
}
BearerCredential is an opaque bearer token. Its formatted representation is always redacted.
func NewBearerCredential ¶
func NewBearerCredential(token string) BearerCredential
NewBearerCredential retains the raw token without validation or cloning backing storage. Token bounds/grammar are separate consumer policies; secret accessors intentionally return plaintext and offer no secure-erasure guarantee.
func (BearerCredential) GoString ¶
func (BearerCredential) GoString() string
GoString returns a fixed redacted Go-syntax representation.
func (BearerCredential) Kind ¶
func (BearerCredential) Kind() CredentialKind
Kind returns CredentialBearer even for an empty zero-value credential.
func (BearerCredential) String ¶
func (BearerCredential) String() string
String returns fixed redacted prose without exposing stored values.
func (BearerCredential) Token ¶
func (c BearerCredential) Token() string
Token returns the plaintext token; formatting redaction does not protect accessor use.
type BeginInstrumenter ¶
type BeginInstrumenter interface {
// Begin runs synchronously and may return a replacement context plus completion
// callback. Providers must preserve cancellation policy, bound latency and
// screen custom categories. Reuse requires concurrent safety. The decorator
// contains telemetry panics, not blocking; it invokes a returned callback once
// only when the wrapped authentication call returns normally.
Begin(context.Context, CredentialKind) (context.Context, func(Event))
}
BeginInstrumenter begins instrumentation for one authentication attempt. Implementations must not derive attributes from credential contents.
type Binding ¶
type Binding struct {
// Kind selects one routing family; unknown nonempty kinds are permitted.
Kind CredentialKind
// Authenticator is borrowed, not cloned; callers own provider lifetime and concurrent safety.
Authenticator Authenticator
}
Binding associates a credential kind with one authenticator. Bindings of the same kind are evaluated in declaration order.
type Challenge ¶
type Challenge struct {
// contains filtered or unexported fields
}
Challenge is an immutable authentication challenge. Transport adapters are responsible for serializing it according to their protocol.
func NewChallenge ¶
NewChallenge validates bounded ASCII tokens and quoted-text bytes, then copies parameters. Values allow HTAB and high bytes but reject other controls; no UTF-8 normalization or confidentiality classification is performed. The zero Challenge is not valid protocol data. See docs/specification-decisions.md.
func (Challenge) Parameters ¶
Parameters returns a defensive copy of the authentication parameters.
type Composite ¶
type Composite struct {
// contains filtered or unexported fields
}
Composite routes typed credentials to ordered authenticators. Only rejected credentials fall through; every other failure is terminal.
func NewComposite ¶
NewComposite requires nonempty bindings and refuses nil/typed-nil providers. It copies binding storage, not provider state; there is no binding-count cap. Reuse concurrently only when every borrowed provider supports it.
func (*Composite) Authenticate ¶
Authenticate evaluates authenticators bound to the credential kind in deterministic declaration order. A nonnil context is checked before dispatch, not between every provider call. Only rejected failures fall through; an anonymous/zero success or unknown error becomes unavailable. Provider/Kind panics and noncooperative blocking propagate; no retry or shutdown is owned.
type Credential ¶
type Credential interface {
// Kind returns stable routing metadata without disclosing credential contents.
// Custom implementations must keep String output redacted and any borrowed
// state safe for concurrent use; the interface cannot enforce that obligation.
Kind() CredentialKind
fmt.Stringer
}
Credential is a typed authentication credential. Implementations redact their secret-bearing representation.
type CredentialKind ¶
type CredentialKind string
CredentialKind identifies a credential's protocol family.
const ( // CredentialBasic names Basic username/password credentials. CredentialBasic CredentialKind = "basic" // CredentialBearer names opaque bearer-token credentials. CredentialBearer CredentialKind = "bearer" // CredentialAPIKey names key-ID/key credentials. CredentialAPIKey CredentialKind = "api_key" )
type Event ¶
type Event struct {
// Outcome is the attempt state; custom strings must be screened by instrumenters.
Outcome Outcome
// Failure is a Failure kind when available; empty means no typed failure classification.
Failure FailureKind
// Duration is measured elapsed time; the decorator clamps negative clock movement to zero.
Duration time.Duration
}
Event carries category/duration telemetry, never credential fields. Its string types can still contain application data; concrete owned adapters project unknown categories to fixed labels, not arbitrary custom providers.
type Failure ¶
type Failure struct {
// contains filtered or unexported fields
}
Failure is a secret-safe, typed authentication failure.
func NewFailure ¶
func NewFailure(kind FailureKind, options ...FailureOption) *Failure
NewFailure preserves the supplied kind/cause/challenges without validating kind or limiting challenge count. Nil options are ignored. Default Error text is fixed, but Kind, Unwrap and Challenges can expose application data.
func (*Failure) Challenges ¶
Challenges returns a defensive copy of the associated challenges.
func (*Failure) Kind ¶
func (f *Failure) Kind() FailureKind
Kind returns the stable failure classification.
type FailureKind ¶
type FailureKind string
FailureKind classifies authentication failures independently of transports.
const ( // FailureAbsent identifies absence from enabled credential sources. FailureAbsent FailureKind = "absent" // FailureInvalid identifies malformed or inadmissible credential data. FailureInvalid FailureKind = "invalid" // FailureRejected identifies a well-formed credential refused by policy. FailureRejected FailureKind = "rejected" FailureUnavailable FailureKind = "unavailable" // FailureAmbiguous identifies multiple credentials where one was required. FailureAmbiguous FailureKind = "ambiguous" )
type FailureOption ¶
type FailureOption func(*Failure)
FailureOption configures a Failure.
func WithChallenges ¶
func WithChallenges(challenges ...Challenge) FailureOption
WithChallenges associates transport-independent challenges with a failure.
func WithFailureCause ¶
func WithFailureCause(cause error) FailureOption
WithFailureCause preserves cause for errors.Is and errors.As without including the cause text in Failure.Error.
type Instrumented ¶
type Instrumented struct {
// contains filtered or unexported fields
}
Instrumented decorates an authenticator with failure-isolated telemetry.
func NewInstrumented
deprecated
func NewInstrumented(authenticator Authenticator, instrumenter Instrumenter, clock Clock) (*Instrumented, error)
NewInstrumented creates an authentication instrumentation decorator for the legacy Start-named observation contract.
Deprecated: use NewInstrumentedWithBegin. It accepts the preferred Begin-named contract without expanding the released Instrumenter interface. Migrate by supplying a BeginInstrumenter and changing the constructor call. NewInstrumented remains supported throughout v1; its earliest removal is v2.0.0.
func NewInstrumentedWithBegin ¶
func NewInstrumentedWithBegin(authenticator Authenticator, instrumenter BeginInstrumenter, clock Clock) (*Instrumented, error)
NewInstrumentedWithBegin creates an authentication instrumentation decorator using the preferred one-attempt observation vocabulary. Nil and typed-nil dependencies are refused; provider/clock state remains borrowed. No goroutine, flush or provider shutdown is owned; concurrent reuse requires collaborators to support it.
func (*Instrumented) Authenticate ¶
func (i *Instrumented) Authenticate(ctx context.Context, credential Credential) (Result, error)
Authenticate reports bounded outcome metadata without changing the wrapped authenticator's result or error. Clock/begin/finish panics are isolated, but the authenticator's panic propagates and does not run finish. A provider can replace the forwarded context; nil replacement keeps the original. No callback deadline/preemption or universal custom-category redaction is added.
type Instrumenter
deprecated
type Instrumenter interface {
// Start runs synchronously and may return a replacement context plus completion
// callback. Providers must preserve cancellation policy, bound latency and
// screen custom categories. Reuse requires concurrent safety. The decorator
// contains telemetry panics, not blocking; it invokes a returned callback once
// only when the wrapped authentication call returns normally.
Start(context.Context, CredentialKind) (context.Context, func(Event))
}
Instrumenter starts instrumentation for one authentication attempt. Implementations must not derive attributes from credential contents.
Deprecated: implement BeginInstrumenter and use NewInstrumentedWithBegin. Begin aligns observation naming without adding a method to this released required interface. Migrate by adding Begin with the same semantics and switching constructor calls. Instrumenter remains supported throughout v1; its earliest removal is v2.0.0.
type Outcome ¶
type Outcome string
Outcome is the bounded authentication outcome reported to instrumentation.
const ( // OutcomeAuthenticated marks completion with an authenticated Result. OutcomeAuthenticated Outcome = "authenticated" // OutcomeAnonymous marks completion with explicit anonymous state. OutcomeAnonymous Outcome = "anonymous" // OutcomeFailed marks completion with an error. OutcomeFailed Outcome = "failed" )
type Principal ¶
type Principal struct {
// contains filtered or unexported fields
}
Principal is an immutable authenticated identity or the explicit anonymous identity. Its zero value is anonymous.
func AnonymousPrincipal ¶
func AnonymousPrincipal() Principal
AnonymousPrincipal returns the explicit anonymous identity.
func NewPrincipal ¶
func NewPrincipal(spec PrincipalSpec) (Principal, error)
NewPrincipal validates and copies authenticated identity data using the default finite Principal limits. See NewPrincipalWithOptions to reduce them.
func NewPrincipalWithOptions ¶
func NewPrincipalWithOptions(spec PrincipalSpec, options ...PrincipalOption) (Principal, error)
NewPrincipalWithOptions admits authenticated identity data before copying it. Options may reduce, but not raise or disable, the default limits. Invalid options match both ErrInvalidPrincipal and ErrInvalidConfiguration; identity or claim admission failures match ErrInvalidPrincipal. Nil options are ignored.
Each retained string is bounded, and its bytes count toward one aggregate budget, including repeated identity/list/claim-key/string-value occurrences. Each audience, tenant-hint and scope list has an independent count limit. Claims share one recursive value-count budget: scalars, nils and containers count once, interface wrappers and map keys do not. Repeated references count for each output occurrence. Existing claim count/depth/collection limits also apply. Retained strings have independent backing storage; defined scalar string types are preserved. AuthenticatedAt is retained unchanged.
func PrincipalFromContext ¶
PrincipalFromContext retrieves the exact stored value; found can be true for anonymous identities. Nil context panics; use IsAnonymous separately.
func (Principal) AuthenticatedAt ¶
AuthenticatedAt returns the time at which the identity was authenticated, preserving the caller's trusted time.Location and timestamp representation.
func (Principal) IsAnonymous ¶
IsAnonymous reports whether p represents absence of an authenticated identity.
func (Principal) Scopes ¶
Scopes returns a copy of the scopes asserted by the credential. Scopes are authentication data and are not an authorization decision.
func (Principal) TenantHints ¶
TenantHints returns a copy of non-authoritative tenant hints.
type PrincipalOption ¶
type PrincipalOption func(*principalConfig)
PrincipalOption configures only Principal construction.
func WithMaxPrincipalClaimNodes ¶
func WithMaxPrincipalClaimNodes(maximum int) PrincipalOption
WithMaxPrincipalClaimNodes reduces the inclusive recursive claim-value limit. Containers, scalars and nil values each count once; interface wrappers do not.
func WithMaxPrincipalIdentityEntries ¶
func WithMaxPrincipalIdentityEntries(maximum int) PrincipalOption
WithMaxPrincipalIdentityEntries reduces the inclusive entry limit for each audience, tenant-hint, and scope list independently.
func WithMaxPrincipalStringBytes ¶
func WithMaxPrincipalStringBytes(maximum int) PrincipalOption
WithMaxPrincipalStringBytes reduces the inclusive byte limit for each string.
func WithMaxPrincipalTotalStringBytes ¶
func WithMaxPrincipalTotalStringBytes(maximum int) PrincipalOption
WithMaxPrincipalTotalStringBytes reduces the inclusive total retained string byte limit, counting every occurrence of identity data, claim keys and string values.
type PrincipalSpec ¶
type PrincipalSpec struct {
// Subject is required nonempty identity text; it is not normalized or confidentiality-classified.
Subject string
// Method is required nonempty authentication-method text, not an authorization policy.
Method string
// Issuer is optional authority text; core construction does not validate its URI.
Issuer string
// Audiences is copied nonempty audience text, with an independent list limit.
Audiences []string
// TenantHints is copied non-authoritative tenant metadata, not verified tenancy.
TenantHints []string
// Scopes is copied authentication data, not an authorization decision.
Scopes []string
// Claims is copied bounded scalar/map/collection data; unsupported kinds fail admission.
Claims map[string]any
// AuthenticatedAt retains trusted application timestamp/location metadata unchanged.
AuthenticatedAt time.Time
}
PrincipalSpec contains the identity data used to construct a Principal. Callers may reuse or mutate its slices and maps after construction returns, but must not mutate them concurrently with construction. AuthenticatedAt and its time.Location are trusted clock/application metadata, retained unchanged.
type Result ¶
type Result struct {
// contains filtered or unexported fields
}
Result is the outcome of successful authentication policy evaluation.
func AnonymousResult ¶
func AnonymousResult() Result
AnonymousResult creates an explicit anonymous result for optional routes.
func NewAuthenticatedResult ¶
NewAuthenticatedResult creates a result for a concrete authenticated identity.
type ResultState ¶
type ResultState string
ResultState identifies whether authentication established an identity or an explicitly permitted anonymous state.
const ( // ResultAuthenticated marks a concrete identity, not an authorization grant. ResultAuthenticated ResultState = "authenticated" // ResultAnonymous marks explicitly permitted absence of an identity. ResultAnonymous ResultState = "anonymous" )
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
adapters
|
|
|
http
Package authenticationhttp provides strict HTTP credential extraction, challenges, and authentication-only middleware for net/http.
|
Package authenticationhttp provides strict HTTP credential extraction, challenges, and authentication-only middleware for net/http. |
|
slog
Package authenticationslog adapts authentication Begin instrumentation to log/slog using New.
|
Package authenticationslog adapts authentication Begin instrumentation to log/slog using New. |
|
Package apikey provides New/NewStatic for key-ID/key credentials.
|
Package apikey provides New/NewStatic for key-ID/key credentials. |
|
Package authhttp preserves the original HTTP authentication adapter import path.
|
Package authhttp preserves the original HTTP authentication adapter import path. |
|
Package authlog preserves the original structured-log adapter import path.
|
Package authlog preserves the original structured-log adapter import path. |
|
Package authtest provides synthetic deterministic fixtures via Principal, NewClock/NewAuthenticator and HTTP helpers.
|
Package authtest provides synthetic deterministic fixtures via Principal, NewClock/NewAuthenticator and HTTP helpers. |
|
Package basic provides NewStatic/NewStaticWithOptions for bounded Basic credentials.
|
Package basic provides NewStatic/NewStaticWithOptions for bounded Basic credentials. |
|
Package bearer provides New for borrowed opaque-token validators and NewStatic for atomically replaceable digest/principal snapshots.
|
Package bearer provides New for borrowed opaque-token validators and NewStatic for atomically replaceable digest/principal snapshots. |