auth

package
v0.12.0 Latest Latest
Warning

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

Go to latest
Published: Aug 22, 2025 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// Default OAuth client ID for FTL authentication
	DefaultClientID = "client_01K2ADMPRAFT9X83PFVJBQ6T49"
	// Default AuthKit domain for authentication
	DefaultAuthKitDomain = "divine-lion-50-staging.authkit.app"
	// Maximum time to wait for login completion
	LoginTimeout = 30 * time.Minute
	// Keyring service name
	KeyringService = "ftl"
	// Keyring username
	KeyringUsername = "default"
)

Constants for OAuth configuration

Variables

This section is empty.

Functions

func GetM2MTokenFromEnv

func GetM2MTokenFromEnv() string

GetM2MTokenFromEnv gets a pre-generated M2M token from environment

func IsM2MConfigured

func IsM2MConfigured() bool

IsM2MConfigured checks if M2M credentials are available

Types

type AuthStatus

type AuthStatus struct {
	LoggedIn     bool
	Credentials  *Credentials
	Error        error
	NeedsRefresh bool
}

AuthStatus represents the current authentication status

type BrowserOpener

type BrowserOpener interface {
	OpenURL(url string) error
}

BrowserOpener defines the interface for opening URLs in a browser

type CredentialStore

type CredentialStore interface {
	// Load retrieves stored credentials
	Load() (*Credentials, error)
	// Save stores credentials securely
	Save(creds *Credentials) error
	// Delete removes stored credentials
	Delete() error
	// Exists checks if credentials are stored
	Exists() bool

	// M2M-specific methods
	StoreToken(token string, expiresIn int) error
	GetM2MConfig() (*M2MConfig, error)
	StoreM2MConfig(config *M2MConfig) error
	SetActorType(actorType string) error
	GetActorType() (string, error)
}

CredentialStore provides secure storage for authentication credentials

type Credentials

type Credentials struct {
	// AuthKit domain used for authentication
	AuthKitDomain string `json:"authkit_domain"`
	// OAuth access token
	AccessToken string `json:"access_token"`
	// OAuth refresh token for renewing access
	RefreshToken string `json:"refresh_token,omitempty"`
	// Token expiration time
	ExpiresAt *time.Time `json:"expires_at,omitempty"`
	// Client ID used for authentication
	ClientID string `json:"client_id,omitempty"`
}

Credentials represents stored authentication credentials

func (*Credentials) IsExpired

func (c *Credentials) IsExpired() bool

IsExpired checks if the access token has expired

func (*Credentials) TimeUntilExpiry

func (c *Credentials) TimeUntilExpiry() time.Duration

TimeUntilExpiry returns the duration until token expiry

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"`
	ExpiresIn               int    `json:"expires_in"`
	Interval                int    `json:"interval,omitempty"`
}

DeviceAuthResponse represents the response from device authorization endpoint

type HTTPClient

type HTTPClient interface {
	Do(req *http.Request) (*http.Response, error)
}

HTTPClient defines the interface for HTTP operations

type JWTClaims

type JWTClaims struct {
	// Standard claims
	Subject   string `json:"sub"`
	Email     string `json:"email"`
	Name      string `json:"name"`
	ExpiresAt int64  `json:"exp"`
	IssuedAt  int64  `json:"iat"`

	// WorkOS-specific claims
	OrganizationID string   `json:"org_id"`
	Organizations  []string `json:"org_ids"`
	ActorType      string   `json:"actor_type"`
	UserID         string   `json:"user_id"`

	// Additional user info
	EmailVerified bool   `json:"email_verified"`
	Username      string `json:"username"`
	FirstName     string `json:"first_name"`
	LastName      string `json:"last_name"`
}

JWTClaims represents the claims we extract from the JWT

func ExtractIDToken

func ExtractIDToken(tokenResp *TokenResponse) (*JWTClaims, error)

ExtractIDToken extracts user info from an ID token if present

