Documentation
¶
Overview ¶
Package auth provides authentication handler interfaces and utilities for scafctl. Auth handlers manage identity verification, credential storage, and token acquisition. They are separate from providers - providers are stateless execution primitives, while auth handlers manage state (cached tokens, refresh tokens) across invocations.
Index ¶
- Constants
- Variables
- func ConfigActiveProfile(ctx context.Context, handlerName string) string
- func DeleteProfile(cfg *config.Config, handlerName, profile string) (bool, error)
- func DisplayProfileName(profile string) string
- func EnsureProfileRegistered(cfg *config.Config, handlerName, profile string)
- func FingerprintHash(identity string) string
- func GlobalProfileFromContext(ctx context.Context) string
- func HasCapability(capabilities []Capability, capability Capability) bool
- func HasHandler(ctx context.Context, name string) bool
- func IsAlreadyAuthenticated(err error) bool
- func IsAuthenticationFailed(err error) bool
- func IsCapabilityNotSupported(err error) bool
- func IsClaimsChallenge(err error) bool
- func IsConsentRequired(err error) bool
- func IsDisabled(h Handler) bool
- func IsFlowNotSupported(err error) bool
- func IsGrantInvalid(err error) bool
- func IsHandlerNotFound(err error) bool
- func IsInvalidScope(err error) bool
- func IsNotAuthenticated(err error) bool
- func IsProfileResolved(ctx context.Context) bool
- func IsTimeout(err error) bool
- func IsTokenExpired(err error) bool
- func IsUserCancelled(err error) bool
- func ListConfiguredProfiles(ctx context.Context, handlerName string) []string
- func ListHandlers(ctx context.Context) []string
- func NormalizeProfileName(name string) string
- func ParseProfileKey(key string) (handler, profile string)
- func ProfileFromContext(ctx context.Context) string
- func ProfileKey(handler, profile string) string
- func ResolveActiveProfile(ctx context.Context, handlerName string) string
- func ResolveEntraConfig(cfg *config.EntraAuthConfig, profile string) *config.EntraAuthConfig
- func ResolveGCPConfig(cfg *config.GCPAuthConfig, profile string) *config.GCPAuthConfig
- func ResolveGitHubConfig(cfg *config.GitHubAuthConfig, profile string) *config.GitHubAuthConfig
- func ValidateAuthProfiles(cfg *config.Config) error
- func ValidateProfileName(name string) error
- func WithGlobalProfile(ctx context.Context, profile string) context.Context
- func WithProfile(ctx context.Context, profile string) context.Context
- func WithProfileResolved(ctx context.Context) context.Context
- func WithRegistry(ctx context.Context, registry *Registry) context.Context
- type CacheEntry
- type CachedToken
- type CachedTokenInfo
- type Capability
- type Claims
- type ClaimsChallengeError
- type Configurer
- type CredentialDetector
- type Error
- type FallbackResolverFunc
- type Flow
- type FlowAvailability
- type FlowDetectionResult
- type FlowDetector
- type FlowReporter
- type GroupsProvider
- type Handler
- type HandlerMetadata
- type IdentityType
- type LoginOptions
- type MockConfigurerHandler
- type MockFlowDetectorHandler
- type MockHandler
- func (m *MockHandler) Capabilities() []Capability
- func (m *MockHandler) DisplayName() string
- func (m *MockHandler) GetToken(ctx context.Context, opts TokenOptions) (*Token, error)
- func (m *MockHandler) InjectAuth(ctx context.Context, req *http.Request, opts TokenOptions) error
- func (m *MockHandler) ListCachedTokens(ctx context.Context) ([]*CachedTokenInfo, error)
- func (m *MockHandler) Login(ctx context.Context, opts LoginOptions) (*Result, error)
- func (m *MockHandler) Logout(ctx context.Context) error
- func (m *MockHandler) Name() string
- func (m *MockHandler) PurgeExpiredTokens(ctx context.Context) (int, error)
- func (m *MockHandler) Reset()
- func (m *MockHandler) SetAuthenticated(claims *Claims)
- func (m *MockHandler) SetNotAuthenticated()
- func (m *MockHandler) SetToken(token *Token)
- func (m *MockHandler) SetTokenError(err error)
- func (m *MockHandler) Status(ctx context.Context) (*Status, error)
- func (m *MockHandler) SupportedFlows() []Flow
- type PreLoginAction
- type PreLoginResult
- type Registry
- func (r *Registry) All() map[string]Handler
- func (r *Registry) Count() int
- func (r *Registry) Disable(name, reason string) error
- func (r *Registry) Get(name string) (Handler, error)
- func (r *Registry) GetContext(ctx context.Context, name string) (Handler, error)
- func (r *Registry) GetRegistered(name string) (Handler, bool)
- func (r *Registry) Has(name string) bool
- func (r *Registry) List() []string
- func (r *Registry) Register(handler Handler) error
- func (r *Registry) SetFallbackResolver(fn FallbackResolverFunc)
- func (r *Registry) Unregister(name string) error
- type RegistryOption
- type Result
- type ServerMode
- type Status
- type Token
- type TokenAcquireFunc
- type TokenCache
- func (c *TokenCache) CacheKey(flow Flow, fingerprint, scope string) string
- func (c *TokenCache) Clear(ctx context.Context) error
- func (c *TokenCache) Delete(ctx context.Context, flow Flow, fingerprint, scope string) error
- func (c *TokenCache) Get(ctx context.Context, flow Flow, fingerprint, scope string) (*Token, error)
- func (c *TokenCache) ListCachedEntries(ctx context.Context) ([]CacheEntry, error)
- func (c *TokenCache) ParseKey(key string) (Flow, string, string, bool)
- func (c *TokenCache) Prefix() string
- func (c *TokenCache) PurgeExpired(ctx context.Context) (int, error)
- func (c *TokenCache) Set(ctx context.Context, flow Flow, fingerprint, scope string, token *Token) error
- type TokenCacheAccessor
- type TokenLister
- type TokenOptions
- type TokenPurger
Constants ¶
const ( CapScopesOnLogin = sdkauth.CapScopesOnLogin CapScopesOnTokenRequest = sdkauth.CapScopesOnTokenRequest CapTenantID = sdkauth.CapTenantID CapHostname = sdkauth.CapHostname CapTokenHostname = sdkauth.CapTokenHostname CapInstanceHostname = sdkauth.CapInstanceHostname CapFederatedToken = sdkauth.CapFederatedToken CapCallbackPort = sdkauth.CapCallbackPort CapFlowOverride = sdkauth.CapFlowOverride )
const ( MinCallbackPort = 1024 MaxCallbackPort = 65535 )
Callback port bounds for the interactive OAuth loopback callback server. Zero means "unset" (ephemeral/OS-assigned); any non-zero value must be an unprivileged, in-range TCP port within [MinCallbackPort, MaxCallbackPort]. These are the single source of truth shared by CLI flag validation and the host->plugin wire clamp so the two layers cannot drift.
const ( // EnvAzureFederatedToken is the raw federated token (for testing/debugging). // Takes precedence over EnvAzureFederatedTokenFile if both are set. EnvAzureFederatedToken = "AZURE_FEDERATED_TOKEN" //nolint:gosec // This is the env var name, not a credential // EnvAzureFederatedTokenFile is the path to the projected service account token. EnvAzureFederatedTokenFile = "AZURE_FEDERATED_TOKEN_FILE" //nolint:gosec // This is the env var name, not a credential )
Environment variable constants used by auth handlers. These are defined here so that CLI commands can reference them without importing handler-specific packages (e.g., pkg/auth/entra).
const ( FlowDeviceCode = sdkauth.FlowDeviceCode FlowInteractive = sdkauth.FlowInteractive FlowServicePrincipal = sdkauth.FlowServicePrincipal FlowWorkloadIdentity = sdkauth.FlowWorkloadIdentity FlowPAT = sdkauth.FlowPAT FlowMetadata = sdkauth.FlowMetadata FlowGcloudADC = sdkauth.FlowGcloudADC FlowGitHubApp = sdkauth.FlowGitHubApp FlowClientCredentials = sdkauth.FlowClientCredentials FlowOnBehalfOf = sdkauth.FlowOnBehalfOf )
const ( IdentityTypeUser = sdkauth.IdentityTypeUser IdentityTypeServicePrincipal = sdkauth.IdentityTypeServicePrincipal IdentityTypeWorkloadIdentity = sdkauth.IdentityTypeWorkloadIdentity )
const ( Delegate = sdkauth.ServerContextDelegated Server = sdkauth.ServerContextServer )
const ( // ProfileSeparator is the character used to separate handler name from profile name. ProfileSeparator = "@" // MaxProfileNameLength is the maximum allowed length for a profile name. MaxProfileNameLength = 64 // BuiltinProfileName is the display name for the unnamed built-in profile. // Internally the built-in profile is stored as "" (empty string), but this // constant is used for display and as an accepted alias in --profile flags. BuiltinProfileName = "built-in" // DefaultProfileName is kept for backward compatibility. Input of "default" // is still accepted and normalized to the unnamed built-in profile. DefaultProfileName = "default" )
const CachedTokenVersion = 1
CachedTokenVersion is the current serialization format version for cached tokens. Increment when making breaking changes to the CachedToken schema.
const DefaultMinValidFor = sdkauth.DefaultMinValidFor
DefaultMinValidFor is the default minimum validity duration for tokens.
Variables ¶
var ( ErrNotAuthenticated = errors.New("not authenticated") ErrAuthenticationFailed = errors.New("authentication failed") ErrTokenExpired = errors.New("credentials expired") ErrConsentRequired = errors.New("consent required: please login with the required scope") ErrInvalidScope = errors.New("invalid scope: scope cannot be empty") ErrHandlerNotFound = errors.New("auth handler not found") ErrFlowNotSupported = errors.New("authentication flow not supported") ErrUserCancelled = errors.New("authentication cancelled by user") ErrTimeout = errors.New("authentication timed out") ErrAlreadyAuthenticated = errors.New("already authenticated") ErrGrantInvalid = errors.New("invalid grant: the refresh token is invalid or has been revoked") ErrCapabilityNotSupported = errors.New("capability not supported by this auth handler") ErrClaimsChallenge = errors.New("claims challenge: re-authentication required by Conditional Access policy") )
Sentinel errors for the auth package.
var ( // ErrNilHandler indicates a nil handler was passed to Register. ErrNilHandler = errors.New("cannot register nil handler") // ErrEmptyHandlerName indicates a handler with an empty name was passed to Register. ErrEmptyHandlerName = errors.New("handler name cannot be empty") // ErrHandlerAlreadyRegistered indicates a handler with the same name is already registered. ErrHandlerAlreadyRegistered = errors.New("auth handler already registered") )
Sentinel errors for the registry.
var ErrHandlerDisabled = errors.New("auth handler disabled")
ErrHandlerDisabled is returned by disabled auth handlers when any operation is attempted. Use errors.Is to detect this condition.
var ErrOpaqueToken = fmt.Errorf("token is not a decodable JWT")
ErrOpaqueToken is returned when a token is not a decodable JWT (e.g., encrypted or opaque).
Functions ¶
func ConfigActiveProfile ¶ added in v0.17.0
ConfigActiveProfile returns the active profile for a handler from the config file only, ignoring context and flags. Use this for display purposes (e.g. marking which profile is active in status output).
func DeleteProfile ¶ added in v0.17.0
DeleteProfile removes a named profile from the in-memory config. If the handler's ActiveProfile points to the deleted profile, it is reset to the unnamed built-in profile. Returns true if the profile existed and was removed.
func DisplayProfileName ¶ added in v0.17.0
DisplayProfileName returns the display name for a profile. The unnamed built-in profile ("") is shown as "built-in".
func EnsureProfileRegistered ¶ added in v0.17.0
EnsureProfileRegistered adds a named profile entry to the in-memory config if it doesn't already exist. This makes the profile discoverable by ListConfiguredProfiles and auth switch without requiring manual config edits. Does nothing for the default (empty) profile.
func FingerprintHash ¶ added in v0.6.0
FingerprintHash computes a short, deterministic hash from an identity string for use as a cache-key segment. It prevents cross-config cache collisions by partitioning cache entries per unique configuration identity (e.g., clientID+tenantID).
Returns "_" for an empty identity, indicating that no config-specific partitioning is required (e.g., the metadata-server flow where the identity is implicit).
func GlobalProfileFromContext ¶ added in v0.17.0
GlobalProfileFromContext retrieves the global auth profile from the context. Returns "" if no global profile is set.
func HasCapability ¶ added in v0.5.0
func HasCapability(capabilities []Capability, capability Capability) bool
HasCapability checks if a set of capabilities includes the specified capability.
func HasHandler ¶
HasHandler checks if an auth handler exists in the context's registry. The name can include a profile suffix using "handler@profile" syntax.
func IsAlreadyAuthenticated ¶ added in v0.6.0
IsAlreadyAuthenticated returns true if the error indicates the user is already authenticated.
func IsAuthenticationFailed ¶ added in v0.6.0
IsAuthenticationFailed returns true if the error indicates authentication failed.
func IsCapabilityNotSupported ¶ added in v0.5.0
IsCapabilityNotSupported returns true if the error indicates a capability is not supported.
func IsClaimsChallenge ¶ added in v0.9.0
IsClaimsChallenge returns true if the error indicates a claims challenge is required.
func IsConsentRequired ¶ added in v0.4.0
IsConsentRequired returns true if the error indicates consent is required for the requested scope.
func IsDisabled ¶ added in v0.33.0
IsDisabled reports whether the given handler is a disabled wrapper.
func IsFlowNotSupported ¶ added in v0.6.0
IsFlowNotSupported returns true if the error indicates the flow is not supported.
func IsGrantInvalid ¶ added in v0.6.0
IsGrantInvalid returns true if the error indicates the grant (refresh token) is invalid or revoked.
func IsHandlerNotFound ¶
IsHandlerNotFound returns true if the error indicates the handler was not found.
func IsInvalidScope ¶ added in v0.6.0
IsInvalidScope returns true if the error indicates the scope is invalid.
func IsNotAuthenticated ¶
IsNotAuthenticated returns true if the error indicates the user is not authenticated.
func IsProfileResolved ¶ added in v0.17.0
IsProfileResolved returns true if profile resolution has already been performed for this context. When true, GetToken skips its automatic profile fallback.
func IsTokenExpired ¶
IsTokenExpired returns true if the error indicates the token has expired.
func IsUserCancelled ¶
IsUserCancelled returns true if the error indicates the user cancelled.
func ListConfiguredProfiles ¶ added in v0.17.0
ListConfiguredProfiles returns the profile names configured for a handler.
func ListHandlers ¶
ListHandlers lists all auth handlers in the context's registry.
func NormalizeProfileName ¶ added in v0.17.0
NormalizeProfileName maps the reserved names "built-in" and "default" to the internal empty string representation. All other names are returned as-is.
func ParseProfileKey ¶ added in v0.17.0
ParseProfileKey splits "handler@profile" into (handler, profile). Returns (key, "") for bare handler names without a profile separator. The profile name is normalized: "handler@built-in" and "handler@default" both return ("handler", "").
func ProfileFromContext ¶ added in v0.17.0
ProfileFromContext retrieves the auth profile from the context. Returns "" if no profile is set.
func ProfileKey ¶ added in v0.17.0
ProfileKey joins handler and profile into "handler@profile". Returns bare handler name when profile is empty.
func ResolveActiveProfile ¶ added in v0.17.0
ResolveActiveProfile determines which profile should be active for a handler given the current context and configuration. Precedence (highest first):
- Profile from context (set by solution YAML or --profile flag)
- Profile from --auth-profile global flag / SCAFCTL_AUTH_PROFILE env var
- ActiveProfile from handler config
- Empty string (default profile)
func ResolveEntraConfig ¶ added in v0.17.0
func ResolveEntraConfig(cfg *config.EntraAuthConfig, profile string) *config.EntraAuthConfig
ResolveEntraConfig returns a copy of the Entra config with the active profile's fields merged on top. Non-empty profile fields override top-level values. If no profile is active or the profile doesn't exist, the top-level config is returned unchanged. The returned config has ActiveProfile/Profiles cleared since it represents the fully-resolved effective config.
func ResolveGCPConfig ¶ added in v0.17.0
func ResolveGCPConfig(cfg *config.GCPAuthConfig, profile string) *config.GCPAuthConfig
ResolveGCPConfig returns a copy of the GCP config with the active profile's fields merged on top. Non-empty profile fields override top-level values.
func ResolveGitHubConfig ¶ added in v0.17.0
func ResolveGitHubConfig(cfg *config.GitHubAuthConfig, profile string) *config.GitHubAuthConfig
ResolveGitHubConfig returns a copy of the GitHub config with the active profile's fields merged on top. Non-empty profile fields override top-level values.
func ValidateAuthProfiles ¶ added in v0.17.0
ValidateAuthProfiles validates all profile names in the auth configuration. Returns the first validation error encountered, or nil if all names are valid.
func ValidateProfileName ¶ added in v0.17.0
ValidateProfileName checks that a profile name is valid. Valid names are 1-64 characters, ASCII alphanumeric plus - and _, starting with an alphanumeric character.
func WithGlobalProfile ¶ added in v0.17.0
WithGlobalProfile returns a new context with the global auth profile set. This is used for the --auth-profile persistent flag / SCAFCTL_AUTH_PROFILE env var.
func WithProfile ¶ added in v0.17.0
WithProfile returns a new context with the given auth profile name.
func WithProfileResolved ¶ added in v0.17.0
WithProfileResolved marks the context as having completed profile resolution. This prevents GetToken from re-resolving the profile when a caller has already determined the correct profile (including explicitly choosing the built-in profile).
Types ¶
type CacheEntry ¶ added in v0.6.0
type CacheEntry struct {
Flow Flow `json:"flow" yaml:"flow" doc:"Authentication flow for this cache entry"`
Fingerprint string `json:"fingerprint" yaml:"fingerprint" doc:"Identity fingerprint for cache partitioning" maxLength:"128"`
Scope string `json:"scope" yaml:"scope" doc:"OAuth scope for this cache entry" maxLength:"1024"`
}
CacheEntry represents a unique cache slot identified by flow, fingerprint, and scope.
type CachedToken ¶ added in v0.6.0
type CachedToken struct {
Version int `json:"version" yaml:"version" doc:"Schema version of the cached token format" minimum:"0" maximum:"100" example:"1"`
AccessToken string `json:"accessToken" yaml:"accessToken" doc:"The cached access token" maxLength:"65536"` //nolint:gosec // G117: not a hardcoded credential, stores runtime token data
TokenType string `json:"tokenType" yaml:"tokenType" doc:"Token type, typically Bearer" example:"Bearer" maxLength:"64"`
ExpiresAt time.Time `json:"expiresAt" yaml:"expiresAt" doc:"Time the token expires"`
Scope string `json:"scope" yaml:"scope" doc:"OAuth scope the token was issued for" maxLength:"1024"`
Flow Flow `` /* 131-byte string literal not displayed */
Fingerprint string `json:"fingerprint,omitempty" yaml:"fingerprint,omitempty" doc:"Truncated SHA-256 hash of the config identity" maxLength:"128"`
CachedAt time.Time `json:"cachedAt" yaml:"cachedAt" doc:"Time the token was written to cache"`
SessionID string `json:"sessionId,omitempty" yaml:"sessionId,omitempty" doc:"Stable identifier of the authentication session" maxLength:"128"`
}
CachedToken is the structure stored on disk for each cached token.
type CachedTokenInfo ¶ added in v0.5.0
type CachedTokenInfo = sdkauth.CachedTokenInfo
CachedTokenInfo holds display metadata for a cached token.
type Capability ¶ added in v0.5.0
type Capability = sdkauth.Capability
Capability represents a feature or behavior that an auth handler supports.
type Claims ¶
Claims represents normalized identity claims from any auth handler.
func ParseJWTClaims ¶ added in v0.6.0
ParseJWTClaims decodes a JWT token string (without signature verification) and extracts normalized identity claims. This works for both ID tokens and access tokens that are standard three-part JWTs.
Returns ErrOpaqueToken if the token is not a decodable JWT (e.g., encrypted or opaque tokens issued by some providers for first-party resources).
type ClaimsChallengeError ¶ added in v0.9.0
type ClaimsChallengeError struct {
// Claims is the base64url-encoded claims challenge string from the token endpoint.
Claims string
// Scope is the scope that triggered the claims challenge.
Scope string
}
ClaimsChallengeError wraps ErrClaimsChallenge with the raw claims payload returned by the token endpoint so callers can pass it into a re-authentication request.
func (*ClaimsChallengeError) Error ¶ added in v0.9.0
func (e *ClaimsChallengeError) Error() string
Error implements the error interface.
func (*ClaimsChallengeError) Unwrap ¶ added in v0.9.0
func (e *ClaimsChallengeError) Unwrap() error
Unwrap returns the sentinel so errors.Is(err, ErrClaimsChallenge) works.
type Configurer ¶ added in v0.17.0
type Configurer interface {
// ApplyOverrides sends updated key-value settings to the handler.
// Keys use the handler's config field names (e.g., "clientId", "tenantId").
// Only non-empty values are applied; empty strings are ignored.
ApplyOverrides(ctx context.Context, overrides map[string]string) error
}
Configurer is an optional interface for auth handlers that accept runtime setting overrides. The auth login command uses this to apply --client-id and --tenant flags before initiating the login flow.
type CredentialDetector ¶ added in v0.6.0
type CredentialDetector struct {
// HasCredentials returns true if this credential type is available.
HasCredentials func() bool
// Flow is the auth flow to use when these credentials are detected.
Flow Flow
// Description is a human-readable message shown when this credential is detected.
Description string
}
CredentialDetector checks for available credentials in the environment.
type Error ¶
type Error struct {
Handler string `json:"handler" yaml:"handler" doc:"Name of the auth handler" example:"entra" maxLength:"64"`
Operation string `json:"operation" yaml:"operation" doc:"Operation that failed" example:"login" maxLength:"64"`
Cause error `json:"-" yaml:"-"`
}
Error wraps authentication errors with additional context.
type FallbackResolverFunc ¶ added in v0.16.0
FallbackResolverFunc is called by Get when a handler is not found in the registry. It receives the handler name and should return the resolved handler or an error. The resolver is invoked at most once per name — resolved handlers are automatically registered and subsequent Get calls return them directly without invoking the fallback again.
type Flow ¶
Flow represents an authentication flow type.
type FlowAvailability ¶ added in v0.15.0
type FlowAvailability = sdkplugin.FlowAvailability
FlowAvailability reports whether a specific auth flow is available based on environment credentials or configuration.
type FlowDetectionResult ¶ added in v0.6.0
type FlowDetectionResult struct {
// Flow is the selected authentication flow.
Flow Flow
// Description is a human-readable message about what was detected,
// or empty if the default flow was used.
Description string
}
FlowDetectionResult contains the auto-detected flow and a description.
func DetectFlow ¶ added in v0.6.0
func DetectFlow(explicitFlow Flow, detectors []CredentialDetector, defaultFlow Flow) FlowDetectionResult
DetectFlow determines the best authentication flow given an explicit preference, a prioritized list of credential detectors, and a default fallback flow.
Resolution order:
- If explicitFlow is non-empty, use it.
- Check detectors in order; use the first one with available credentials.
- Fall back to defaultFlow.
type FlowDetector ¶ added in v0.15.0
type FlowDetector interface {
// DetectAvailableFlows returns the availability of each supported auth flow
// based on the current environment (env vars, config files, metadata endpoints).
DetectAvailableFlows(ctx context.Context) ([]FlowAvailability, error)
}
FlowDetector is an optional interface for auth handlers that can report which flows have pre-existing environment credentials (e.g., PAT in GITHUB_TOKEN, workload identity in AZURE_FEDERATED_TOKEN_FILE). The CLI uses this for flow auto-selection without importing handler-specific packages.
Plugin auth handlers implement this via the SDK's DetectAvailableFlows RPC. Built-in handlers (like oauth2) may optionally implement this interface.
type FlowReporter ¶ added in v0.10.1
type FlowReporter interface {
// ActiveFlow returns the authentication flow currently in use.
// Returns an empty string if the flow cannot be determined.
ActiveFlow(ctx context.Context) Flow
}
FlowReporter is an optional interface for auth handlers that can report the credential source currently being used (e.g. device-code, gcloud-adc, workload-identity). The status command uses this to display the active flow.
type GroupsProvider ¶ added in v0.5.0
type GroupsProvider interface {
// GetGroups returns the ObjectIDs of all groups the authenticated user belongs to.
// Implementations must handle pagination transparently, so all memberships —
// including those beyond any per-token cap (e.g. the 200-group JWT limit for
// Microsoft Entra) — are returned.
GetGroups(ctx context.Context) ([]string, error)
}
GroupsProvider is an optional interface that auth handlers can implement to return the authenticated user's group memberships as a slice of ObjectIDs.
Handlers that do not implement this interface do not support group membership queries. Callers should type-assert to this interface before invoking GetGroups.
type Handler ¶
type Handler interface {
// Name returns the unique identifier for this auth handler.
Name() string
// DisplayName returns a human-readable name for display purposes.
DisplayName() string
// Login initiates the authentication flow.
// For interactive flows (like device code), this blocks until completion or timeout.
// Returns the authenticated identity claims on success.
Login(ctx context.Context, opts LoginOptions) (*Result, error)
// Logout clears stored credentials for this handler.
Logout(ctx context.Context) error
// Status returns the current authentication status.
// Returns a status with Authenticated=false if not logged in.
Status(ctx context.Context) (*Status, error)
// GetToken returns a valid access token for the specified options.
// Uses cached tokens when available and valid for the requested duration,
// otherwise refreshes from the identity provider.
// Returns ErrNotAuthenticated if user is not logged in.
// Returns ErrTokenExpired if refresh token has expired (re-login required).
GetToken(ctx context.Context, opts TokenOptions) (*Token, error)
// InjectAuth adds authentication to an HTTP request.
// This is the primary method used by providers (like HTTP) to authenticate requests.
// Automatically handles token acquisition/refresh as needed.
InjectAuth(ctx context.Context, req *http.Request, opts TokenOptions) error
// SupportedFlows returns the authentication flows this handler supports.
SupportedFlows() []Flow
// Capabilities returns the set of capabilities this handler supports.
// Commands use capabilities to dynamically determine which flags and
// validation rules apply for a given handler.
Capabilities() []Capability
}
Handler defines the interface for authentication handlers. Auth handlers manage identity verification, credential storage, and token acquisition. This interface is host-only and not part of the SDK because it references net/http.
func GetHandler ¶
GetHandler gets an auth handler from the context's registry. The name can include a profile suffix using "handler@profile" syntax. The profile portion is stripped for registry lookup; use ParseProfileKey to extract the profile for passing via context to handler methods.
type HandlerMetadata ¶ added in v0.28.0
type HandlerMetadata = sdkauth.HandlerMetadata
HandlerMetadata is the canonical persisted metadata for an auth session, shared by core and all plugin auth handlers.
type IdentityType ¶
type IdentityType = sdkauth.IdentityType
IdentityType represents the type of authenticated identity.
type LoginOptions ¶
type LoginOptions = sdkauth.LoginOptions
LoginOptions configures the login process.
type MockConfigurerHandler ¶ added in v0.17.0
type MockConfigurerHandler struct {
*MockHandler
ApplyOverridesErr error
ApplyOverridesCalls []map[string]string
}
MockConfigurerHandler embeds MockHandler and adds Configurer support.
func NewMockConfigurerHandler ¶ added in v0.17.0
func NewMockConfigurerHandler(name string) *MockConfigurerHandler
NewMockConfigurerHandler creates a mock handler that implements Configurer.
func (*MockConfigurerHandler) ApplyOverrides ¶ added in v0.17.0
func (m *MockConfigurerHandler) ApplyOverrides(_ context.Context, overrides map[string]string) error
ApplyOverrides implements Configurer.
type MockFlowDetectorHandler ¶ added in v0.15.0
type MockFlowDetectorHandler struct {
*MockHandler
DetectFlowsResult []FlowAvailability
DetectFlowsErr error
}
MockFlowDetectorHandler embeds MockHandler and adds FlowDetector support.
func NewMockFlowDetectorHandler ¶ added in v0.15.0
func NewMockFlowDetectorHandler(name string) *MockFlowDetectorHandler
NewMockFlowDetectorHandler creates a mock handler that implements FlowDetector.
func (*MockFlowDetectorHandler) DetectAvailableFlows ¶ added in v0.15.0
func (m *MockFlowDetectorHandler) DetectAvailableFlows(_ context.Context) ([]FlowAvailability, error)
DetectAvailableFlows implements FlowDetector.
type MockHandler ¶
type MockHandler struct {
NameValue string
DisplayNameValue string
FlowsValue []Flow
CapabilitiesValue []Capability
LoginResult *Result
LoginErr error
LogoutErr error
StatusResult *Status
StatusErr error
GetTokenResult *Token
GetTokenErr error
InjectAuthErr error
ListCachedTokensResult []*CachedTokenInfo
ListCachedTokensErr error
PurgeExpiredResult int
PurgeExpiredErr error
LoginCalls []LoginOptions
LogoutCalls int
StatusCalls int
GetTokenCalls []TokenOptions
InjectAuthCalls []TokenOptions
PurgeExpiredCalls int
// LastContextProfile captures the profile from context on the most recent call.
// This enables tests to verify that profile propagation reaches the handler.
LastContextProfile string
// contains filtered or unexported fields
}
MockHandler implements Handler for testing.
func NewMockHandler ¶
func NewMockHandler(name string) *MockHandler
NewMockHandler creates a new mock auth handler with default values.
func (*MockHandler) Capabilities ¶ added in v0.5.0
func (m *MockHandler) Capabilities() []Capability
func (*MockHandler) DisplayName ¶
func (m *MockHandler) DisplayName() string
func (*MockHandler) GetToken ¶
func (m *MockHandler) GetToken(ctx context.Context, opts TokenOptions) (*Token, error)
func (*MockHandler) InjectAuth ¶
func (m *MockHandler) InjectAuth(ctx context.Context, req *http.Request, opts TokenOptions) error
func (*MockHandler) ListCachedTokens ¶ added in v0.5.0
func (m *MockHandler) ListCachedTokens(ctx context.Context) ([]*CachedTokenInfo, error)
func (*MockHandler) Login ¶
func (m *MockHandler) Login(ctx context.Context, opts LoginOptions) (*Result, error)
func (*MockHandler) Name ¶
func (m *MockHandler) Name() string
func (*MockHandler) PurgeExpiredTokens ¶ added in v0.5.0
func (m *MockHandler) PurgeExpiredTokens(ctx context.Context) (int, error)
func (*MockHandler) Reset ¶
func (m *MockHandler) Reset()
func (*MockHandler) SetAuthenticated ¶
func (m *MockHandler) SetAuthenticated(claims *Claims)
func (*MockHandler) SetNotAuthenticated ¶
func (m *MockHandler) SetNotAuthenticated()
func (*MockHandler) SetToken ¶
func (m *MockHandler) SetToken(token *Token)
func (*MockHandler) SetTokenError ¶
func (m *MockHandler) SetTokenError(err error)
func (*MockHandler) SupportedFlows ¶
func (m *MockHandler) SupportedFlows() []Flow
type PreLoginAction ¶ added in v0.6.0
type PreLoginAction int
PreLoginAction describes what the caller should do after a pre-login check.
const ( // PreLoginProceed means the login should proceed normally. PreLoginProceed PreLoginAction = iota // PreLoginSkip means the user is already authenticated and login should be skipped. PreLoginSkip // PreLoginAlreadyAuthenticated means the user is already authenticated but login was not skipped. PreLoginAlreadyAuthenticated )
type PreLoginResult ¶ added in v0.6.0
type PreLoginResult struct {
// Action indicates what the caller should do.
Action PreLoginAction
// Identity is the display name of the authenticated identity (if any).
Identity string
}
PreLoginResult contains the result of a pre-login check.
func PreLoginCheck ¶ added in v0.6.0
func PreLoginCheck(ctx context.Context, handler Handler, flow Flow, force, skipIfAuthenticated bool, hostname string, skipCheckFlows ...Flow) (*PreLoginResult, error)
PreLoginCheck checks whether a handler is already authenticated and determines the appropriate action. If force is true, the handler is logged out first and PreLoginProceed is returned. If the flow is in skipCheckFlows, no check is performed.
Parameters:
- handler: the auth handler to check
- flow: the selected auth flow
- force: if true, force logout and proceed
- skipIfAuthenticated: if true and already authenticated, return PreLoginSkip
- hostname: the explicitly requested host (empty if none). For host-aware handlers, a non-empty hostname bypasses the already-authenticated check so the user can log in to a different host without --force.
- skipCheckFlows: flows for which no auth-status check is needed (e.g., FlowPAT)
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry manages registered auth handlers.
func NewRegistry ¶
func NewRegistry(opts ...RegistryOption) *Registry
NewRegistry creates a new auth handler registry.
func RegistryFromContext ¶
RegistryFromContext retrieves the auth registry from the context.
func (*Registry) Disable ¶ added in v0.33.0
Disable replaces the named handler with a disabled wrapper that rejects all token operations. The handler remains visible in List/Has/All but GetToken/InjectAuth/Login return ErrHandlerDisabled. If the handler is already disabled, the reason is updated without double-wrapping.
func (*Registry) Get ¶
Get retrieves an auth handler by name. If the handler is not found and a fallback resolver is configured, it invokes the resolver to lazily fetch the handler (e.g., by downloading and starting a plugin). Resolved handlers are automatically registered for subsequent lookups.
Get uses context.Background() for the fallback resolver. Use GetContext to propagate caller cancellation into the fallback.
func (*Registry) GetContext ¶ added in v0.16.0
GetContext retrieves an auth handler by name, propagating the given context into the fallback resolver. This allows callers to cancel long-running fallback operations (e.g., plugin downloads) via context cancellation.
func (*Registry) GetRegistered ¶ added in v0.16.0
GetRegistered retrieves a handler by name from the registry without invoking the fallback resolver. Returns the handler and true if found, or nil and false if not registered.
func (*Registry) SetFallbackResolver ¶ added in v0.16.0
func (r *Registry) SetFallbackResolver(fn FallbackResolverFunc)
SetFallbackResolver sets or replaces the fallback resolver. This is safe to call after construction (e.g., from PersistentPreRun after the registry is already stored in context).
func (*Registry) Unregister ¶
Unregister removes an auth handler from the registry.
type RegistryOption ¶ added in v0.16.0
type RegistryOption func(*Registry)
RegistryOption configures a Registry during construction.
func WithFallbackResolver ¶ added in v0.16.0
func WithFallbackResolver(fn FallbackResolverFunc) RegistryOption
WithFallbackResolver sets a lazy fallback resolver that is called when Get cannot find a handler in the registry. This enables demand-driven plugin resolution — only handlers that are actually requested trigger network I/O or subprocess startup.
type ServerMode ¶ added in v0.33.0
type ServerMode = sdkplugin.ServerMode
type Token ¶
Token represents a short-lived access token.
func GetCachedOrAcquireToken ¶ added in v0.6.0
func GetCachedOrAcquireToken[T any]( ctx context.Context, cache *TokenCache, opts TokenOptions, flow Flow, cacheKey string, getCreds func() (T, error), isCredsNil func(T) bool, getFingerprint func(T) string, acquireToken TokenAcquireFunc[T], logPrefix string, ) (*Token, error)
GetCachedOrAcquireToken is a generic helper that handles the common pattern of: 1. Retrieving credentials 2. Checking the cache (unless ForceRefresh) 3. Acquiring a new token if needed 4. Caching the new token
Parameters:
- ctx: context for cancellation and logging
- cache: the token cache to read/write from
- opts: token acquisition options (scope, min validity, force refresh flags)
- flow: the authentication flow type for cache partitioning
- cacheKey: the cache lookup key (typically opts.Scope; GitHub uses a fixed key)
- getCreds: retrieves credentials; returns (T, error) — return a nil error if the credential source doesn't produce errors
- isCredsNil: returns true when the credential value indicates "not configured"
- getFingerprint: computes a cache-partitioning fingerprint from the credentials
- acquireToken: mints a fresh token using the credentials and scope
- logPrefix: short label for log messages (e.g. "SP", "WI", "pat")
type TokenAcquireFunc ¶ added in v0.6.0
TokenAcquireFunc is a function that acquires a token given credentials and a scope (or cache key).
type TokenCache ¶ added in v0.6.0
type TokenCache struct {
// contains filtered or unexported fields
}
TokenCache provides disk-based caching for access tokens via pkg/secrets. Tokens are stored encrypted and survive process restarts. Each (flow, fingerprint, scope) tuple has its own secret key for atomic updates and fault isolation. The fingerprint prevents cross-config cache contamination when users switch between different authentication configurations (e.g., different tenant IDs, client IDs, WIF audiences).
TokenCache is shared by all auth handlers (entra, gcp, github). Each handler provides its own key prefix at construction time to namespace its entries.
func NewTokenCache ¶ added in v0.6.0
func NewTokenCache(secretStore secrets.Store, prefix string) *TokenCache
NewTokenCache creates a new disk-based token cache. The prefix parameter namespaces cache entries per handler (e.g., "scafctl.auth.entra.token.").
func (*TokenCache) CacheKey ¶ added in v0.6.0
func (c *TokenCache) CacheKey(flow Flow, fingerprint, scope string) string
CacheKey builds the secret store key for a given flow, fingerprint, and scope. Format: <prefix><flow>.<fingerprint>.<base64url(scope)>
func (*TokenCache) Clear ¶ added in v0.6.0
func (c *TokenCache) Clear(ctx context.Context) error
Clear removes all cached tokens by listing secrets with the handler's token prefix and deleting them.
func (*TokenCache) Delete ¶ added in v0.6.0
Delete removes a cached token for the given flow, fingerprint, and scope.
func (*TokenCache) Get ¶ added in v0.6.0
Get retrieves a token for the given flow, fingerprint, and scope from disk cache. Returns nil, nil if no token is cached for this combination. Returns nil, error if there was an error reading the cache.
func (*TokenCache) ListCachedEntries ¶ added in v0.6.0
func (c *TokenCache) ListCachedEntries(ctx context.Context) ([]CacheEntry, error)
ListCachedEntries returns all cached (flow, fingerprint, scope) entries.
func (*TokenCache) ParseKey ¶ added in v0.6.0
ParseKey extracts the flow, fingerprint, and scope from a secret key. Returns false if the key is not a valid token cache key for this cache's prefix.
func (*TokenCache) Prefix ¶ added in v0.6.0
func (c *TokenCache) Prefix() string
Prefix returns the secret key prefix used by this TokenCache.
func (*TokenCache) PurgeExpired ¶ added in v0.6.0
func (c *TokenCache) PurgeExpired(ctx context.Context) (int, error)
PurgeExpired removes all expired access tokens from the cache. Returns the number of tokens removed.
type TokenCacheAccessor ¶ added in v0.6.0
type TokenCacheAccessor interface {
GetTokenCache() *TokenCache
}
TokenCacheAccessor provides access to the token cache. All three handler packages (entra, gcp, github) satisfy this via their Handler structs.
type TokenLister ¶ added in v0.5.0
type TokenLister = sdkauth.TokenLister
TokenLister is an optional interface for auth handlers that can enumerate cached tokens.
type TokenOptions ¶
type TokenOptions = sdkauth.TokenOptions
TokenOptions configures token acquisition.
type TokenPurger ¶ added in v0.5.0
type TokenPurger = sdkauth.TokenPurger
TokenPurger is an optional interface for auth handlers that can remove expired tokens.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package diagnose provides reusable auth diagnostic checks.
|
Package diagnose provides reusable auth diagnostic checks. |
|
Package execcredential builds Kubernetes client-go ExecCredential payloads from scafctl auth tokens.
|
Package execcredential builds Kubernetes client-go ExecCredential payloads from scafctl auth tokens. |
|
Package handlerdep decides how an auth handler name maps to a plugin dependency for catalog resolution.
|
Package handlerdep decides how an auth handler name maps to a plugin dependency for catalog resolution. |
|
Package hostname resolves a user-supplied hostname selector (e.g.
|
Package hostname resolves a user-supplied hostname selector (e.g. |
|
Package loginui renders the interactive login experience shared by the 'auth login' and 'kube login' commands.
|
Package loginui renders the interactive login experience shared by the 'auth login' and 'kube login' commands. |
|
Package migrate provides domain logic for migrating built-in auth handlers to plugin-based handlers.
|
Package migrate provides domain logic for migrating built-in auth handlers to plugin-based handlers. |
|
Package oauth2 implements a generic configurable OAuth2 auth handler.
|
Package oauth2 implements a generic configurable OAuth2 auth handler. |
|
Package official defines the manifest of first-party auth handlers that scafctl distributes as standalone gRPC plugins (published to ghcr.io/oakwood-commons/auth-handlers/<name>), NOT compiled into the binary.
|
Package official defines the manifest of first-party auth handlers that scafctl distributes as standalone gRPC plugins (published to ghcr.io/oakwood-commons/auth-handlers/<name>), NOT compiled into the binary. |
|
Package statusrows contains the domain logic for expanding an auth handler's status into per-cluster (per-instance) sessions.
|
Package statusrows contains the domain logic for expanding an auth handler's status into per-cluster (per-instance) sessions. |