requestprincipal

package
v0.14.0 Latest Latest
Warning

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

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

Documentation

Overview

Package requestprincipal is the protocol-neutral view of who made an HTTP request. A resource server (a product API) protects its routes with one middleware that tries several Authenticators in order — a human's BFF cookie or bearer token, an API key, an AI agent's AAuth-signed request — and finds a RequestPrincipal in the request context, whichever protocol authenticated it.

The package has no protocol dependencies. Adapters live with their protocols: relyingparty.NewRequestAuthenticator wraps SystemAuth bearer tokens, API keys and BFF sessions, and the aauthrs subpackage verifies AAuth (agent auth) requests.

Index

Constants

View Source
const (
	// ProtocolSession is a browser (BFF) cookie session.
	ProtocolSession = "session"
	// ProtocolOIDC is an OAuth 2.0 / OpenID Connect bearer access token.
	ProtocolOIDC = "oidc"
	// ProtocolAPIKey is an API key.
	ProtocolAPIKey = "apikey"
	// ProtocolAAuth is an AAuth HTTP message signature with an agent,
	// person or auth token.
	ProtocolAAuth = "aauth"
)

Protocol values for RequestPrincipal.Protocol.

Variables

View Source
var ErrNoCredentials = errors.New("requestprincipal: no credentials")

ErrNoCredentials is returned by an Authenticator when the request carries no credentials of its kind, so the next authenticator may try.

View Source
var ErrNoPrincipal = errors.New("requestprincipal: no SystemForge principal")

ErrNoPrincipal is returned by PrincipalUUID when the request carries no principal that is a SystemForge principal.

Functions

func Middleware

func Middleware(opts Options, authenticators ...Authenticator) func(http.Handler) http.Handler

Middleware authenticates each request with the authenticators in order (see Chain.Authenticate), puts the RequestPrincipal in the request context, and otherwise writes the protocol's response: the rejecting authenticator's *Error, a 401 with every authenticator's challenge when none recognized the request, or a 500 for an internal error.

func PrincipalUUID

func PrincipalUUID(ctx context.Context) (uuid.UUID, error)

PrincipalUUID returns the SystemForge principal ID of the request's principal. It returns ErrNoPrincipal when the request is unauthenticated or its principal ID is not a SystemForge principal ID, such as an issuer-qualified subject of a credential issued elsewhere.

func WithPrincipal

func WithPrincipal(ctx context.Context, p *RequestPrincipal) context.Context

WithPrincipal returns ctx carrying p.

Types

type Authenticator

type Authenticator interface {
	Authenticate(r *http.Request) (*RequestPrincipal, error)
}

Authenticator authenticates requests of one protocol.

Authenticate returns the principal, or:

  • an error wrapping ErrNoCredentials when the request carries none of its credentials;
  • an *Error when it carries them but they are invalid or insufficient (the response the protocol prescribes: a challenge, 401 or 403);
  • any other error for an internal failure (a 500).

type AuthenticatorFunc

type AuthenticatorFunc func(r *http.Request) (*RequestPrincipal, error)

AuthenticatorFunc adapts a function to Authenticator.

func (AuthenticatorFunc) Authenticate

func (f AuthenticatorFunc) Authenticate(r *http.Request) (*RequestPrincipal, error)

Authenticate calls f.

type Chain

type Chain []Authenticator

Chain tries authenticators in order. It is itself an Authenticator.

func (Chain) Authenticate

func (c Chain) Authenticate(r *http.Request) (*RequestPrincipal, error)

Authenticate returns the principal from the first authenticator that recognizes the request's credentials. An authenticator that recognizes them but rejects them ends the chain with its error: credentials of one protocol never fall through to another. When none recognizes the request, the result is a 401 *Error carrying every Challenger's headers, and wraps ErrNoCredentials.

func (Chain) Challenge

func (c Chain) Challenge(h http.Header)

Challenge implements Challenger with every member's challenges.

type Challenger

type Challenger interface {
	Challenge(h http.Header)
}

Challenger is implemented by authenticators that advertise themselves on a 401 response to a request that no authenticator recognized: a bearer authenticator adds WWW-Authenticate, an AAuth authenticator adds AAuth-Requirement. Challenge adds its headers to h.

type Error

