Documentation
¶
Overview ¶
Package auth provides keyring-based credential storage and OAuth token management.
Index ¶
- Constants
- Variables
- func Authorize(ctx context.Context, creds *config.ClientCredentials, opts AuthorizeOptions) (email string, accountID int64, tok *oauth2.Token, err error)
- func DeletePAT(store Store, email string) error
- func GetAuthenticatedEmail(client string) (string, error)
- func GetPAT(store Store, email string) (token string, accountID int64, err error)
- func GetPATFromEnv() (token string, accountID int64, ok bool)
- func IsKeychainLockedError(msg string) bool
- func ParseTokenKey(k string) (client, email string, ok bool)
- func SelectAccount(accounts []HarvestAccount) (int64, error)
- func StorePAT(store Store, email string, accountID int64, token string) error
- func ValidatePAT(ctx context.Context, token string, accountID int64) (email string, err error)
- type AccountsResponse
- type AuthorizeOptions
- type HarvestAccount
- type KeyringStore
- func (s *KeyringStore) DeleteToken(client, email string) error
- func (s *KeyringStore) GetToken(client, email string) (Token, error)
- func (s *KeyringStore) Keys() ([]string, error)
- func (s *KeyringStore) ListTokens() ([]Token, error)
- func (s *KeyringStore) SetToken(client, email string, accountID int64, tok Token) error
- type PATTokenSource
- type Store
- type Token
- type TokenSource
Constants ¶
const ( // PATClient is the client name used for PAT tokens in the keyring. PATClient = "pat" // PATEnvToken is the environment variable for the PAT. PATEnvToken = "HARVESTCLI_TOKEN" // PATEnvAccountID is the environment variable for the account ID. PATEnvAccountID = "HARVESTCLI_ACCOUNT_ID" )
Variables ¶
var ErrNotAuthenticated = errors.New("not authenticated")
ErrNotAuthenticated indicates no valid token is available.
var HarvestOAuthEndpoint = oauth2.Endpoint{
AuthURL: "https://id.getharvest.com/oauth2/authorize",
TokenURL: "https://id.getharvest.com/api/v2/oauth2/token",
}
HarvestOAuthEndpoint is the Harvest OAuth2 endpoint.
Functions ¶
func Authorize ¶
func Authorize(ctx context.Context, creds *config.ClientCredentials, opts AuthorizeOptions) (email string, accountID int64, tok *oauth2.Token, err error)
Authorize performs OAuth authorization and returns the email, account ID, and token.
func GetAuthenticatedEmail ¶
GetAuthenticatedEmail returns the email for any authenticated account, optionally filtered by client name.
func GetPATFromEnv ¶
GetPATFromEnv checks for HARVESTCLI_TOKEN and HARVESTCLI_ACCOUNT_ID environment variables. Returns token, accountID, ok.
func IsKeychainLockedError ¶
IsKeychainLockedError returns true if the error indicates the keychain is locked.
func ParseTokenKey ¶
ParseTokenKey parses a keyring key into client and email.
func SelectAccount ¶
func SelectAccount(accounts []HarvestAccount) (int64, error)
SelectAccount prompts user to select an account if multiple exist. Returns the selected account ID.
Types ¶
type AccountsResponse ¶
type AccountsResponse struct {
User struct {
ID int64 `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Email string `json:"email"`
} `json:"user"`
Accounts []HarvestAccount `json:"accounts"`
}
AccountsResponse is the response from /accounts endpoint.
func FetchAccounts ¶
FetchAccounts retrieves the user's Harvest accounts using the token.
type AuthorizeOptions ¶
type AuthorizeOptions struct {
Manual bool // Manual copy/paste flow instead of browser
ForceConsent bool // Force consent screen
Timeout time.Duration // Timeout for callback server
Client string // OAuth client name
}
AuthorizeOptions configures the OAuth authorization flow.
type HarvestAccount ¶
type HarvestAccount struct {
ID int64 `json:"id"`
Name string `json:"name"`
Product string `json:"product"`
}
HarvestAccount represents a Harvest account from the accounts endpoint.
type KeyringStore ¶
type KeyringStore struct {
// contains filtered or unexported fields
}
KeyringStore implements Store using the system keyring.
func (*KeyringStore) DeleteToken ¶
func (s *KeyringStore) DeleteToken(client, email string) error
DeleteToken removes a token from the keyring.
func (*KeyringStore) GetToken ¶
func (s *KeyringStore) GetToken(client, email string) (Token, error)
GetToken retrieves a token from the keyring.
func (*KeyringStore) Keys ¶
func (s *KeyringStore) Keys() ([]string, error)
Keys returns all keys in the keyring.
func (*KeyringStore) ListTokens ¶
func (s *KeyringStore) ListTokens() ([]Token, error)
ListTokens returns all tokens in the keyring.
type PATTokenSource ¶
type PATTokenSource struct {
// contains filtered or unexported fields
}
PATTokenSource is a token source that uses a Personal Access Token. PATs don't expire and don't need refresh.
func NewPATTokenSource ¶
func NewPATTokenSource(token string) *PATTokenSource
NewPATTokenSource creates a TokenSource from a Personal Access Token.
type Store ¶
type Store interface {
Keys() ([]string, error)
SetToken(client, email string, accountID int64, tok Token) error
GetToken(client, email string) (Token, error)
DeleteToken(client, email string) error
ListTokens() ([]Token, error)
}
Store defines the interface for token storage.
func OpenDefault ¶
OpenDefault opens the keyring store with auto-detected backend.
func OpenWithBackend ¶
OpenWithBackend opens the keyring store with a specific backend.
type Token ¶
type Token struct {
Client string `json:"client,omitempty"`
Email string `json:"email"`
AccountID int64 `json:"account_id"`
Scopes []string `json:"scopes,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
RefreshToken string `json:"-"` // NEVER serialize to JSON/logs
}
Token represents stored authentication information. RefreshToken is stored separately in the keyring and never serialized to JSON.
type TokenSource ¶
type TokenSource struct {
// contains filtered or unexported fields
}
TokenSource provides OAuth2 tokens with lazy refresh on 401. Access tokens are kept in memory only; refresh tokens are stored in keyring.
func NewTokenSource ¶
func NewTokenSource(store Store, client, email string, cfg *oauth2.Config) *TokenSource
NewTokenSource creates a new TokenSource for the given client and email.
func (*TokenSource) Invalidate ¶
func (ts *TokenSource) Invalidate()
Invalidate marks the current access token as invalid. Forces a refresh on the next Token() call. Call this on 401 responses.