toolauth

package
v0.6.3 Latest Latest
Warning

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

Go to latest
Published: Sep 12, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package toolauth provides client-side authentication for kombify desktop tools.

Desktop tools (SpeechKit, etc.) use this package to authenticate against the kombify Cloud platform via API key or device code flow. It handles token storage (OS credential store or encrypted file fallback), automatic token refresh, entitlement checking with caching, and batched usage reporting.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotAuthenticated is returned when an operation requires authentication
	// but no token is available.
	ErrNotAuthenticated = fmt.Errorf("toolauth: not authenticated")
	// ErrAuthorizationPending is returned by PollDeviceCode when the user has
	// not yet completed authorization.
	ErrAuthorizationPending = fmt.Errorf("toolauth: authorization pending")
	// ErrDeviceCodeExpired is returned by PollDeviceCode when the device code
	// has expired before the user authorized.
	ErrDeviceCodeExpired = fmt.Errorf("toolauth: device code expired")
)

Sentinel errors for expected conditions.

Functions

This section is empty.

Types

type APIError

type APIError struct {
	StatusCode int
	Body       string
}

APIError represents a non-success HTTP response from the platform API.

func (*APIError) Error

func (e *APIError) Error() string

Error implements the error interface.

type AuthResult

type AuthResult struct {
	Token        TokenPair     `json:"token"`
	Entitlements *Entitlements `json:"entitlements,omitempty"`
}

AuthResult is the outcome of a successful authentication attempt.

type Client

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

Client authenticates desktop tools against the kombify Cloud platform. It manages token lifecycle (obtain, refresh, store) and provides access to entitlements and usage reporting.

Client is safe for concurrent use.

func New

func New(cfg Config) (*Client, error)

New creates a new toolauth Client. It attempts to load a previously stored token from the token store. An error is returned only if the configuration is invalid; a missing stored token is not an error.

func (*Client) AuthenticateWithAPIKey

func (c *Client) AuthenticateWithAPIKey(ctx context.Context, apiKey string) (*AuthResult, error)

AuthenticateWithAPIKey authenticates using a pre-provisioned API key. On success the token is persisted to the token store.

func (*Client) GetAccessToken

func (c *Client) GetAccessToken(ctx context.Context) (string, error)

GetAccessToken returns a valid access token, refreshing it if necessary. Returns an error if the client is not authenticated.

func (*Client) GetEntitlements

func (c *Client) GetEntitlements(ctx context.Context) (*Entitlements, error)

GetEntitlements fetches the tool entitlements for the authenticated user. Results are cached for 24 hours. Use InvalidateEntitlementCache to force a fresh fetch.

func (*Client) GetFeatureValue

func (c *Client) GetFeatureValue(ctx context.Context, feature string) (any, error)

GetFeatureValue returns the raw value of a feature from the entitlements. Returns nil, nil if the feature does not exist.

func (*Client) HasFeature

func (c *Client) HasFeature(ctx context.Context, feature string) (bool, error)

HasFeature checks whether the authenticated user has the named feature enabled for this tool. The entitlement cache is used if fresh, otherwise a fetch is triggered.

func (*Client) InvalidateEntitlementCache

func (c *Client) InvalidateEntitlementCache()

InvalidateEntitlementCache clears the cached entitlements so the next call to GetEntitlements, HasFeature, or GetFeatureValue triggers a fresh fetch.

func (*Client) IsAuthenticated

func (c *Client) IsAuthenticated() bool

IsAuthenticated reports whether the client holds a token. This does not verify the token is still valid on the server.

func (*Client) Logout

func (c *Client) Logout(_ context.Context) error

Logout clears the stored token and cached entitlements.

func (*Client) PollDeviceCode

func (c *Client) PollDeviceCode(ctx context.Context, deviceCode string) (*AuthResult, error)

PollDeviceCode polls the platform to check whether the user has completed the device code authorization. Returns ErrAuthorizationPending if the user has not yet authorized, or ErrDeviceCodeExpired if the code has expired.

func (*Client) ReportUsage

func (c *Client) ReportUsage(_ context.Context, events ...UsageEvent) error

ReportUsage buffers usage events for asynchronous delivery. Events are held in memory until flushed by a UsageReporter. If no UsageReporter is running, events accumulate in memory without bound; callers should start a reporter for long-lived processes.

func (*Client) StartDeviceCodeFlow

