Documentation
¶
Index ¶
- Constants
- Variables
- func CleanAllExpiredTokens() (int, error)
- func CleanExpiredTokens(serverURL string) (int, error)
- func DeleteExchangedToken(serverURL string, req *exchange.ExchangeRequest) error
- func DeleteIdentity(serverURL string) error
- func DeleteSession(serverURL string) error
- func GetConfigDir() (string, error)
- func GetDefaultIdentityPath() (string, error)
- func GetSessionDir(serverURL string) (string, error)
- func GetSessionIdentityPath(serverURL string) (string, error)
- func GetToken(ctx context.Context, audience ...string) (string, error)
- func GetTokenForServer(ctx context.Context, serverURL string, audience ...string) (string, error)
- func GetTokenForServerWithOptions(ctx context.Context, serverURL string, req *exchange.ExchangeRequest) (string, error)
- func GetTokenWithOptions(ctx context.Context, req *exchange.ExchangeRequest) (string, error)
- func GetTokensDir(serverURL string) (string, error)
- func HashExchangeRequest(req *exchange.ExchangeRequest) string
- func ListSessions() (map[string]*SessionInfo, string, error)
- func LoadDefaultIdentity() (string, time.Time, error)
- func LoadExchangedToken(serverURL string, req *exchange.ExchangeRequest) (string, time.Time, error)
- func LoadExchangedTokenWithRenewal(ctx context.Context, serverURL string, req *exchange.ExchangeRequest) (string, time.Time, bool, error)
- func LoadIdentity(serverURL string) (string, time.Time, error)
- func LoadIdentityWithRenewal(ctx context.Context, serverURL string) (string, time.Time, bool, error)
- func ResolveExchangeServer(override string) string
- func SaveExchangedToken(serverURL string, req *exchange.ExchangeRequest, token string, ...) error
- func SaveIdentity(serverURL, token string) error
- func SetDefaultSession(serverURL string) error
- type CachedToken
- type ChainedTokenSource
- type EnvTokenSource
- type FileTokenSource
- type Manager
- type Option
- type ServerOptions
- func (o *ServerOptions) AddFlags(cmd *cobra.Command)
- func (o *ServerOptions) Config() *command.OptionsSetConfig
- func (o *ServerOptions) Manager(ctx context.Context) (*Manager, error)
- func (o *ServerOptions) TokenSource(ctx context.Context, audience ...string) (TokenSource, error)
- func (o *ServerOptions) TokenSourceWithRequest(ctx context.Context, req *exchange.ExchangeRequest) (TokenSource, error)
- func (o *ServerOptions) Validate() error
- type ServerOptionsOption
- type ServiceTokenSource
- type ServiceTokenSourceOption
- type SessionInfo
- type SessionsConfig
- type StaticTokenSource
- type TokenSource
Constants ¶
const ( // DefaultCredentialsEnvVar is the environment variable checked for credentials. DefaultCredentialsEnvVar = "CARABINER_CREDENTIALS" // DefaultCredentialsFile is the filename for the default credentials file. DefaultCredentialsFile = "identity.json" // DefaultConfigDir is the subdirectory under os.UserConfigDir for carabiner config. DefaultConfigDir = "carabiner" // DefaultExchangeServer is the default deadrop exchange server URL. DefaultExchangeServer = "https://auth.carabiner.dev" )
const DefaultLoginURL = "https://login.carabiner.dev"
DefaultLoginURL is the default login URL for the Carabiner login service.
const DefaultServer = "https://auth.carabiner.dev"
DefaultServer is the default deadrop exchange server URL.
const RenewalThreshold = 10 * time.Minute
RenewalThreshold is the time before expiry when a token should be renewed. If a token expires within this duration, it will be automatically renewed.
Variables ¶
var ErrTokenExpired = fmt.Errorf("token is expired and cannot be renewed, please log in again")
ErrTokenExpired is returned when the token is expired and cannot be renewed.
Functions ¶
func CleanAllExpiredTokens ¶
CleanAllExpiredTokens removes expired tokens from all server sessions. Returns the total number of tokens removed.
func CleanExpiredTokens ¶
CleanExpiredTokens removes all expired tokens from a server's token cache. Returns the number of tokens removed.
func DeleteExchangedToken ¶
func DeleteExchangedToken(serverURL string, req *exchange.ExchangeRequest) error
DeleteExchangedToken removes a specific cached token.
func DeleteIdentity ¶
DeleteIdentity removes the identity file for a specific server.
func DeleteSession ¶
DeleteSession removes the entire session for a server, including its directory.
func GetConfigDir ¶
GetConfigDir returns the carabiner config directory path
func GetDefaultIdentityPath ¶
GetDefaultIdentityPath returns the path to the default session's identity file
func GetSessionDir ¶
GetSessionDir returns the directory path for a server's session
func GetSessionIdentityPath ¶
GetSessionIdentityPath returns the path to the identity file for a server's session
func GetToken ¶
GetToken is a convenience function for apps to get a token for a specific audience. It uses the default session's server and automatically handles caching and renewal.
Example usage:
token, err := credentials.GetToken(ctx, "https://api.example.com")
if err != nil {
log.Fatal(err)
}
// Use token...
func GetTokenForServer ¶
GetTokenForServer is like GetToken but allows specifying a specific server.
func GetTokenForServerWithOptions ¶
func GetTokenForServerWithOptions(ctx context.Context, serverURL string, req *exchange.ExchangeRequest) (string, error)
GetTokenForServerWithOptions is like GetTokenWithOptions but allows specifying a specific server.
func GetTokenWithOptions ¶
GetTokenWithOptions is like GetToken but allows specifying full exchange options.
Example usage:
token, err := credentials.GetTokenWithOptions(ctx, &exchange.ExchangeRequest{
Audience: []string{"https://api.example.com"},
Scope: []string{"read", "write"},
})
func GetTokensDir ¶
GetTokensDir returns the tokens directory path for a server's session.
func HashExchangeRequest ¶
func HashExchangeRequest(req *exchange.ExchangeRequest) string
HashExchangeRequest generates a deterministic hash for an exchange request. This is used to create unique filenames for cached tokens. Only the Audience, Scope, and Resource fields are hashed.
func ListSessions ¶
func ListSessions() (map[string]*SessionInfo, string, error)
ListSessions returns all configured sessions
func LoadDefaultIdentity ¶
LoadDefaultIdentity loads the identity token from the default session.
func LoadExchangedToken ¶
LoadExchangedToken loads a cached exchanged token for a specific server and request. Returns the token and its expiry time if found and not expired.
func LoadExchangedTokenWithRenewal ¶
func LoadExchangedTokenWithRenewal(ctx context.Context, serverURL string, req *exchange.ExchangeRequest) (string, time.Time, bool, error)
LoadExchangedTokenWithRenewal loads a cached exchanged token, automatically re-exchanging it if it's about to expire (within RenewalThreshold). Returns the token, expiry time, whether renewal was performed, and any error. This function opportunistically cleans up expired tokens with ~10% probability.
func LoadIdentity ¶
LoadIdentity loads the identity token for a specific server. Returns the token and its expiry time if valid. This function does NOT perform auto-renewal. Use LoadIdentityWithRenewal for that.
func LoadIdentityWithRenewal ¶
func LoadIdentityWithRenewal(ctx context.Context, serverURL string) (string, time.Time, bool, error)
LoadIdentityWithRenewal loads the identity token for a specific server, automatically renewing it if it's about to expire (within RenewalThreshold). Returns the token, expiry time, and whether renewal was performed.
func ResolveExchangeServer ¶
ResolveExchangeServer returns the exchange server URL to use. If override is non-empty it is returned directly. Otherwise the server URL from the default session is used. If no session exists, DefaultExchangeServer is returned.
func SaveExchangedToken ¶
func SaveExchangedToken(serverURL string, req *exchange.ExchangeRequest, token string, expiresAt time.Time) error
SaveExchangedToken saves an exchanged token to the server's token cache.
func SaveIdentity ¶
SaveIdentity saves the identity token to the session-specific identity file for a server. This creates the session if it doesn't exist.
func SetDefaultSession ¶
SetDefaultSession sets the default session to the specified server
Types ¶
type CachedToken ¶
type CachedToken struct {
Token string `json:"token"`
ExpiresAt time.Time `json:"expires_at"`
Spec *exchange.ExchangeRequest `json:"spec"`
}
CachedToken represents an exchanged token stored on disk.
type ChainedTokenSource ¶
type ChainedTokenSource struct {
// contains filtered or unexported fields
}
ChainedTokenSource tries multiple TokenSources in order until one succeeds.
func NewChainedTokenSource ¶
func NewChainedTokenSource(sources ...TokenSource) *ChainedTokenSource
NewChainedTokenSource creates a TokenSource that tries each source in order. The first source that returns a valid token is used.
type EnvTokenSource ¶
type EnvTokenSource struct {
// contains filtered or unexported fields
}
EnvTokenSource reads a token from an environment variable.
func DefaultEnvTokenSource ¶
func DefaultEnvTokenSource() *EnvTokenSource
DefaultEnvTokenSource returns a TokenSource that reads from the CARABINER_CREDENTIALS environment variable.
func NewEnvTokenSource ¶
func NewEnvTokenSource(envVar string) *EnvTokenSource
NewEnvTokenSource creates a TokenSource that reads from an environment variable.
type FileTokenSource ¶
type FileTokenSource struct {
// contains filtered or unexported fields
}
FileTokenSource reads a token from a file. The file is read on each call to Token(), allowing for external token rotation.
func DefaultFileTokenSource ¶
func DefaultFileTokenSource() (*FileTokenSource, error)
DefaultFileTokenSource returns a TokenSource that reads from the default session's identity file. If no session exists, falls back to the legacy path at os.UserConfigDir()/carabiner/identity.json.
func NewFileTokenSource ¶
func NewFileTokenSource(path string) *FileTokenSource
NewFileTokenSource creates a TokenSource that reads from a file. The file should contain a JWT token (whitespace is trimmed).
func ServerFileTokenSource ¶
func ServerFileTokenSource(serverURL string) (*FileTokenSource, error)
ServerFileTokenSource returns a TokenSource that reads from a specific server's session identity file.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager manages credential sessions by handling token lifecycle. It uses a central identity token source to exchange for short lived audience-specific tokens.
func NewManager ¶
NewManager creates a new credential manager.
Use WithTokenSource to configure the central identity token source(s). If no sources are provided, the manager uses the default sources:
- CARABINER_CREDENTIALS environment variable
- os.UserConfigDir()/carabiner/identity.json
Use WithServer to configure the deadrop exchange server URL.
func (*Manager) Register ¶
Register adds a new exchange request and immediately exchanges a token.
The id is used to retrieve the token later via Token() or TokenSource().
func (*Manager) Token ¶
Token returns the token for the given id. If the token is expired or about to expire, it will be refreshed.
func (*Manager) TokenSource ¶
func (m *Manager) TokenSource(id string) (TokenSource, error)
TokenSource returns a TokenSource for the given id.
type Option ¶
type Option func(*Manager)
Option is a functional option for configuring the Manager.
func WithHTTPClient ¶
WithHTTPClient sets a custom HTTP client for the exchange client.
func WithMaxRetries ¶
WithMaxRetries sets the maximum number of retry attempts for token exchange. Default is 5.
func WithRefreshBuffer ¶
WithRefreshBuffer sets the refresh buffer as a fraction of token lifetime. For example, 0.2 means refresh when 20% of the token lifetime remains (i.e., at 80% of the way through the token's validity period). Default is 0.2.
func WithRetryInterval ¶
WithRetryInterval sets the initial retry interval for exponential backoff. Default is 1 second.
func WithServer ¶
WithServer sets the deadrop exchange server URL.
func WithTokenSource ¶
func WithTokenSource(sources ...TokenSource) Option
WithTokenSource adds one or more TokenSources for the central identity token. Multiple sources are tried in order until one succeeds. If no sources are provided via this option, the Manager uses the default sources: 1. CARABINER_CREDENTIALS environment variable 2. os.UserConfigDir()/carabiner/identity.json
type ServerOptions ¶
type ServerOptions struct {
// Server is the deadrop exchange server URL.
Server string
// Prefix is an optional prefix for flag names (e.g., "deadrop" -> "--deadrop-server").
Prefix string
// Audience is the default audience for token exchange.
Audience []string
// DisablePersistence disables token caching to disk.
DisablePersistence bool
}
ServerOptions is an ServerOptionsSet for configuring deadrop credentials in CLI tools. It provides the --server flag and methods to obtain TokenSource instances for specific audiences.
Example usage in a CLI tool:
type MyServerOptions struct {
credentials.ServerOptions
// other options...
}
func (o *MyServerOptions) AddFlags(cmd *cobra.Command) {
o.ServerOptions.AddFlags(cmd)
// add other flags...
}
// In command handler:
source, err := opts.TokenSource(ctx)
if err != nil {
return err
}
token, err := source.Token(ctx)
Example with prefix and audience:
opts := credentials.NewServerOptions(
credentials.WithPrefix("deadrop"),
credentials.WithAudience("https://api.example.com"),
)
func NewServerOptions ¶
func NewServerOptions(opts ...ServerOptionsOption) *ServerOptions
NewServerOptions creates a new ServerOptions with default values. Use functional options to customize the configuration.
Examples:
// Default options
opts := credentials.NewServerOptions()
// With prefix
opts := credentials.NewServerOptions(credentials.WithPrefix("deadrop"))
// With prefix and audience
opts := credentials.NewServerOptions(
credentials.WithPrefix("deadrop"),
credentials.WithAudience("https://api.example.com"),
)
func (*ServerOptions) AddFlags ¶
func (o *ServerOptions) AddFlags(cmd *cobra.Command)
AddFlags adds the deadrop credential flags to the command.
func (*ServerOptions) Config ¶
func (o *ServerOptions) Config() *command.OptionsSetConfig
Config returns the OptionsSetConfig for this options set.
func (*ServerOptions) Manager ¶
func (o *ServerOptions) Manager(ctx context.Context) (*Manager, error)
Manager returns a new credentials Manager configured with these options. The Manager provides more control over token lifecycle than TokenSource.
Example:
mgr, err := opts.Manager(ctx)
if err != nil {
return err
}
defer mgr.Close()
err = mgr.Register(ctx, "api", &exchange.ExchangeRequest{
Audience: []string{"https://api.example.com"},
})
token, err := mgr.Token(ctx, "api")
func (*ServerOptions) TokenSource ¶
func (o *ServerOptions) TokenSource(ctx context.Context, audience ...string) (TokenSource, error)
TokenSource returns a TokenSource for the given audience. If no audience is provided, uses the audience configured via WithAudience(). The returned TokenSource handles token exchange and automatic renewal.
Example:
// With audience specified at call time
source, err := opts.TokenSource(ctx, "https://api.example.com")
// Using preloaded audience from WithAudience()
opts := credentials.NewServerOptions(credentials.WithAudience("https://api.example.com"))
source, err := opts.TokenSource(ctx)
func (*ServerOptions) TokenSourceWithRequest ¶
func (o *ServerOptions) TokenSourceWithRequest(ctx context.Context, req *exchange.ExchangeRequest) (TokenSource, error)
TokenSourceWithRequest returns a TokenSource for the given exchange request. This allows specifying additional exchange parameters like scope and resource.
Example:
source, err := opts.TokenSourceWithRequest(ctx, &exchange.ExchangeRequest{
Audience: []string{"https://api.example.com"},
Scope: []string{"read", "write"},
})
func (*ServerOptions) Validate ¶
func (o *ServerOptions) Validate() error
Validate validates the options.
type ServerOptionsOption ¶
type ServerOptionsOption func(*ServerOptions)
ServerOptionsOption is a functional option for configuring ServerOptions.
func WithAudience ¶
func WithAudience(audience ...string) ServerOptionsOption
WithAudience sets the default audience for token exchange. This can be overridden when calling TokenSource().
func WithDisablePersistence ¶
func WithDisablePersistence() ServerOptionsOption
WithDisablePersistence disables token caching to disk.
func WithPrefix ¶
func WithPrefix(prefix string) ServerOptionsOption
WithPrefix sets the flag prefix for the options. For example, WithPrefix("deadrop") results in flags like --deadrop-server.
type ServiceTokenSource ¶
type ServiceTokenSource struct {
// contains filtered or unexported fields
}
ServiceTokenSource is a TokenSource that exchanges the main Carabiner identity token for a service-specific token based on an ExchangeRequest. It manages the lifecycle of the exchanged token, automatically renewing it when less than 20% of its lifetime remains (configurable via WithServiceRefreshBuffer).
The ExchangeRequest serves as a template: its Audience, Scope, Resource, and token type fields are preserved, while SubjectToken is set automatically from the identity source on each exchange.
Example usage:
source, err := credentials.NewServiceTokenSource(
&exchange.ExchangeRequest{
Audience: []string{"https://api.example.com"},
},
"https://auth.carabiner.dev",
credentials.WithServicePersistence(),
)
if err != nil {
log.Fatal(err)
}
token, err := source.Token(ctx)
func NewServiceTokenSource ¶
func NewServiceTokenSource(req *exchange.ExchangeRequest, serverURL string, opts ...ServiceTokenSourceOption) (*ServiceTokenSource, error)
NewServiceTokenSource creates a ServiceTokenSource that exchanges the main Carabiner identity for a service-specific token matching the given ExchangeRequest.
The request serves as a template: SubjectToken is ignored and set automatically from the identity source on each exchange. All other fields (Audience, Scope, Resource, SubjectTokenType, RequestedTokenType) are forwarded as-is.
The serverURL is the deadrop exchange server URL. Use options to configure identity source, persistence, and refresh behavior.
func (*ServiceTokenSource) Token ¶
func (s *ServiceTokenSource) Token(ctx context.Context) (string, error)
Token returns a valid exchanged service token. If the current token has less than 20% of its lifetime remaining, it is automatically renewed in the background. If no valid token is available, a new exchange is performed synchronously.
type ServiceTokenSourceOption ¶
type ServiceTokenSourceOption func(*ServiceTokenSource)
ServiceTokenSourceOption configures a ServiceTokenSource.
func WithServiceIdentitySource ¶
func WithServiceIdentitySource(source TokenSource) ServiceTokenSourceOption
WithServiceIdentitySource overrides the default identity token source used to obtain the subject token for exchange.
func WithServicePersistence ¶
func WithServicePersistence() ServiceTokenSourceOption
WithServicePersistence enables token persistence in the server's session directory. When enabled, exchanged tokens are cached to disk and loaded on subsequent calls, surviving process restarts.
func WithServiceRefreshBuffer ¶
func WithServiceRefreshBuffer(buffer float64) ServiceTokenSourceOption
WithServiceRefreshBuffer sets the fraction of token lifetime remaining that triggers a renewal. Default is 0.2 (renew when 20% of lifetime remains).
type SessionInfo ¶
type SessionInfo struct {
Dir string `json:"dir"`
CreatedAt time.Time `json:"created_at"`
ServerURL string `json:"server_url,omitempty"` // Stored for reference
}
SessionInfo holds information about a session for a specific server
func GetDefaultSession ¶
func GetDefaultSession() (*SessionInfo, string, error)
GetDefaultSession returns the default session info, if any
func GetOrCreateSession ¶
func GetOrCreateSession(serverURL string) (*SessionInfo, error)
GetOrCreateSession gets an existing session for a server or creates a new one
type SessionsConfig ¶
type SessionsConfig struct {
Sessions map[string]*SessionInfo `json:"sessions"`
Default string `json:"default,omitempty"`
}
SessionsConfig holds the mapping of servers to session directories
func LoadSessionsConfig ¶
func LoadSessionsConfig() (*SessionsConfig, error)
LoadSessionsConfig loads the sessions configuration from disk
type StaticTokenSource ¶
type StaticTokenSource struct {
// contains filtered or unexported fields
}
StaticTokenSource returns a fixed token. Useful for testing.
func NewStaticTokenSource ¶
func NewStaticTokenSource(token string) *StaticTokenSource
NewStaticTokenSource creates a TokenSource that always returns the same token.
type TokenSource ¶
type TokenSource interface {
// Token returns a valid token or an error.
Token(ctx context.Context) (string, error)
}
TokenSource is an interface for retrieving tokens, similar to oauth2.TokenSource.
func DefaultTokenSource ¶
func DefaultTokenSource() (TokenSource, error)
DefaultTokenSource returns a ChainedTokenSource that tries: 1. CARABINER_CREDENTIALS environment variable 2. os.UserConfigDir()/carabiner/identity.json