func ExtractUserInfo

func ExtractUserInfo(tokenString string) (*JWTClaims, error)

ExtractUserInfo extracts user information from a JWT token without verification This is safe because the token has already been verified by the backend

func (*JWTClaims) GetDisplayName

func (c *JWTClaims) GetDisplayName() string

GetDisplayName returns the best available display name for the user

func (*JWTClaims) IsExpired

func (c *JWTClaims) IsExpired() bool

IsExpired checks if the token is expired

type KeyringStore

type KeyringStore struct{}

KeyringStore implements CredentialStore using OS keyring

func NewKeyringStore

func NewKeyringStore() (*KeyringStore, error)

NewKeyringStore creates a new keyring-based credential store

func (*KeyringStore) Delete

func (s *KeyringStore) Delete() error

Delete removes stored credentials from the keyring

func (*KeyringStore) Exists

func (s *KeyringStore) Exists() bool

Exists checks if credentials are stored

func (*KeyringStore) GetActorType

func (s *KeyringStore) GetActorType() (string, error)

GetActorType retrieves the stored actor type

func (*KeyringStore) GetM2MConfig

func (s *KeyringStore) GetM2MConfig() (*M2MConfig, error)

GetM2MConfig retrieves stored M2M configuration

func (*KeyringStore) Load

func (s *KeyringStore) Load() (*Credentials, error)

Load retrieves stored credentials from the keyring

func (*KeyringStore) Save

func (s *KeyringStore) Save(creds *Credentials) error

Save stores credentials in the keyring

func (*KeyringStore) SetActorType

func (s *KeyringStore) SetActorType(actorType string) error

SetActorType stores whether the current actor is a user or machine

func (*KeyringStore) StoreM2MConfig

func (s *KeyringStore) StoreM2MConfig(config *M2MConfig) error

StoreM2MConfig stores M2M configuration

func (*KeyringStore) StoreToken

func (s *KeyringStore) StoreToken(token string, expiresIn int) error

StoreToken stores just an access token (for M2M flows)

type LoginConfig

type LoginConfig struct {
	// Don't open browser automatically
	NoBrowser bool
	// Override AuthKit domain (for testing)
	AuthKitDomain string
	// Override OAuth client ID (for testing)
	ClientID string
	// Force re-authentication even if already logged in
	Force bool
}

LoginConfig contains configuration for the login process

type M2MConfig

type M2MConfig struct {
	ClientID     string `json:"client_id"`
	ClientSecret string `json:"client_secret"`
	Issuer       string `json:"issuer,omitempty"`
	OrgID        string `json:"org_id,omitempty"` // Set after token exchange
}

M2MConfig holds configuration for machine-to-machine authentication

type M2MManager

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

M2MManager handles machine-to-machine authentication

func NewM2MManager

func NewM2MManager(store CredentialStore) *M2MManager

NewM2MManager creates a new M2M authentication manager

func (*M2MManager) ExchangeCredentials

func (m *M2MManager) ExchangeCredentials(ctx context.Context, config *M2MConfig) (*TokenResponse, error)

ExchangeCredentials exchanges client credentials for an access token

func (*M2MManager) LoadM2MConfig

func (m *M2MManager) LoadM2MConfig() (*M2MConfig, error)

LoadM2MConfig loads M2M configuration from environment or stored config

type M2MTokenResponse

type M2MTokenResponse struct {
	AccessToken string `json:"access_token"`
	TokenType   string `json:"token_type"`
	ExpiresIn   int    `json:"expires_in"`
}

M2MTokenResponse represents the response from the token endpoint

type Manager

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

Manager handles authentication operations

func NewManager

func NewManager(store CredentialStore, config *LoginConfig) *Manager

NewManager creates a new authentication manager

func NewManagerWithMocks

func NewManagerWithMocks(store CredentialStore, provider OAuthProvider, browser BrowserOpener, config *LoginConfig) *Manager