func (c *Client) StartDeviceCodeFlow(ctx context.Context) (*DeviceCodeResponse, error)

StartDeviceCodeFlow initiates the OAuth 2.0 device authorization flow. The caller should display VerificationURI and UserCode to the user, then poll with PollDeviceCode.

func (*Client) StartUsageReporter

func (c *Client) StartUsageReporter(ctx context.Context, flushInterval time.Duration) *UsageReporter

StartUsageReporter starts a background goroutine that flushes usage events at the given interval. The reporter runs until Stop is called or the provided context is canceled.

type Config

type Config struct {
	// BaseURL is the kombify API base URL (e.g. "https://api.kombify.io").
	BaseURL string
	// ToolName identifies the tool (e.g. "speechkit").
	ToolName string
	// ToolVersion is the semantic version of the tool (e.g. "0.1.0").
	ToolVersion string
	// TokenStore provides persistent token storage. If nil, the platform
	// default is used (Windows Credential Manager or encrypted file).
	TokenStore TokenStore
	// HTTPClient is an optional custom HTTP client. If nil, a default
	// client with a 30-second timeout is used.
	HTTPClient *http.Client
}

Config configures the toolauth Client.

type DeviceCodeResponse

type DeviceCodeResponse struct {
	DeviceCode      string `json:"device_code"`
	UserCode        string `json:"user_code"`
	VerificationURI string `json:"verification_uri"`
	ExpiresIn       int    `json:"expires_in"`
	Interval        int    `json:"interval"`
}

DeviceCodeResponse is returned when initiating the device code auth flow. The user must visit VerificationURI and enter UserCode to authorize the device.

type Entitlements

type Entitlements struct {
	Tool      string         `json:"tool"`
	Features  map[string]any `json:"features,omitempty"`
	ExpiresAt *time.Time     `json:"expires_at,omitempty"`
}

Entitlements describes what features a tool license grants.

type FileStore

type FileStore struct{}

FileStore stores tokens as AES-256-GCM encrypted JSON files. This is the fallback when the OS credential store is unavailable. Files are stored in ~/.kombify/<toolname>/token.json.

func (*FileStore) Delete

func (s *FileStore) Delete(toolName string) error

Delete removes the token file from disk.

func (*FileStore) Load

func (s *FileStore) Load(toolName string) (*TokenPair, error)

Load reads and decrypts the token pair from disk. Returns nil, nil if the file does not exist.

func (*FileStore) Save

func (s *FileStore) Save(toolName string, token *TokenPair) error

Save encrypts and writes the token pair to disk.

type TokenPair

type TokenPair struct {
	AccessToken  string    `json:"access_token"`
	RefreshToken string    `json:"refresh_token"`
	ExpiresAt    time.Time `json:"expires_at"`
	UserID       string    `json:"user_id"`
}

TokenPair holds the access and refresh tokens issued by the platform.

func (*TokenPair) IsExpired

func (t *TokenPair) IsExpired() bool

IsExpired reports whether the access token has expired. A 30-second buffer is applied to avoid using a token that is about to expire.

type TokenStore

type TokenStore interface {
	// Save persists the token pair for the given tool name.
	Save(toolName string, token *TokenPair) error
	// Load retrieves a previously stored token pair.
	// Returns nil, nil if no token is stored.
	Load(toolName string) (*TokenPair, error)
	// Delete removes the stored token pair for the given tool name.
	Delete(toolName string) error
}

TokenStore persists token pairs between tool sessions. Implementations must be safe for concurrent use.

func DefaultTokenStore

func DefaultTokenStore() TokenStore

DefaultTokenStore returns the platform-preferred token store: the Windows Credential Manager on Windows, the encrypted file store elsewhere. Exported for native-client consumers (CLI login flows) that need direct store access without the full Client device-flow wrapper.

type UsageEvent

type UsageEvent struct {
	Metric string    `json:"metric"`
	Value  float64   `json:"value"`
	At     time.Time `json:"at"`
}

UsageEvent represents a single usage metric to be reported to the platform.

type UsageReporter

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

UsageReporter runs a background goroutine that periodically flushes buffered usage events to the platform API.

func (*UsageReporter) Stop

func (r *UsageReporter) Stop()

Stop signals the reporter to flush remaining events and stop. It blocks until the final flush completes.

Jump to

Keyboard shortcuts

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