type Error struct {
	// Status is the HTTP status (401 when zero).
	Status int
	// Header holds response headers, such as a challenge.
	Header http.Header
	// Code and Message form the default JSON body
	// {"code": ..., "message": ...}.
	Code    string
	Message string
	// Respond, when set, writes the whole response instead (after Header
	// is applied), for protocols with their own error bodies.
	Respond func(w http.ResponseWriter)
	// Err is the underlying cause, for logs.
	Err error
}

Error is an authentication failure with the response its protocol prescribes.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Unwrap

func (e *Error) Unwrap() error

func (*Error) Write

func (e *Error) Write(w http.ResponseWriter)

Write writes the response for e.

type Options

type Options struct {
	// Optional lets requests without credentials through without a
	// principal (handlers check FromContext). Invalid credentials are
	// still rejected.
	Optional bool
	// Logger receives internal errors. Default: slog.Default().
	Logger *slog.Logger
}

Options configures Middleware.

type Proof

type Proof struct {
	// Method names the credential form (e.g. "access_token", "api_key",
	// "session", "aa-auth+jwt").
	Method string
	// Issuer is the party that issued the credential.
	Issuer string
	// Audience is the audience the credential was verified for.
	Audience string
	// TokenID is the credential's identifier (a JWT jti or an API key ID).
	TokenID string
	// KeyThumbprint is the RFC 7638 thumbprint of the key the request was
	// signed with, for proof-of-possession credentials.
	KeyThumbprint string
	// IssuedAt and ExpiresAt bound the credential, when it states them.
	IssuedAt  time.Time
	ExpiresAt time.Time
	// Params are further protocol-specific evidence (e.g. the signature's
	// covered components), by name.
	Params map[string]string
}

Proof is the verified evidence an authenticator accepted.

type RequestPrincipal

type RequestPrincipal struct {
	// PrincipalID is the stable identifier the application keys
	// authorization and records on: the app-local principal ID for
	// SystemAuth credentials, or an issuer-qualified subject for
	// credentials issued elsewhere (see the adapter's documentation).
	PrincipalID string
	// Type is the kind of party that made the request.
	Type Type
	// Subject is the credential's subject as its issuer states it. It is
	// unique within Proof.Issuer only.
	Subject string
	// Organization is the organization (tenant) the credential is scoped
	// to, when it is scoped to one.
	Organization string
	// Actor identifies the party that made the request when it is not
	// the subject: for an agent acting for a person, the agent.
	Actor string
	// Delegator identifies the party the actor acts for, when there is
	// one: for an agent acting for a person, the person.
	Delegator string
	// Mission identifies the task the credential was issued for, when
	// the protocol has one (AAuth: the mission's s256 digest).
	Mission string
	// Session identifies the authenticated session or grant: a BFF
	// session or an issued token's ID.
	Session string
	// Protocol is how the request authenticated (Protocol*).
	Protocol string
	// Proof is the verified evidence behind the principal.
	Proof Proof
	// Scopes are the scopes or grants the credential carries. Empty for
	// a session, which carries the principal's full access.
	Scopes []string
	// Claims are additional verified attributes, by name.
	Claims map[string]any
	// Native is the adapter's own, protocol-specific result (for example
	// *relyingparty.AuthenticatedPrincipal), for callers that need more
	// than the neutral view.
	Native any
}

RequestPrincipal is the authenticated principal of one request.

func FromContext

func FromContext(ctx context.Context) (*RequestPrincipal, bool)

FromContext returns the request principal in ctx, if any.

func (*RequestPrincipal) HasScope

func (p *RequestPrincipal) HasScope(scope string) bool

HasScope reports whether the principal's credential carries scope.

func (*RequestPrincipal) IsAgent

func (p *RequestPrincipal) IsAgent() bool

IsAgent reports whether the request was made by an AI agent.

type Type

type Type string

Type is the kind of party a request principal is.

const (
	// TypeHuman is an interactive person.
	TypeHuman Type = "human"
	// TypeAgent is an AI agent, possibly acting for a person.
	TypeAgent Type = "agent"
	// TypeService is a backend service or system account.
	TypeService Type = "service"
	// TypeApplication is an OAuth client acting as itself.
	TypeApplication Type = "application"
)

Directories

Path Synopsis
Package aauthrs authenticates AI agents at a resource server with AAuth (draft-hardt-oauth-aauth-protocol), producing a requestprincipal.RequestPrincipal.
Package aauthrs authenticates AI agents at a resource server with AAuth (draft-hardt-oauth-aauth-protocol), producing a requestprincipal.RequestPrincipal.

Jump to

Keyboard shortcuts

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