refusal

package
v1.76.10 Latest Latest
Warning

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

Go to latest
Published: Oct 15, 2026 License: MIT Imports: 8 Imported by: 0

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

View Source
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.

View Source
const Header = "X-Request-Id"

Header carries the request id, inbound when a gateway set it and always on the response.

View Source
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 ID

func ID(ctx context.Context) string

ID is the request id the context carries, or empty outside a request.

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

func LogHandler(next slog.Handler) slog.Handler

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

func Middleware(next http.Handler) http.Handler

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

func Text(ctx context.Context, phrase string) string

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

func WellFormed(id string) bool

WellFormed reports whether a caller's id may be adopted: letters, digits and . _ : - only, between eight and sixty-four of them.

func WithID

func WithID(ctx context.Context, id string) context.Context

WithID carries an id on a context, for work that has no request to take one from and for the tests that stand in for one.

Types

This section is empty.

Jump to

Keyboard shortcuts

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