auth

package
v0.18.0 Latest Latest
Warning

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

Go to latest
Published: Jun 28, 2026 License: AGPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Package auth handles CLI authentication: the device authorization grant (wallet/agent/passkey), service-account JWT-bearer, credential storage, and silent token refresh.

Index

Constants

View Source
const ClientID = "privasys-cli"

ClientID is the baked-in public OIDC client identifier for the CLI. The device flow uses no client secret and no redirect URI.

View Source
const DefaultScope = "openid email profile offline_access"

DefaultScope requests an id token, profile/email attributes, and a refresh token (offline_access) for silent renewal.

View Source
const PlatformAudience = "privasys-platform"

PlatformAudience is the default resource-server audience for the management-service API.

Variables

View Source
var ErrNotLoggedIn = errors.New("not authenticated: run `privasys auth login` or `privasys auth activate-service-account`")

ErrNotLoggedIn is returned when no credential exists for an issuer.

Functions

func AccessToken

func AccessToken(ctx context.Context, issuer string) (string, error)

AccessToken returns a valid access token for the issuer, honoring (in order): PRIVASYS_ACCESS_TOKEN, PRIVASYS_SERVICE_KEY, a stored service account, then a stored user credential (refreshing silently when needed).

func AccessTokenForAudience added in v0.7.0

func AccessTokenForAudience(ctx context.Context, issuer, audience string) (string, error)

AccessTokenForAudience mints an access token bound to a specific audience (e.g. "attestation-server") so the CLI can call that resource server directly. For user sessions it uses the refresh grant with an `audience:` scope (the rotated refresh token keeps the original scope); for service accounts it mints via JWT-bearer. PRIVASYS_ACCESS_TOKEN is returned as-is.

func Claims

func Claims(token string) (map[string]interface{}, error)

Claims decodes (without verifying) the payload of a JWT. Used for `whoami` against the caller's own token; trust comes from the token having been minted into the keychain by a verified flow, not from local re-validation.

func Delete

func Delete(issuer string) error

Delete removes a credential and any keychain secrets for the issuer.

func GeneratePKCE

func GeneratePKCE() (verifier, challenge string)

GeneratePKCE returns a random verifier and its S256 challenge.

func RemovePending added in v0.14.0

func RemovePending()

RemovePending deletes the pending device authorization (best-effort).

func Save

func Save(c *Credential) error

Save persists a credential, pushing the long-lived secrets to the keychain when it is available (falling back to the 0600 file otherwise).

func SavePending added in v0.14.0

func SavePending(p PendingDevice) error

SavePending writes the pending device authorization (0600).

func SaveUserCredential added in v0.14.0

func SaveUserCredential(issuer string, tr *TokenResponse) error

SaveUserCredential stores the tokens from a completed user login.

Types

type Credential

type Credential struct {
	Issuer          string    `json:"issuer"`
	ClientID        string    `json:"client_id,omitempty"`
	Subject         string    `json:"subject,omitempty"`
	Scope           string    `json:"scope,omitempty"`
	AccessToken     string    `json:"access_token,omitempty"`
	IDToken         string    `json:"id_token,omitempty"`
	AccessExpiresAt time.Time `json:"access_expires_at,omitempty"`

	// RefreshToken (user flows) — blanked from the file when kept in keychain.
	RefreshToken string `json:"refresh_token,omitempty"`

	// ServiceKey (Mode D) — the raw service-key JSON, minted on demand.
	// Blanked from the file when kept in keychain.
	ServiceKey string `json:"service_key,omitempty"`

	IsServiceKeyAcc bool `json:"is_service_account,omitempty"`
	// contains filtered or unexported fields
}

Credential is the stored authentication state for one issuer.

The long-lived secrets (refresh token, service-account key) are kept in the OS keychain when available; the short-lived access/id tokens and metadata live in a 0600 file. This split keeps the most sensitive material in the keychain while staying under per-item blob limits (e.g. Windows Credential Manager ~2.5KB) that a full JWT bundle would blow past.

