refresh

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 14, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package refresh contains provider-neutral renewable credential sources.

A refresh State is an opaque, versioned payload. It deliberately keeps access authority out of its encoded form by default; a source may opt into access-token persistence only when its provider requires it for cross-process adoption.

Index

Constants

View Source
const (
	// StateSchemaV1 is the only state schema understood by this release.
	StateSchemaV1 uint32 = 1
	SchemaV1      uint32 = StateSchemaV1
	StateVersion1 uint32 = StateSchemaV1
	// MaxStateBytes bounds decoding before a provider-controlled payload can be
	// retained in memory.
	MaxStateBytes = 128 << 10
	// MaxProviderDataBytes bounds continuity fields carried between exchanges.
	MaxProviderDataBytes = 32 << 10
)
View Source
const LockFilename = ".credential-refresh.lock"

LockFilename is the owner-only lock entry used by FileCoordinator.

Variables

View Source
var (
	ErrInvalidState        = errors.New("credentials/refresh: invalid state")
	ErrInvalidOptions      = errors.New("credentials/refresh: invalid options")
	ErrExchange            = errors.New("credentials/refresh: token exchange failed")
	ErrRefresh             = errors.New("credentials/refresh: refresh failed")
	ErrAmbiguousRotation   = errors.New("credentials/refresh: ambiguous token rotation")
	ErrAmbiguousRefresh    = ErrAmbiguousRotation
	ErrRefreshAmbiguous    = ErrAmbiguousRotation
	ErrAdoptionUnavailable = errors.New("credentials/refresh: advanced generation has no usable lease")
	ErrCoordinator         = errors.New("credentials/refresh: coordinator unavailable")
	ErrUnsupportedPlatform = errors.New("credentials/refresh: unsupported platform")
	ErrDurabilityUnknown   = errors.New("credentials/refresh: visible commit durability unknown")
	ErrClosed              = credentials.ErrSourceClosed
	ErrCanceled            = credentials.ErrCanceled
)

Functions

func EncodeState

func EncodeState(state State) (secrets.Secret, error)

EncodeState validates and bounds an opaque persisted state value.

func MarshalState

func MarshalState(state State) (secrets.Secret, error)

MarshalState is an alias kept for callers that prefer an explicit verb.

func NewCoordinator

func NewCoordinator(args ...any) (credentials.RefreshCoordinator, error)

NewCoordinator is a convenience constructor. With no argument it returns a process coordinator; with a string argument it opens a host lock. A credentials.SharingScope argument selects the process implementation (the scope is retained for validation by callers but cannot provide host safety).

Types

type AmbiguousRotationError

type AmbiguousRotationError struct {
	Reference  credentials.Reference
	Generation credentials.Generation
}

AmbiguousRotationError reports a possibly consumed refresh token whose durable CAS outcome could not be established. It intentionally carries only safe identity metadata and must trigger explicit recovery/login.

func (*AmbiguousRotationError) Error

func (e *AmbiguousRotationError) Error() string

func (*AmbiguousRotationError) Format

func (e *AmbiguousRotationError) Format(s fmt.State, _ rune)

func (*AmbiguousRotationError) GoString

func (e *AmbiguousRotationError) GoString() string

func (*AmbiguousRotationError) Unwrap

func (e *AmbiguousRotationError) Unwrap() error

type Clock

type Clock = credentials.Clock

Clock is an injectable source clock. It is an alias so provider packages can use the same clock contract as credentials.Builder.

type ClockFunc

type ClockFunc = credentials.ClockFunc

ClockFunc adapts a function to Clock.

type Config

type Config = Options

type Coordinator

type Coordinator = credentials.RefreshCoordinator

Coordinator is the concise name used by provider adapters.

type ExchangeError

type ExchangeError struct{}

ExchangeError intentionally discards arbitrary provider error values.

func (*ExchangeError) Error

func (e *ExchangeError) Error() string

func (*ExchangeError) Format

func (e *ExchangeError) Format(s fmt.State, _ rune)

func (*ExchangeError) GoString

func (e *ExchangeError) GoString() string

func (*ExchangeError) Unwrap

func (e *ExchangeError) Unwrap() error

type ExchangeFunc

type ExchangeFunc func(context.Context, State) (TokenResponse, error)

ExchangeFunc is the preferred provider callback shape. Options.Exchange intentionally accepts any compatible function/interface so existing providers can use a State, Secret, or their own small adapter without the refresh package importing provider policy.

type ExchangeResult

type ExchangeResult = TokenResponse

ExchangeResult and Token are compatibility aliases for provider packages that use those names for a token exchange response.

type FileCoordinator

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

FileCoordinator is a host-visible coordinator backed by an owner-only lock file. The platform implementation owns descriptor and no-follow details.

func NewFileCoordinator

func NewFileCoordinator(root string) (*FileCoordinator, error)

NewFileCoordinator opens a host-visible lock rooted at root. The root is explicit and is never inferred from the environment or user home.

func NewLocalCoordinator

