Documentation
¶
Overview ¶
Package authn provides an engine-agnostic Kratos middleware dispatcher for authentication. The main package is a pure dispatcher: it knows nothing about credential carriers (Bearer token, mTLS PeerCertificate, API-Key header, signature, etc.). Engine sub-packages (e.g. `security/authn/jwt`) are responsible for credential I/O.
Dispatcher form (P0-4b):
authn.Server(
authn.Multi(
authn.Named(jwt.Scheme, jwt.NewAuthenticator(...)),
authn.Named(apikey.Scheme, apikey.NewAuthenticator(...)),
),
authn.WithRulesFuncs(examplev1.AuthnRules, iamv1.AuthnRules),
)
`authn.Server` itself is engine-agnostic: it consumes the annotation table (`Rules`) generated by `protoc-gen-servora-authn` to decide for each RPC path whether to skip (PublicMethods), restrict to a subset of schemes (MethodSchemes), or fail-open across all engines (unannotated).
`authn.Multi` is the standard decorator over multiple `NamedAuthenticator` instances. It treats ErrNoCredentials as "try the next allowed engine" and treats any other error as fail-fast.
On success the enriched context returned by the engine is passed directly to the handler. On failure an optional `WithAuditOnFailure` auditor emits a CloudEvents event; the dispatcher itself does not write to the legacy auditpb detail holder.
Index ¶
- Variables
- func AuthTypeFrom(ctx context.Context) (string, bool)
- func Server(a Authenticator, opts ...Option) middleware.Middleware
- func SubjectFromAny(fns ...func(context.Context) (string, bool)) func(context.Context) (string, bool)
- func WithAuthType(ctx context.Context, authType string) context.Context
- type Authenticator
- type NamedAuthenticator
- type Option
- type Rules
- type SchemeAttempt
- type SchemeAttemptsErr
Constants ¶
This section is empty.
Variables ¶
var ErrNoCredentials = errors.New("authn: no credentials")
ErrNoCredentials is returned by authentication engines when the request does not carry credentials for that engine. It is not an authentication failure by itself: composite dispatchers such as Multi use it to continue to the next allowed engine. Invalid credentials and backend/config failures must return any other non-nil error.
Functions ¶
func AuthTypeFrom ¶ added in v0.5.0
AuthTypeFrom retrieves the authentication type string previously set via WithAuthType. Returns ("", false) if not present.
func Server ¶
func Server(a Authenticator, opts ...Option) middleware.Middleware
Server returns a Kratos middleware that dispatches authentication to the supplied `Authenticator` (typically a `Multi` decorator).
Per-request behavior:
- Resolve operation: `transport.FromServerContext(ctx).Operation()`.
- PublicMethods passthrough: if op ∈ `Rules.PublicMethods`, passthrough — do not call the engine.
- Build the allowed-schemes set: if op ∈ `Rules.MethodSchemes`, install `allowed = set(rules.MethodSchemes[op])` into ctx. Otherwise install nil (fail-open / unannotated).
- Call `a.Authenticate(ctx)`.
- Success → use the returned enriched ctx directly, call the handler.
- Failure → optionally emit audit event (if WithAuditOnFailure set), then either invoke `WithErrorHandler` (if set) or return `errors.Unauthorized("AUTHN_FAILED", reason)`.
func SubjectFromAny ¶ added in v0.5.0
func SubjectFromAny(fns ...func(context.Context) (string, bool)) func(context.Context) (string, bool)
SubjectFromAny composes multiple subject-extraction functions into a single combinator. The first function that returns (subject, true) wins; nil entries are silently skipped.
This allows business code to combine different identity sources (e.g. actor-from-JWT, actor-from-apikey, actor-from-mTLS) into a unified subject resolver without coupling to any specific engine.
Types ¶
type Authenticator ¶
Authenticator is the interface for authenticating incoming requests.
CONTRACT: this interface intentionally contains ONLY behavior body (`Authenticate`). Engine metadata belongs to the wrapper layer via `authn.Named(scheme, a)` — NOT on the interface itself.
What MUST NOT live on this interface:
- Engine metadata (e.g. `Method() string`) — supplied by `authn.Named` when wiring `authn.Multi`; framework main package is agnostic to the scheme string.
- Hooks / callbacks (e.g. `OnSuccess`) — caller responsibility.
- Injection (logger / tracer) — container responsibility.
- Infra probes (e.g. `Health`) — separate sibling interface.
This single-method shape prevents interface bloat as new engines (mTLS, API-Key, AK+SK, Passkey, etc.) are added: each engine is described to the dispatcher by `Named` at wiring time, and orchestration is the `Multi` decorator's responsibility.
func Multi ¶ added in v0.4.8
func Multi(named ...NamedAuthenticator) Authenticator
Multi composes multiple `NamedAuthenticator` engines into a single `Authenticator`. First-success-wins: engines are tried in injection order (NOT in `allowedSchemes` order — business decides the precedence at wiring time).
If the `allowedSchemes` set installed by `Server` (from `Rules.MethodSchemes`) is non-nil, engines whose scheme is absent from the set are skipped silently. If nil (unannotated method), every engine participates.
Wrapping a single engine via `Multi(Named(...))` is a supported and recommended pattern: it gives the dispatcher the scheme name without requiring a separate `WithMethod` option, and makes future expansion to more engines a one-line change.
type NamedAuthenticator ¶ added in v0.4.8
type NamedAuthenticator struct {
// contains filtered or unexported fields
}
NamedAuthenticator is an opaque scheme + Authenticator pair produced by `Named`. Fields are package-private; consumers can only construct via `Named` and consume via `Multi`.
func Named ¶ added in v0.4.8
func Named(scheme string, a Authenticator) NamedAuthenticator
Named pairs a scheme string with an `Authenticator` for `Multi`.
The scheme string is opaque to the framework — any value is accepted. Engine sub-packages typically expose a `Scheme` constant (e.g. `jwt.Scheme = "jwt"`) so business code can write `authn.Named(jwt.Scheme, jwt.NewAuthenticator(...))`.
type Option ¶
type Option func(*serverConfig)
Option configures the Server middleware.
func WithAuditOnFailure ¶ added in v0.5.0
WithAuditOnFailure installs an Auditor that receives a CloudEvents event on every authentication failure. The event carries:
- type = "servora.authn.v1.failure"
- source = the RPC operation from transport ctx
- severity extension = "WARN"
- data = error message as text/plain
When no auditor is configured (default), the failure path does not emit.
func WithErrorHandler ¶
WithErrorHandler installs a custom error transformer invoked when authentication fails. If the underlying error implements `SchemeAttemptsErr` (i.e. came from `Multi`), the hook can type-assert to retrieve per-scheme attempts.
func WithRulesFuncs ¶ added in v0.4.8
WithRulesFuncs registers one or more rule-table generator functions. `protoc-gen-servora-authn` emits one `AuthnRules() Rules` per .proto package; business code passes them as variadic args to merge across modules. Nil entries are skipped (no panic) so business code can pass optional generators conditionally.
Merge semantics:
- PublicMethods slices are appended in argument order.
- MethodSchemes entries from later generators overwrite earlier ones. RPC paths are fully qualified service names; collisions are rare in practice and the last-wins rule lets business code intentionally override a downstream module's annotation if needed.
type Rules ¶ added in v0.4.8
Rules is the aggregate authentication-rules table consumed by `Server`. It is produced by `protoc-gen-servora-authn` per generated package (e.g. `examplev1.AuthnRules()`) and merged across modules by `WithRulesFuncs`.
Two disjoint subsets:
- PublicMethods — RPC paths annotated `MODE_PUBLIC`; the dispatcher short-circuits before calling the engine.
- MethodSchemes — RPC paths annotated `MODE_REQUIRED`, mapped to the accepted scheme list (e.g. `["jwt", "apikey"]`); the dispatcher installs an `allowedSchemes` ctx channel so `Multi` can filter.
An RPC path absent from BOTH maps is unannotated; the dispatcher treats it as fail-open (no allowed-set installed; `Multi` tries every engine in injection order).
type SchemeAttempt ¶ added in v0.4.8
SchemeAttempt records one engine's outcome inside a `Multi` dispatch. Both fields are public so `WithErrorHandler` consumers can render per-scheme diagnostics (logging, metrics labels, custom RPC errors).
type SchemeAttemptsErr ¶ added in v0.4.8
type SchemeAttemptsErr interface {
error
SchemeAttempts() []SchemeAttempt
}
SchemeAttemptsErr is the public interface satisfied by the package-private error type returned from `Multi.Authenticate` when every allowed engine failed. Business code obtains structured access via type assertion:
authn.WithErrorHandler(func(ctx context.Context, err error) error {
if as, ok := err.(authn.SchemeAttemptsErr); ok {
for _, a := range as.SchemeAttempts() {
log.Errorw("authn attempt failed",
"scheme", a.Scheme, "reason", a.Reason)
}
}
return err
})
`Server` itself uses this interface to render safe structured failure reasons.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package apikey provides an API-key authentication skeleton for the engine-agnostic authn dispatcher.
|
Package apikey provides an API-key authentication skeleton for the engine-agnostic authn dispatcher. |
|
Package jwt provides a generic Bearer JWT authentication skeleton for the engine-agnostic authn dispatcher.
|
Package jwt provides a generic Bearer JWT authentication skeleton for the engine-agnostic authn dispatcher. |
|
Package noop provides a no-op Authenticator that passes through without enrichment.
|
Package noop provides a no-op Authenticator that passes through without enrichment. |