Help us shape the future of Go! Take the 2026 Go Developer Survey

authorizationdetails

package
v0.57.0 Latest Latest
Warning

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

Go to latest
Published: Oct 26, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package authorizationdetails validates the RFC 9396 authorization_details parameter of a token request and asks per-type hooks what to grant.

The package only parses and delegates. It does not persist the granted details, does not put them in tokens, and does not convey them to resource servers. Register only types whose enforcement the deployment performs itself.

Usage has two phases. Registry.Parse runs early and cheaply, before any expensive checks, and rejects malformed input. Pending.Grant runs late, after the request is otherwise accepted, and calls the hooks.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalid reports that the authorization_details parameter is malformed:
	// bad JSON, over a size or depth limit, duplicate member names, an entry
	// that is not an object, or a missing, unknown or wrong-grant "type".
	// Callers should answer with a generic invalid_authorization_details error
	// and must not echo request data.
	ErrInvalid = errors.New("invalid authorization_details")
)

Functions

This section is empty.

Types

type Error

type Error struct {
	Code   ErrorCode
	Reason string
}

Error is a client-visible rejection a Grant hook may return. Reason is shown to the client, so it must match [a-z0-9_]{1,64} and must not carry request data. Any other error a hook returns is treated as an internal failure.

func (Error) Error

func (e Error) Error() string

Error implements error.

type ErrorCode

type ErrorCode string

ErrorCode is the OAuth error code a hook may return to the client.

const (
	// CodeInvalidAuthorizationDetails is the RFC 9396 invalid_authorization_details error.
	CodeInvalidAuthorizationDetails ErrorCode = "invalid_authorization_details"
	// CodeInvalidRequest is the RFC 6749 invalid_request error. It is for
	// problems outside the authorization details themselves, such as a missing
	// or unacceptable related parameter. Problems in the details' content
	// (unknown fields, wrong types, invalid values, missing required fields)
	// must use CodeInvalidAuthorizationDetails, per RFC 9396 section 5.
	CodeInvalidRequest ErrorCode = "invalid_request"
)

type Pending

type Pending struct {
	// contains filtered or unexported fields
}

Pending is a parsed, not yet granted authorization_details value. It is single-use: call Grant at most once.

func (*Pending) Grant

func (p *Pending) Grant(ctx context.Context, req Request) (json.RawMessage, error)

Grant calls each type's hook once, in the order the types first appear in the request, and returns the granted entries as a JSON array: types in that order, each type's entries in the order its hook returned them ("[]" when the request held no entries). The package fills req.Entries and req.GrantType.

A hook must return at least one entry, and every entry is checked as strictly as the request: valid UTF-8, within the size limit, no duplicate member names, and an object of the hook's own type. The combined array must also fit the size limit. The output is built with encoding/json, so entries are compacted and HTML-escaped (<, > and & become \u003c, \u003e and \u0026): equal to the hook's output as JSON, not byte-identical.

Errors: Error is a hook rejection to pass to the client. A plain error means the package rejected hook output, and any other error is an untyped hook failure; both are internal failures whose text must not reach the client.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry holds the registered types. It is immutable and safe for concurrent use.

func New

func New(types map[string]Type) (*Registry, error)

New copies and validates the registered types, keyed by exact, case-sensitive type name. It rejects empty or whitespace names, a nil Grant, and an empty or blank GrantTypes list. A registry with no types is valid; it accepts only the empty array.

func (*Registry) Parse

func (r *Registry) Parse(raw, grantType string) (*Pending, error)

Parse checks the raw authorization_details value for the given grant type. The value must be at most 64 KiB of valid UTF-8 holding one JSON array of objects, nested at most 64 containers deep, in which no object repeats a member name (also not differing only in letter case; that rule is ToolHive policy, not RFC 9396). Every entry needs a non-empty string "type" that is registered for grantType. The empty array "[]" is valid.

Any failure returns ErrInvalid.

type Request

type Request struct {
	// Entries holds this type's entries in request order.
	Entries []json.RawMessage
	// GrantType is the grant type of the token request.
	GrantType string
	// ClientID is the authenticated client.
	ClientID string
	// Actor is the resolved actor; it equals ClientID without an actor_token.
	Actor string
	// ActorTokenPresent reports whether the request carried an actor_token.
	ActorTokenPresent bool
	// RequestedTokenType is the requested_token_type of the request.
	RequestedTokenType string
	// RequestedScopes are the scopes the client asked for.
	RequestedScopes []string
	// GrantedAudience is the audience the server has already decided to grant.
	GrantedAudience []string
	// Subject describes the validated subject token.
	Subject Subject
}

Request is the context a Grant hook receives. The caller supplies every field except Entries and GrantType, which the package fills.

All hooks of one request share the same Request values: the slices, Subject and Subject.Claims are not copied per hook, so a hook must not modify them. Only Entries is specific to the hook's type.

type Result

type Result struct {
	// Entries are the granted entries. The list must be non-empty and every
	// entry must be a JSON object whose "type" is the hook's own type.
	Entries []json.RawMessage
}

Result is what a Grant hook decided.

type Subject

type Subject struct {
	Issuer   string
	Subject  string
	ClientID string
	JWTID    string
	Audience []string
	IssuedAt time.Time
	Expiry   time.Time
	External bool // validated through a trusted issuer
	// Claims holds all verified claims, passed to hooks as given.
	Claims map[string]any
}

Subject describes a validated subject token.

type Type

type Type struct {
	// GrantTypes lists the grant types this type is accepted on. It is required
	// and must be non-empty. An entry of this type on any other grant type is
	// rejected as invalid.
	GrantTypes []string

	// Grant decides what to grant for all of this type's entries in a request.
	// It is called at most once per request, after the other checks passed,
	// with every entry of the type in request order.
	//
	// Grant is decide-only: it may read state but must not commit it, because
	// token issuance can still fail after it returns. Returning Error rejects
	// the request with that code and reason; any other error is an internal
	// failure.
	Grant func(context.Context, Request) (Result, error)
}

Type registers one authorization-details type.

Jump to

Keyboard shortcuts

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