func NewLocalCoordinator(root string) (*FileCoordinator, error)

NewLocalCoordinator is an alias for NewFileCoordinator.

func (*FileCoordinator) Close

func (c *FileCoordinator) Close() error

func (*FileCoordinator) Scope

func (*FileCoordinator) WithLock

func (c *FileCoordinator) WithLock(ctx context.Context, ref credentials.Reference, fn func(context.Context) error) error

type InvalidStateError

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

InvalidStateError never retains input bytes or provider response text.

func (*InvalidStateError) Error

func (e *InvalidStateError) Error() string

func (*InvalidStateError) Format

func (e *InvalidStateError) Format(state fmt.State, _ rune)

func (*InvalidStateError) GoString

func (e *InvalidStateError) GoString() string

func (*InvalidStateError) Unwrap

func (e *InvalidStateError) Unwrap() error

type Lease

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

Lease is an immutable, concurrency-safe lease snapshot. Access tokens are retained only inside the authorizer constructed at publication time.

func (*Lease) Authorizer

func (l *Lease) Authorizer() httpauth.Authorizer

func (*Lease) Descriptor

func (l *Lease) Descriptor() credentials.Descriptor

func (*Lease) ExpiresAt

func (l *Lease) ExpiresAt() time.Time

func (*Lease) Format

func (l *Lease) Format(state fmt.State, _ rune)

func (*Lease) Generation

func (l *Lease) Generation() credentials.Generation

func (*Lease) GoString

func (l *Lease) GoString() string

func (*Lease) String

func (l *Lease) String() string

type Options

type Options struct {
	Reference  credentials.Reference
	Descriptor credentials.Descriptor
	State      secrets.Reference
	// StateReference is a descriptive alias for State.
	StateReference secrets.Reference

	Resolver      secrets.Resolver
	Store         secrets.Store
	Preconditions secrets.PreconditionCapabilities

	Coordinator        credentials.RefreshCoordinator
	RefreshCoordinator credentials.RefreshCoordinator
	StateSharing       credentials.SharingScope
	Sharing            credentials.SharingScope

	Clock Clock
	Now   func() time.Time

	ExpirySkew time.Duration
	// Skew is a descriptive alias for ExpirySkew.
	Skew time.Duration
	// RefreshTimeout bounds provider exchange and persistence. It is owned by
	// the source and is not derived from an initiating request context.
	RefreshTimeout       time.Duration
	SourceRefreshTimeout time.Duration

	// Exchange, Refresh, and Refresher may be a typed ExchangeFunc or an
	// adapter with a compatible method/function shape. Reflection at this
	// provider-neutral boundary lets provider packages retain their own token
	// response type while the source validates the normalized result.
	Exchange  any
	Refresh   any
	Refresher any

	// InitialState is useful when a provider has already acquired a memory-only
	// access token. If Schema is zero, the state is loaded from Resolver.
	InitialState State
	// PersistAccessToken opts into durable access-token adoption across
	// processes. It is false by default because access authority is normally
	// memory-only.
	PersistAccessToken bool

	// Context bounds constructor-time state resolution. A nil value uses a
	// background context; it never becomes the refresh context.
	Context context.Context
}

Options constructs one renewable source for one exact credential identity. Resolver and Store refer to the same state reference. Store must affirm compare-and-swap support; a refresh never silently falls back to an unconditional write.

type ProcessCoordinator

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

ProcessCoordinator provides keyed in-process single exclusion. It is useful for tests and process-local state; callers using host/shared state should use NewFileCoordinator or inject an equivalent distributed implementation.

func NewInProcessCoordinator

func NewInProcessCoordinator() *ProcessCoordinator

NewInProcessCoordinator is a descriptive constructor alias.

func NewProcessCoordinator

func NewProcessCoordinator() *ProcessCoordinator

NewProcessCoordinator constructs a process-local coordinator.

func (*ProcessCoordinator) Close

func (c *ProcessCoordinator) Close() error

Close prevents new lock acquisitions. Existing callbacks are not canceled; source-owned refresh contexts provide their own bounded lifetime.

func (*ProcessCoordinator) Scope

func (*ProcessCoordinator) WithLock

type RefreshCoordinator

type RefreshCoordinator = credentials.RefreshCoordinator

RefreshCoordinator is re-exported for provider packages that only import the refresh package.

type RefreshResponse

type RefreshResponse = TokenResponse

type RefreshState

type RefreshState = State

RefreshState is a descriptive alias for State.

type Source

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

Source is a renewable credentials.Source. It owns refresh coordination for one exact reference and publishes only immutable leases after state CAS.

func New

func New(args ...any) (*Source, error)

New constructs a Source from Options. The variadic form also accepts a *Options and keeps source construction forwards-compatible with provider adapters that pass an optional context as a second argument.

func NewRefreshableSource

func NewRefreshableSource(args ...any) (*Source, error)

NewRefreshableSource is a descriptive constructor alias.

func NewSource

func NewSource(args ...any) (*Source, error)