func List

func List() ([]*Credential, error)

List returns the stored credentials (without rehydrating keychain secrets).

func Load

func Load(issuer string) (*Credential, error)

Load returns the credential for an issuer, rehydrating secrets from the keychain when they were stored there.

func (*Credential) MarshalJSON

func (c *Credential) MarshalJSON() ([]byte, error)

MarshalJSON/UnmarshalJSON make the unexported keychain flags persist.

func (*Credential) UnmarshalJSON

func (c *Credential) UnmarshalJSON(data []byte) error

type DeviceAuthResponse

type DeviceAuthResponse struct {
	DeviceCode              string `json:"device_code"`
	UserCode                string `json:"user_code"`
	VerificationURI         string `json:"verification_uri"`
	VerificationURIComplete string `json:"verification_uri_complete"`
	QRPayload               string `json:"qr_payload"`
	ExpiresIn               int    `json:"expires_in"`
	Interval                int    `json:"interval"`

	Error            string `json:"error"`
	ErrorDescription string `json:"error_description"`
}

DeviceAuthResponse is the /device_authorization result (RFC 8628 + the Privasys qr_payload extension).

func BeginDevice

func BeginDevice(ctx context.Context, issuer, scope, agentName string) (*DeviceAuthResponse, string, error)

BeginDevice starts a device authorization. The returned verifier must be kept by the caller and presented when polling.

type PendingDevice added in v0.14.0

type PendingDevice struct {
	Issuer     string    `json:"issuer"`
	DeviceCode string    `json:"device_code"`
	Verifier   string    `json:"verifier"`
	UserCode   string    `json:"user_code"`
	Interval   int       `json:"interval"`
	ExpiresAt  time.Time `json:"expires_at"`
}

PendingDevice persists an in-progress device authorization so a later invocation (CLI `auth poll`, or the MCP `auth_poll` tool) can complete it. It holds the PKCE verifier + device_code, so it lives in a 0600 file and is never returned through any agent-readable channel.

func LoadPending added in v0.14.0

func LoadPending() (PendingDevice, error)

LoadPending reads the pending device authorization, or an error if none.

type ServiceKey

type ServiceKey struct {
	Type      string `json:"type"`
	KeyID     string `json:"keyId"`
	Key       string `json:"key"` // RSA-2048 private key, PKCS#1 PEM
	UserID    string `json:"userId"`
	AccountID string `json:"accountId"`
}

ServiceKey is the on-disk service-account key (same shape the IdP issues).

func ParseServiceKey

func ParseServiceKey(data []byte) (*ServiceKey, error)

ParseServiceKey decodes a service-key.json document.

type TokenResponse

type TokenResponse struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	IDToken      string `json:"id_token"`
	TokenType    string `json:"token_type"`
	ExpiresIn    int    `json:"expires_in"`
	Scope        string `json:"scope"`

	Error            string `json:"error"`
	ErrorDescription string `json:"error_description"`
}

TokenResponse is the /token result for any grant.

func MintServiceAccountToken

func MintServiceAccountToken(ctx context.Context, issuer string, k *ServiceKey, audience string) (*TokenResponse, error)

MintServiceAccountToken exchanges a signed assertion for an access token via the JWT-bearer grant.

func PollOnce

func PollOnce(ctx context.Context, issuer, deviceCode, verifier string) (*TokenResponse, time.Duration, error)

PollOnce performs a single device_code token poll. On success it returns the tokens; while pending it returns (nil, nil); other errors are returned.

func PollUntil

func PollUntil(ctx context.Context, issuer, deviceCode, verifier string, interval int, expiresIn int) (*TokenResponse, error)

PollUntil polls until approval, expiry, or ctx cancellation, honoring the server interval and slow_down back-off.

Jump to

Keyboard shortcuts

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