auth

package
v0.13.0 Latest Latest
Warning

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

Go to latest
Published: Jun 15, 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 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).

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 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