authn

package
v0.16.0 Latest Latest
Warning

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

Go to latest
Published: Oct 6, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package authn is the server side of the SDK's auth package: the JWT authenticator, which verifies a bearer token against the issuers a deployment trusts, and the access-roster grants preset. They need a JWT library and the access-roster vocabulary, which an emitter does not, so they are not in the SDK.

Index

Constants

View Source
const (
	// GroupSeparator separates the segments of a group name.
	GroupSeparator = ":"
	// ScopeAll is the scope of a role over the whole installation rather than one
	// of its tenants. What it means is the reader's to decide: this preset reads
	// it as every tenant.
	ScopeAll = "all"
)
View Source
const Thing = "audit"

Thing is what an audit log is called in the thing position of a grant.

Variables

This section is empty.

Functions

func SplitGroup added in v0.13.0

func SplitGroup(name string) (scope, thing, role string, ok bool)

SplitGroup reads a group name as a grant: the scope the role is held in, the thing it is held on, and the role. It reports false for a name that is not a grant: two segments, an empty segment, or a fourth one. The scope is returned as written, so ScopeAll comes back as "all".

Types

type AccessRoster

type AccessRoster struct {
	// From is the issuer whose groups are read, or "" for any while one
	// issuer is trusted.
	From string
	// Claim is where the groups are. Empty means "groups".
	Claim string
	// Profiles is the deployment's profiles by name, each with the presets it
	// was composed from. It is what turns a role into profile names.
	Profiles map[string][]string
}

AccessRoster reads grants out of access-roster's group vocabulary.

Every grant there is named `<scope>:<thing>:<role>` — role, on thing, in scope — and this preset reads the ones whose thing is "audit". The scope is "all" or an audit tenant identifier, byte for byte; an environment is not in the name, because each deployment's query service requires its own token audience and the issuer decides who may hold which, which is where the estate already keeps that boundary.

A role grants operations over the profiles built from certain presets, so that a deployment's own profile names need no mention: a profile composed from `security` and `dora` is a security profile whatever it is called.

Two roles are deliberately absent. `resolve` comes from no group name; it undoes the pseudonymisation and is granted by an explicit rule naming the person. And there is no assessor role, because a group name carries no dates; a time-boxed grant is an explicit rule with a window.

func (AccessRoster) Grants

func (a AccessRoster) Grants(p auth.Principal) []auth.Grant

Grants implements Preset.

Each audit group the principal holds becomes one grant, named for the group, so that the record of a read says `acme:audit:viewer` rather than a rule name somebody invented. A group whose role covers none of this deployment's profiles grants nothing here, which is right: a billing role in a deployment with no billing profile has nothing to read.

func (AccessRoster) Issuer

func (a AccessRoster) Issuer() string

Issuer implements Preset.

func (AccessRoster) Name

func (AccessRoster) Name() string

Name implements Preset.

type Issuer

type Issuer struct {
	// URL is the issuer exactly as its tokens name it. Discovery and the key set
	// are found from it, and a token is sent to this issuer's keys only if its
	// iss claim is this string, byte for byte.
	URL string
	// Audience is required. An audit log is the last API that should accept a
	// token minted for some other service: a workload that received a user's
	// token could otherwise replay it here and read the trail under that user's
	// grants.
	Audience string
}

Issuer is a token issuer a deployment trusts.

type JWT

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

JWT authenticates bearer tokens from any of several issuers.

Verification is gateway-auth's, one verifier per issuer, so that a token is checked here exactly as every other service in the fleet checks it: key set fetched by discovery and refreshed in the background, signature, issuer, audience and expiry. What this adds is the choice between issuers. A token's iss claim is read before verification only to pick whose keys to check it with, and the chosen verifier then requires that same issuer, so a token claiming the wrong issuer fails verification rather than being believed.

Several issuers make one thing possible that a single issuer does not: two of them asserting the same claim. See Rule.Issuer.

func NewJWT

func NewJWT(ctx context.Context, issuers []Issuer, logger *slog.Logger) (*JWT, error)

NewJWT builds the authenticator, discovering every issuer now so that one that is unreachable or misnamed stops the service at start-up rather than on its first request.

func (*JWT) Principal

func (j *JWT) Principal(ctx context.Context, req *http.Request) (auth.Principal, error)

Principal implements Authenticator.

Jump to

Keyboard shortcuts

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