Documentation
¶
Overview ¶
Package serviceauth provides constant-time validation of shared service-to-service tokens. It is intended for the IAM mono-repo's service-to-service auth edges (auth ↔ caller, dataaccess ↔ caller, ...) and answers the question "is the calling process a trusted peer service". It does NOT establish end-user identity — see pkg/userauth for that.
Each service owns its own metadata header name and interceptor; this package only owns the comparison logic.
Index ¶
Constants ¶
This section is empty.
Variables ¶
ErrUnauthorized is returned when the presented token does not match any of the configured tokens.
Functions ¶
func HTTPMiddleware ¶ added in v1.26.0
HTTPMiddleware returns middleware that validates the service token presented under headerName against the tokens derived from cfg (Config.Tokens()). It wraps next and rejects requests where the header is missing, empty, or does not match — responding with 401 Unauthorized and a JSON body {"error":"Unauthorized"}.
cfg.NextServiceToken, if set, is accepted alongside cfg.ServiceToken to support zero-downtime rotation.
func UnaryServerInterceptor ¶ added in v1.26.0
func UnaryServerInterceptor(cfg Config, headerName string, publicMethods map[string]bool) grpc.UnaryServerInterceptor
UnaryServerInterceptor returns a gRPC unary server interceptor that validates the service token presented under headerName for all RPCs not in publicMethods. The accepted tokens are derived from cfg (Config.Tokens()).
On any failure — missing metadata, missing or empty header, or token rejection — the interceptor returns codes.Unauthenticated with an opaque "Unauthorized" message. Distinguishing the cause would leak whether a token was provided, providing an oracle to attackers.
Types ¶
type Config ¶ added in v1.26.0
type Config struct {
ServiceToken string `mapstructure:"service_token"`
NextServiceToken string `mapstructure:"next_service_token"`
}
Config is the subset of a service's configuration that controls service-to-service shared-secret authentication. Services embed this with the mapstructure squash tag so the TOML keys sit at the top level of the service's table, e.g.:
[services.data-access] service_token = "..." next_service_token = ""
During rotation, NextServiceToken holds the new token alongside the current one; a Validator built from Tokens() accepts either.
type Validator ¶
type Validator struct {
// contains filtered or unexported fields
}
Validator performs constant-time token validation against a set of pre-computed SHA-512 hashes. It is safe for concurrent use.
func NewValidator ¶
NewValidator creates a Validator that accepts the given tokens. Empty token strings are silently ignored so callers can pass an optional next-token slot without conditional logic.