sessionmint

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 7, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package sessionmint centralizes access-JWT issuance so that login, IssueForUser (change-password flow), and refresh share a single fail-closed "fetch roles → sign access" pipeline. Opaque refresh tokens are issued by runtime/auth/refresh.Store directly from the slice layer, so sessionmint no longer deals with refresh tokens at all.

Fail-closed contract: if the RoleRepository cannot resolve a user's roles (infrastructure fault), MintAccess returns ErrAuthRoleFetchFailed so the caller aborts the in-flight authn action instead of silently issuing a token with empty roles — an outcome that looks like a successful authentication but strips every RBAC capability.

ref: kubernetes/apiserver pkg/authentication/request/union/union.go (FailOnError: credential error short-circuits the chain, never fallthrough) ref: kratos middleware/auth/jwt — claim parse failure aborts, never issues a "token without claims".

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Deps

type Deps struct {
	// Issuer signs the access JWT. Required.
	Issuer TokenIssuer
	// RoleRepo resolves the user's current role names. Required.
	RoleRepo ports.RoleRepository
}

Deps injects the collaborators MintAccess needs.

type Request

type Request struct {
	UserID                string
	SessionID             string
	PasswordResetRequired bool
	// TenantID scopes the role lookup to the correct tenant.
	// Required for GetByUserID (RoleRepository.GetByUserID takes tenant param).
	TenantID tenant.TenantID
}

Request is the per-call input for a MintAccess.

type Result

type Result struct {
	AccessToken string
	Roles       []string
	ExpiresAt   time.Time
	JTI         string
}

Result is the MintAccess output.

ExpiresAt is sampled from Deps.Clk (or clock.Real()) at MintAccess entry; the JWT's own exp claim is stamped independently inside the issuer a moment later. Treat Result.ExpiresAt as the business-layer expiry (used for Session persistence) — the authoritative wire value is the JWT exp claim.

JTI is the per-token unique identifier embedded in the JWT `jti` claim (RFC 9068 §2.2.4). It is generated fresh inside MintAccess so each access token — including post-rotation tokens minted by Refresh — carries its own jti, satisfying ADR-credential D1's per-token uniqueness invariant.

func MintAccess

func MintAccess(ctx context.Context, clk clock.Clock, deps Deps, req Request) (Result, error)

MintAccess fetches the user's role names and signs the access JWT. Role- fetch failure propagates as ErrAuthRoleFetchFailed (HTTP 500) so the caller aborts login / refresh / IssueForUser rather than issue an empty-role token.

The jti claim is a fresh UUIDv4 per token (RFC 9068 §2.2.4); collision probability is negligible and uuid.NewString never errors. Carrying jti alongside sid matches ADR-credential D1 so observability + revocation diagnostics can trace individual tokens. Result.JTI is returned for callers that persist the value (e.g. session row fingerprint when FingerprintJTIRef is in use). The authz_epoch claim has been removed from the JWT in S4d — epoch provenance is now stored exclusively in the session/refresh rows.

type TokenIssuer

type TokenIssuer interface {
	Issue(intent kauth.TokenIntent, subject string, opts auth.IssueOptions) (string, error)
}

TokenIssuer is the minimal surface MintAccess needs from a JWT issuer. Exposing the interface keeps sessionmint unit-testable with a stub issuer. Production code passes in *auth.JWTIssuer directly (it satisfies this interface by method set).

Jump to

Keyboard shortcuts

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