NewManagerWithMocks creates a new authentication manager with all dependencies mocked This is specifically for testing to prevent any external interactions

func NewManagerWithProvider

func NewManagerWithProvider(store CredentialStore, provider OAuthProvider, config *LoginConfig) *Manager

NewManagerWithProvider creates a new authentication manager with a custom OAuth provider This is primarily for testing but can be used for custom OAuth implementations

func (*Manager) CompleteDeviceFlow

func (m *Manager) CompleteDeviceFlow(ctx context.Context, deviceAuth *DeviceAuthResponse) (*Credentials, error)

CompleteDeviceFlow completes the device flow authentication

func (*Manager) ConfigureM2M

func (m *Manager) ConfigureM2M(config *M2MConfig) error

ConfigureM2M stores M2M credentials for later use

func (*Manager) GetActorType

func (m *Manager) GetActorType(ctx context.Context) (string, error)

GetActorType returns whether the current actor is a user or machine

func (*Manager) GetOrRefreshToken

func (m *Manager) GetOrRefreshToken(ctx context.Context) (string, error)

GetOrRefreshToken gets a valid token, refreshing if necessary

func (*Manager) GetToken

func (m *Manager) GetToken(ctx context.Context) (string, error)

GetToken returns the current access token, refreshing if necessary

func (*Manager) Login

func (m *Manager) Login(ctx context.Context) (*Credentials, error)

Login performs the complete OAuth device flow login

func (*Manager) LoginMachine

func (m *Manager) LoginMachine(ctx context.Context) error

LoginMachine performs machine login using client credentials

func (*Manager) LoginMachineWithToken

func (m *Manager) LoginMachineWithToken(ctx context.Context, token string) error

LoginMachineWithToken logs in using a pre-existing M2M token

func (*Manager) Logout

func (m *Manager) Logout() error

Logout removes stored credentials

func (*Manager) Refresh

func (m *Manager) Refresh(ctx context.Context, creds *Credentials) (*Credentials, error)

Refresh refreshes an expired access token

func (*Manager) SaveUserInfoFromToken

func (m *Manager) SaveUserInfoFromToken(token *TokenResponse) error

SaveUserInfoFromToken extracts and saves user info from a token

func (*Manager) StartDeviceFlow

func (m *Manager) StartDeviceFlow(ctx context.Context) (*DeviceAuthResponse, error)

StartDeviceFlow starts the OAuth device flow and returns device auth info

func (*Manager) Status

func (m *Manager) Status() *AuthStatus

Status returns the current authentication status

type MockBrowserOpener

type MockBrowserOpener struct {

	// OpenURL behavior
	OpenURLFunc  func(url string) error
	OpenURLCalls []struct {
		URL string
	}
	// contains filtered or unexported fields
}

MockBrowserOpener is a mock implementation of BrowserOpener for testing

func (*MockBrowserOpener) OpenURL

func (m *MockBrowserOpener) OpenURL(url string) error

OpenURL implements BrowserOpener

func (*MockBrowserOpener) Reset

func (m *MockBrowserOpener) Reset()

Reset clears all recorded calls

type MockBuilder

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

MockBuilder provides a fluent interface for building test scenarios

func NewMockBuilder

func NewMockBuilder() *MockBuilder

NewMockBuilder creates a new mock builder

func (*MockBuilder) Build

func (b *MockBuilder) Build() (*Manager, *MockOAuthProvider, *MockStore)

Build creates a Manager with the configured mocks

func (*MockBuilder) WithDeviceFlow

func (b *MockBuilder) WithDeviceFlow(resp *DeviceAuthResponse, err error) *MockBuilder

WithDeviceFlow configures the device flow response

func (*MockBuilder) WithRefreshToken

func (b *MockBuilder) WithRefreshToken(resp *TokenResponse, err error) *MockBuilder

WithRefreshToken configures the refresh token response

func (*MockBuilder) WithStoreError