NewSource is the conventional constructor alias.

func NewWithOptions

func NewWithOptions(args ...any) (*Source, error)

NewWithOptions is an explicit constructor alias.

func (*Source) Acquire

func (s *Source) Acquire(ctx context.Context) (credentials.Lease, error)

Acquire returns a current immutable lease or starts one shared refresh. Waiting callers observe their own context cancellation; cancellation never cancels the source-owned exchange shared by other callers.

func (*Source) CanRecover

func (s *Source) CanRecover(failure credentials.Failure) bool

CanRecover reports whether this source can recover from an authentication failure without provider-specific policy.

func (*Source) Close

func (s *Source) Close() error

Close prevents new acquisitions. In-flight refreshes retain their source-owned bounded context and may complete an already-admitted lease.

func (*Source) Descriptor

func (s *Source) Descriptor() credentials.Descriptor

Descriptor returns a copy of the exact authority binding.

func (*Source) Invalidate

func (s *Source) Invalidate(ctx context.Context, generation credentials.Generation, failure credentials.Failure) error

Invalidate marks only the currently matching generation unusable. A late invalidation from an older request is ignored after a successful rotation.

func (*Source) Reauth

func (s *Source) Reauth(ctx context.Context, value any) error

Reauth is a concise alias for Reauthenticate.

func (*Source) Reauthenticate

func (s *Source) Reauthenticate(ctx context.Context, value any) error

Reauthenticate rotates the single opaque state record for this existing reference with a CAS against its current version. It never deletes or recreates the safe catalog record. value may be a TokenResponse, State, or the same exchange callback shape accepted by Options.Exchange.

func (*Source) ReauthenticateLease

func (s *Source) ReauthenticateLease(ctx context.Context, value any) (credentials.Lease, error)

ReauthenticateLease is the lease-returning form of Reauthenticate.

func (*Source) Reference

func (s *Source) Reference() credentials.Reference

Reference returns the exact configured identity.

type SourceOptions

type SourceOptions = Options

SourceOptions and Config are compatibility aliases for callers that name the constructor configuration after the source or module.

type State

type State struct {
	Schema       uint32
	Generation   credentials.Generation
	RefreshToken secrets.Secret
	ProviderData []byte
	// Continuity is an alias field for provider adapters that use that term;
	// when set it is encoded together with ProviderData.
	Continuity  []byte
	AccessToken secrets.Secret
	ExpiresAt   time.Time
	// Expiry is an alias for ExpiresAt.
	Expiry             time.Time
	PersistAccessToken bool
}

State is the provider continuity needed to perform one refresh exchange. AccessToken is a process-memory field and is omitted by EncodeState unless PersistAccessToken is explicitly set. ProviderData is copied at every boundary and is bounded by MaxProviderDataBytes.

func DecodeState

func DecodeState(value secrets.Secret) (State, error)

DecodeState validates a bounded opaque persisted state value. Unknown fields, duplicate fields, trailing JSON, and invalid base64 are rejected.

func NewState

func NewState(generation credentials.Generation, value any) (State, error)

func UnmarshalState

func UnmarshalState(value secrets.Secret) (State, error)

UnmarshalState is an alias kept for callers that prefer an explicit verb.

func (State) Clone

func (s State) Clone() (State, error)

Clone returns a detached state snapshot. Secret.Bytes itself returns a copy; ProviderData is copied explicitly because it is a mutable slice.

func (State) Format

func (s State) Format(state fmt.State, _ rune)

func (State) GoString

func (s State) GoString() string

func (State) LogValue

func (s State) LogValue() slog.Value

func (State) String

func (s State) String() string

func (State) Validate

func (s State) Validate() error

Validate checks schema, generation, and secret boundaries without exposing any secret or provider response in the returned error.

type Token

type Token = TokenResponse

type TokenResponse

type TokenResponse struct {
	AccessToken     secrets.Secret
	RefreshToken    secrets.Secret
	RefreshTokenSet bool
	Generation      credentials.Generation
	ExpiresAt       time.Time
	ExpiresIn       time.Duration
	// ExpiresInSeconds is accepted for providers whose wire response uses an
	// integer lifetime rather than a Go duration.
	ExpiresInSeconds   int64
	ProviderData       []byte
	Continuity         []byte
	PersistAccessToken bool
}

TokenResponse is the bounded result of one provider exchange. A missing RefreshToken means “retain the previous refresh token”; set RefreshTokenSet when a provider intentionally returns a replacement that is represented by a non-zero Secret. ExpiresIn is used only when ExpiresAt is zero.

func (TokenResponse) Format

func (r TokenResponse) Format(state fmt.State, _ rune)

func (TokenResponse) GoString

func (r TokenResponse) GoString() string

func (TokenResponse) LogValue

func (r TokenResponse) LogValue() slog.Value

func (TokenResponse) String

func (r TokenResponse) String() string

func (TokenResponse) Validate

func (r TokenResponse) Validate() error

Jump to

Keyboard shortcuts

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