Documentation
¶
Overview ¶
Package refusal is how this service says no.
A caller who is refused learns that they were, and a number: the request id. The reason -- which rule, which group, which client, whether a thing exists at all -- goes to the log and to the audit record under that same id, where an operator can read it and a caller cannot. A reason in the response is a question answered for whoever is probing: whether a client id exists, which audience a proof would open, which group would have been enough.
This package holds the part every surface shares: the request id (one middleware, so every HTTP surface has one), the fixed wording, and the Connect interceptor. The OAuth endpoints' helper lives beside the endpoints, in internal/issuer, because it speaks the library's errors.
Index ¶
- Constants
- func ConnectOptions(log *slog.Logger) []connect.HandlerOption
- func ID(ctx context.Context) string
- func Interceptor(log *slog.Logger) connect.Interceptor
- func LogHandler(next slog.Handler) slog.Handler
- func Middleware(next http.Handler) http.Handler
- func Text(ctx context.Context, phrase string) string
- func WellFormed(id string) bool
- func WithID(ctx context.Context, id string) context.Context
Constants ¶
const ( // NotAuthorised is the answer to every refusal. NotAuthorised = "not authorised" // ServerError is the answer to a fault of ours. ServerError = "server error" // InvalidRequest is the answer to a request that is not well-formed. InvalidRequest = "invalid request" // SignInFirst is the answer to a caller who is nobody yet. SignInFirst = "sign in first" )
The fixed wording. Every refusal a caller reads is one of these and the id; nothing about why is ever formatted into them.
const Header = "X-Request-Id"
Header carries the request id, inbound when a gateway set it and always on the response.
const LogKey = "request_id"
LogKey is the attribute a log line carries the request id under.
Variables ¶
This section is empty.
Functions ¶
func ConnectOptions ¶
func ConnectOptions(log *slog.Logger) []connect.HandlerOption
ConnectOptions installs Interceptor on a Connect handler.
func Interceptor ¶
func Interceptor(log *slog.Logger) connect.Interceptor
Interceptor is how a Connect service says no.
The handlers behind it name their reasons freely -- "this needs the operator role over acme's directory", "that is somebody else's session", the text of an error from a store -- because a reason written where the refusal is made is a reason a maintainer can read. This is the one place they are kept from the caller:
- PermissionDenied is "not authorised (request <id>)", and the message the handler wrote is logged under the id.
- Internal, and the Unknown a plain error becomes, is "server error (request <id>)", and the error is logged under the id.
- Unauthenticated is "sign in first": the caller is nobody yet, and what was wrong with their credential is not theirs to be told.
Every other code is the handler's own answer to the question asked -- not found, invalid argument, a failed precondition -- and passes untouched.
log is where the originals go; nil is the default logger at the time of the call.
func LogHandler ¶
LogHandler adds the request id to every record logged with a request's context, whoever logs it -- this service's own code or the OpenID library's, which logs the parent of every error it answers with. That is how a caller's "request 1f3a..." finds the line that says why.
A record that already names the id itself is left as it is.
func Middleware ¶
Middleware gives every request an id, puts it on the response and on the context, and hands the audit trail the same one.
An inbound X-Request-Id is taken when it is well-formed and short -- a gateway's id is how a caller's report reaches the log line -- and replaced by a random one otherwise, so a caller cannot put arbitrary text into a log through it. Idempotent: a handler already under one keeps the id it has, which is how the merged service nests the console inside the issuer.
func Text ¶
Text is a fixed phrase with the request id, "not authorised (request 1f3a...)". With no id -- a call outside a request -- it is the phrase alone.
func WellFormed ¶
WellFormed reports whether a caller's id may be adopted: letters, digits and . _ : - only, between eight and sixty-four of them.
Types ¶
This section is empty.