func (b *MockBuilder) WithStoreError(err error) *MockBuilder

WithStoreError configures a store error

func (*MockBuilder) WithStoredCredentials

func (b *MockBuilder) WithStoredCredentials(creds *Credentials) *MockBuilder

WithStoredCredentials configures the stored credentials

func (*MockBuilder) WithTokenPolling

func (b *MockBuilder) WithTokenPolling(responses []interface{}) *MockBuilder

WithTokenPolling configures the token polling behavior This simulates the entire polling loop, handling authorization_pending internally

type MockHTTPClient

type MockHTTPClient struct {

	// Do behavior
	DoFunc  func(req *http.Request) (*http.Response, error)
	DoCalls []struct {
		Req *http.Request
	}
	// contains filtered or unexported fields
}

MockHTTPClient is a mock implementation of HTTPClient for testing

func (*MockHTTPClient) Do

func (m *MockHTTPClient) Do(req *http.Request) (*http.Response, error)

Do implements HTTPClient

func (*MockHTTPClient) Reset

func (m *MockHTTPClient) Reset()

Reset clears all recorded calls

type MockOAuthProvider

type MockOAuthProvider struct {

	// StartDeviceFlow behavior
	StartDeviceFlowFunc  func(ctx context.Context) (*DeviceAuthResponse, error)
	StartDeviceFlowCalls []struct {
		Ctx context.Context
	}

	// PollForToken behavior
	PollForTokenFunc  func(ctx context.Context, deviceCode string, interval time.Duration) (*TokenResponse, error)
	PollForTokenCalls []struct {
		Ctx        context.Context
		DeviceCode string
		Interval   time.Duration
	}

	// RefreshToken behavior
	RefreshTokenFunc  func(ctx context.Context, refreshToken string) (*TokenResponse, error)
	RefreshTokenCalls []struct {
		Ctx          context.Context
		RefreshToken string
	}
	// contains filtered or unexported fields
}

MockOAuthProvider is a mock implementation of OAuthProvider for testing

func (*MockOAuthProvider) PollForToken

func (m *MockOAuthProvider) PollForToken(ctx context.Context, deviceCode string, interval time.Duration) (*TokenResponse, error)

PollForToken implements OAuthProvider

func (*MockOAuthProvider) RefreshToken

func (m *MockOAuthProvider) RefreshToken(ctx context.Context, refreshToken string) (*TokenResponse, error)

RefreshToken implements OAuthProvider

func (*MockOAuthProvider) Reset

func (m *MockOAuthProvider) Reset()

Reset clears all recorded calls

func (*MockOAuthProvider) StartDeviceFlow

func (m *MockOAuthProvider) StartDeviceFlow(ctx context.Context) (*DeviceAuthResponse, error)

StartDeviceFlow implements OAuthProvider

type MockStore

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

MockStore implements CredentialStore for testing

func NewMockStore

func NewMockStore(creds *Credentials, err error) *MockStore

NewMockStore creates a mock credential store for testing

func (*MockStore) Delete

func (m *MockStore) Delete() error

Delete clears the mock credentials

func (*MockStore) Exists

func (m *MockStore) Exists() bool

Exists checks if mock credentials exist

func (*MockStore) GetActorType

func (m *MockStore) GetActorType() (string, error)

GetActorType retrieves the stored actor type

func (*MockStore) GetM2MConfig

func (m *MockStore) GetM2MConfig() (*M2MConfig, error)

GetM2MConfig retrieves stored M2M configuration

func (*MockStore) Load

func (m *MockStore) Load() (*Credentials, error)

Load returns the mock credentials

func (*MockStore) Save

func (m *MockStore) Save(creds *Credentials) error

Save stores the mock credentials

func (*MockStore) SetActorType

func (m *MockStore) SetActorType(actorType string) error

SetActorType stores whether the current actor is a user or machine

func (*MockStore) StoreM2MConfig

func (m *MockStore) StoreM2MConfig(config *M2MConfig) error

