auth

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jun 8, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package auth implements the capability-token model: claim set, internal JWT-like encoding (no third-party dep), revocation list, and the issuance flow with TTY/notification confirmation.

See docs/harness-architecture.md § Authentication.

Package auth is part of the GoFastr harness.

See docs/harness-architecture.md for the architecture this package implements.

Index

Constants

View Source
const VerCurrent = 1

VerCurrent is the claim set version this binary issues. Verifiers rejecting an unrecognized Ver fail-closed.

Variables

View Source
var (
	ErrNoChannel    = errors.New("auth: token issuance requires an interactive confirmation channel; see --auth-token-file for headless setups")
	ErrUnknownMint  = errors.New("auth: unknown mint ID")
	ErrCodeMismatch = errors.New("auth: confirmation code mismatch")
	ErrCodeExpired  = errors.New("auth: confirmation code expired (60s window)")
)

Errors surfaced as user-facing strings per § User-facing errors.

Functions

func GenerateSecret

func GenerateSecret() ([]byte, error)

GenerateSecret returns a fresh 32-byte HMAC secret.

Types

type Channel

type Channel interface {
	// Show displays the code and a short description (which session
	// / which identity class is being minted) for the user to see.
	Show(ctx context.Context, code string, desc string) error
}

Channel is the surface that displays a 6-digit confirmation code to the user out-of-band. Implementations: TTY printer, system notification, or a bundled trusted-client modal. See § Token issuance.

type Claims

type Claims struct {
	Ver            int                   `json:"ver"`
	JTI            ids.JTI               `json:"jti"`
	Sessions       []ids.SessionID       `json:"sessions,omitempty"`
	Commands       []string              `json:"commands,omitempty"`
	IdentityClass  control.IdentityClass `json:"identity_class"`
	NotBefore      int64                 `json:"nbf,omitempty"`
	ExpiresAt      int64                 `json:"exp"`
	CanMint        bool                  `json:"can_mint"`
	CriticalClaims []string              `json:"critical_claims,omitempty"`
}

Claims is the token claim set. Verifiers MUST reject a token whose Ver they do not recognize. See § Protocol versioning → Token versioning.

func ClaimsFor

func ClaimsFor(session ids.SessionID, identity control.IdentityClass) Claims

ClaimsFor builds a default claim set for a specific session + identity class with the doc's recommended defaults.

func Verify

func Verify(enc *Encoder, rl *RevocationList, token string, now time.Time) (Claims, error)

Verify validates a token end-to-end: signature, version, not-before, expiry, revocation. Returns the parsed claims on success.

func (Claims) AllowsCommand

func (c Claims) AllowsCommand(kind string) bool

AllowsCommand reports whether the token can issue the given command kind. An empty Commands list means "any command."

func (Claims) AllowsSession

func (c Claims) AllowsSession(s ids.SessionID) bool

AllowsSession reports whether the token may attach to the given session. An empty Sessions list means "any session" — only allowed for the bootstrap token.

func (Claims) Expired

func (c Claims) Expired(now time.Time) bool

Expired reports whether the token is past its exp at the given time.

type Encoder

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

Encoder signs and encodes claim sets. Use a per-machine secret; never persist tokens to disk plaintext (the bootstrap token is returned to the requester and held in their keychain).

func NewEncoder

func NewEncoder(secret []byte) *Encoder

NewEncoder returns an Encoder with the given HMAC secret.

In production, the secret is loaded from the credstore at boot. A fresh secret invalidates every outstanding token.

func (*Encoder) Decode

func (e *Encoder) Decode(token string) (Claims, error)

Decode parses and verifies a token. Returns the claim set or an error if the signature is invalid or the version is unrecognized.

Per § Unknown-field policy → token claims, a token with critical claims the verifier doesn't recognize is rejected; non-critical unknown claims are ignored. The current verifier recognizes all fields above.

func (*Encoder) Encode

func (e *Encoder) Encode(c Claims) (string, error)

Encode signs the claim set with HMAC-SHA256 and returns the `<payload>.<signature>` token string. Both halves are URL-safe-base64 without padding.

type ExpiredError

type ExpiredError struct{ ExpAt time.Time }

ExpiredError matches control.ReasonTokenExpired on the wire.

func (*ExpiredError) Error

func (e *ExpiredError) Error() string

type Issuer

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

Issuer mints capability tokens. Each issuance follows the out-of-band confirmation protocol described in the architecture doc:

  1. Caller invokes Begin with desired claims.
  2. Issuer picks a 6-digit code, asks Channel.Show to display it.
  3. Caller POSTs the code back via Confirm within 60s.
  4. On match, Issuer returns the encoded token.

func NewIssuer

func NewIssuer(enc *Encoder, channel Channel) *Issuer

NewIssuer constructs an Issuer using the given encoder and channel.

If channel is nil the issuer refuses to mint (the doc commits to: "Refuses token issuance with an explicit error: 'Token issuance requires an interactive confirmation channel.'")

func (*Issuer) Begin

func (i *Issuer) Begin(ctx context.Context, claims Claims, desc string) (mintID string, err error)

Begin starts a mint attempt. Returns a mint ID the caller passes back to Confirm, plus the chosen claim set (the issuer may have added defaults like JTI and exp).

If channel is nil, returns ErrNoChannel — the issuer refuses to proceed.

func (*Issuer) Confirm

func (i *Issuer) Confirm(mintID, code string) (string, error)

Confirm completes a mint attempt by checking the user-supplied code against the one the channel showed. On match, returns the encoded token.

func (*Issuer) IssueDirect

func (i *Issuer) IssueDirect(claims Claims) (string, error)

IssueDirect bypasses the confirmation flow. Used by pre-provisioned CI flows where the user has already vouched out-of-band (e.g. by placing a token file with mode 0400). Never expose this on a network transport.

func (*Issuer) WithClock

func (i *Issuer) WithClock(now func() time.Time) *Issuer

WithClock overrides the clock function (for tests).

type PrintTTYChannel

type PrintTTYChannel struct {
	W interface{ Write(p []byte) (int, error) }
}

PrintTTYChannel is a Channel that writes the code to the given io.Writer. The TTY-displaying main loop wires this with os.Stderr.

func (PrintTTYChannel) Show

func (c PrintTTYChannel) Show(ctx context.Context, code string, desc string) error

type RevocationList

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

RevocationList tracks revoked JTIs. Concurrency-safe in-memory store; persistent backing is the caller's responsibility (the docs commit to ~/.local/state/gofastr/harness/revocations.db).

func NewRevocationList

func NewRevocationList() *RevocationList

NewRevocationList returns an empty RevocationList.

func (*RevocationList) IsRevoked

func (r *RevocationList) IsRevoked(jti ids.JTI) bool

IsRevoked reports whether a JTI has been revoked.

func (*RevocationList) Revoke

func (r *RevocationList) Revoke(jti ids.JTI)

Revoke marks a JTI revoked.

func (*RevocationList) Snapshot

func (r *RevocationList) Snapshot() map[ids.JTI]int64

Snapshot returns a copy of the current revocation set. Used for persistence at shutdown.

type RevokedError

type RevokedError struct{ JTI ids.JTI }

RevokedError matches control.ReasonTokenRevoked on the wire.

func (*RevokedError) Error

func (e *RevokedError) Error() string

Jump to

Keyboard shortcuts

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