Repository navigation
Expand file tree
/
Copy pathauthenticator.go
More file actions
62 lines (55 loc) · 2.65 KB
/
Copy pathauthenticator.go
File metadata and controls
62 lines (55 loc) · 2.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// Copyright 2026 Hyperscale. All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
package security
import "context"
// Authenticator validates an [Authentication] produced by an [Extractor] and
// returns a NEW authenticated value. It MUST NOT mutate its input — the
// Authentication is treated as immutable everywhere in the core.
//
// Two-step contract:
//
// - Supports reports whether the authenticator recognizes the credential
// type. Implementations MUST be cheap (a type switch); they MUST NOT
// perform I/O.
// - Authenticate validates the credential and either returns the new,
// authenticated value (IsAuthenticated() == true) or an error wrapping
// a security sentinel.
//
// The sentinel tells the transports how to answer:
//
// - a verdict on the credentials wraps [ErrInvalidCredentials],
// [ErrTokenExpired], [ErrTokenNotFound] or [ErrClientSecretMismatch];
// - a dependency that is temporarily down (user store, key set,
// introspection endpoint) wraps [ErrUnavailable]: the credentials could
// not be checked, they are not refused;
// - [ErrUnsupportedCredential] is the canonical way to bail out at runtime
// when Supports returned true but the value was nonetheless out of
// scope: the [Manager] counts it as an abstention — unless the error
// also wraps one of the sentinels above, which then prevails.
//
// An error wrapping no sentinel, or a "success" without an authenticated
// value (nil, a typed nil or an unauthenticated value), is a contract
// violation the transports answer as an internal error.
//
// Implementations MUST be safe for concurrent use.
type Authenticator interface {
Supports(auth Authentication) bool
Authenticate(ctx context.Context, auth Authentication) (Authentication, error)
}
// AuthenticatorFunc adapts a function to the Authenticator interface. It
// reports Supports == true for every input; callers wanting selectivity
// should write a concrete type instead.
type AuthenticatorFunc func(ctx context.Context, auth Authentication) (Authentication, error)
// Supports implements [Authenticator].
func (AuthenticatorFunc) Supports(Authentication) bool { return true }
// Authenticate implements [Authenticator].
func (f AuthenticatorFunc) Authenticate(ctx context.Context, auth Authentication) (Authentication, error) {
return f(ctx, auth)
}
// NamedAuthenticator is an optional capability: when an Authenticator
// implements it, the [Manager] records the name in the OTel span so
// observability backends can attribute decisions per provider.
type NamedAuthenticator interface {
AuthenticatorName() string
}