StoreM2MConfig stores M2M configuration

func (*MockStore) StoreToken

func (m *MockStore) StoreToken(token string, expiresIn int) error

StoreToken stores just an access token (for M2M flows)

type OAuthClient

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

OAuthClient handles OAuth device flow authentication

func NewOAuthClient

func NewOAuthClient(authKitDomain, clientID string) *OAuthClient

NewOAuthClient creates a new OAuth client

func (*OAuthClient) PollForToken

func (c *OAuthClient) PollForToken(ctx context.Context, deviceCode string, interval time.Duration) (*TokenResponse, error)

PollForToken polls the token endpoint until authentication completes

func (*OAuthClient) RefreshToken

func (c *OAuthClient) RefreshToken(ctx context.Context, refreshToken string) (*TokenResponse, error)

RefreshToken refreshes an expired access token

func (*OAuthClient) StartDeviceFlow

func (c *OAuthClient) StartDeviceFlow(ctx context.Context) (*DeviceAuthResponse, error)

StartDeviceFlow initiates the OAuth device flow

type OAuthProvider

type OAuthProvider interface {
	// StartDeviceFlow initiates the OAuth device flow
	StartDeviceFlow(ctx context.Context) (*DeviceAuthResponse, error)
	// PollForToken polls the token endpoint until authentication completes
	PollForToken(ctx context.Context, deviceCode string, interval time.Duration) (*TokenResponse, error)
	// RefreshToken refreshes an expired access token
	RefreshToken(ctx context.Context, refreshToken string) (*TokenResponse, error)
}

OAuthProvider defines the interface for OAuth operations

type TestHelpers

type TestHelpers struct{}

TestHelpers provides utility functions for tests

func NewTestHelpers

func NewTestHelpers() *TestHelpers

NewTestHelpers creates test helpers

func (*TestHelpers) AccessDeniedError

func (h *TestHelpers) AccessDeniedError() *TokenError

AccessDeniedError creates an access denied error

func (*TestHelpers) AuthorizationPendingError

func (h *TestHelpers) AuthorizationPendingError() *TokenError

AuthorizationPendingError creates an authorization pending error

func (*TestHelpers) DeviceAuthResponse

func (h *TestHelpers) DeviceAuthResponse() *DeviceAuthResponse

DeviceAuthResponse creates a test device auth response

func (*TestHelpers) ExpiredCredentials

func (h *TestHelpers) ExpiredCredentials() *Credentials

ExpiredCredentials creates expired test credentials

func (*TestHelpers) ExpiredTokenError

func (h *TestHelpers) ExpiredTokenError() *TokenError

ExpiredTokenError creates an expired token error

func (*TestHelpers) SlowDownError

func (h *TestHelpers) SlowDownError() *TokenError

SlowDownError creates a slow down error

func (*TestHelpers) TokenResponse

func (h *TestHelpers) TokenResponse() *TokenResponse

TokenResponse creates a test token response

func (*TestHelpers) ValidCredentials

func (h *TestHelpers) ValidCredentials() *Credentials

ValidCredentials creates valid test credentials

type TokenError

type TokenError struct {
	ErrorCode        string `json:"error"`
	ErrorDescription string `json:"error_description,omitempty"`
}

TokenError represents an error response from token endpoint

func (*TokenError) Error

func (e *TokenError) Error() string

Error implements the error interface for TokenError

func (*TokenError) IsAuthorizationPending

func (e *TokenError) IsAuthorizationPending() bool

IsAuthorizationPending checks if the error indicates pending authorization

func (*TokenError) IsExpired

func (e *TokenError) IsExpired() bool

IsExpired checks if the device code has expired

func (*TokenError) IsSlowDown

func (e *TokenError) IsSlowDown() bool

IsSlowDown checks if we should slow down polling

type TokenResponse

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

TokenResponse represents the response from token endpoint

Jump to

Keyboard shortcuts

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