Documentation
¶
Overview ¶
Package client provides client-side authentication utilities for oneauth. It includes credential storage, automatic token refresh, and HTTP client helpers.
Index ¶
- Constants
- type ASMetadata
- type AuthClient
- func (c *AuthClient) ClientCredentialsToken(clientID, clientSecret string, scopes []string) (*ServerCredential, error)
- func (c *AuthClient) GetCredential() (*ServerCredential, error)
- func (c *AuthClient) GetToken() (string, error)
- func (c *AuthClient) HTTPClient() *http.Client
- func (c *AuthClient) IsLoggedIn() bool
- func (c *AuthClient) Login(username, password, scope string) (*ServerCredential, error)
- func (c *AuthClient) LoginWithBrowser(cfg BrowserLoginConfig) (*ServerCredential, error)
- func (c *AuthClient) Logout() error
- func (c *AuthClient) ServerURL() string
- type AuthTransport
- type BrowserLoginConfig
- type ClientOption
- type CredentialStore
- type DiscoveryOption
- type OAuth2TokenRequest
- type OAuth2TokenResponse
- type ServerCredential
Constants ¶
const RefreshThreshold = 5 * time.Minute
RefreshThreshold is how long before expiry to proactively refresh
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ASMetadata ¶ added in v0.0.56
type ASMetadata struct {
// Required
Issuer string `json:"issuer"`
TokenEndpoint string `json:"token_endpoint"`
// Recommended
AuthorizationEndpoint string `json:"authorization_endpoint,omitempty"`
JWKSURI string `json:"jwks_uri,omitempty"`
// Optional
RegistrationEndpoint string `json:"registration_endpoint,omitempty"`
IntrospectionEndpoint string `json:"introspection_endpoint,omitempty"`
RevocationEndpoint string `json:"revocation_endpoint,omitempty"`
UserinfoEndpoint string `json:"userinfo_endpoint,omitempty"`
// Supported features
ScopesSupported []string `json:"scopes_supported,omitempty"`
ResponseTypesSupported []string `json:"response_types_supported,omitempty"`
GrantTypesSupported []string `json:"grant_types_supported,omitempty"`
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported,omitempty"`
TokenEndpointAuthMethods []string `json:"token_endpoint_auth_methods_supported,omitempty"`
}
ASMetadata holds OAuth 2.0 Authorization Server metadata discovered from a well-known endpoint. Fields follow RFC 8414 and OpenID Connect Discovery 1.0.
See: https://www.rfc-editor.org/rfc/rfc8414#section-2
func DiscoverAS ¶ added in v0.0.56
func DiscoverAS(issuerURL string, opts ...DiscoveryOption) (*ASMetadata, error)
DiscoverAS fetches OAuth Authorization Server metadata from well-known endpoints.
It tries the following URLs in order (per RFC 8414 + OIDC Discovery):
For issuer "https://auth.example.com" (no path):
- https://auth.example.com/.well-known/oauth-authorization-server
- https://auth.example.com/.well-known/openid-configuration
For issuer "https://auth.example.com/tenant1" (with path):
- https://auth.example.com/.well-known/oauth-authorization-server/tenant1
- https://auth.example.com/tenant1/.well-known/openid-configuration
Returns the first successful response. Returns an error if all attempts fail.
type AuthClient ¶
type AuthClient struct {
// contains filtered or unexported fields
}
AuthClient is an HTTP client with automatic token management
func NewAuthClient ¶
func NewAuthClient(serverURL string, store CredentialStore, opts ...ClientOption) *AuthClient
NewAuthClient creates a new authenticated HTTP client for a server
func (*AuthClient) ClientCredentialsToken ¶ added in v0.0.56
func (c *AuthClient) ClientCredentialsToken(clientID, clientSecret string, scopes []string) (*ServerCredential, error)
ClientCredentialsToken authenticates using the client_credentials grant (RFC 6749 §4.4). This is for machine-to-machine authentication — no user context, no refresh token. The access token is stored in the credential store for subsequent API calls.
func (*AuthClient) GetCredential ¶
func (c *AuthClient) GetCredential() (*ServerCredential, error)
GetCredential returns the stored credential for this server
func (*AuthClient) GetToken ¶
func (c *AuthClient) GetToken() (string, error)
GetToken returns the current access token, refreshing if needed
func (*AuthClient) HTTPClient ¶
func (c *AuthClient) HTTPClient() *http.Client
HTTPClient returns the underlying HTTP client with auth handling
func (*AuthClient) IsLoggedIn ¶
func (c *AuthClient) IsLoggedIn() bool
IsLoggedIn returns true if there is a valid (non-expired) credential
func (*AuthClient) Login ¶
func (c *AuthClient) Login(username, password, scope string) (*ServerCredential, error)
Login authenticates with username/password and stores the credential
func (*AuthClient) LoginWithBrowser ¶ added in v0.0.56
func (c *AuthClient) LoginWithBrowser(cfg BrowserLoginConfig) (*ServerCredential, error)
LoginWithBrowser performs an OAuth 2.0 authorization code flow with PKCE for CLI/headless clients (RFC 8252). It:
- Generates PKCE verifier + challenge
- Generates a random state parameter for CSRF protection
- Starts a temporary loopback HTTP server to catch the redirect
- Opens the user's browser to the authorization URL
- Waits for the callback with the authorization code
- Validates the state parameter
- Exchanges the code for tokens using the code_verifier
- Stores the credential via the AuthClient's CredentialStore
See: https://www.rfc-editor.org/rfc/rfc8252 (OAuth 2.0 for Native Apps) See: https://www.rfc-editor.org/rfc/rfc7636 (PKCE)
func (*AuthClient) Logout ¶
func (c *AuthClient) Logout() error
Logout removes the credential for this server
func (*AuthClient) ServerURL ¶
func (c *AuthClient) ServerURL() string
ServerURL returns the server URL this client is configured for
type AuthTransport ¶
type AuthTransport struct {
Base http.RoundTripper
Token string
}
AuthTransport wraps an http.RoundTripper to add Authorization headers
func NewAuthTransport ¶
func NewAuthTransport(token string) *AuthTransport
NewAuthTransport creates an AuthTransport with the given token
func NewAuthTransportWithBase ¶
func NewAuthTransportWithBase(base http.RoundTripper, token string) *AuthTransport
NewAuthTransportWithBase creates an AuthTransport with a custom base transport
type BrowserLoginConfig ¶ added in v0.0.56
type BrowserLoginConfig struct {
// AuthorizationEndpoint is the AS authorization URL.
// If empty, auto-discovered via DiscoverAS(serverURL) using the
// AuthClient's server URL.
AuthorizationEndpoint string
// TokenEndpoint is the AS token URL for code exchange.
// If empty, uses the AuthClient's configured tokenEndpoint.
TokenEndpoint string
// ClientID identifies this client to the authorization server.
// Required.
ClientID string
// Scopes to request (e.g., []string{"openid", "read", "write"}).
Scopes []string
// CallbackPort is the port for the loopback redirect server.
// If 0, a random available port is chosen.
CallbackPort int
// Timeout for the entire flow (waiting for user to complete browser login).
// Defaults to 5 minutes.
Timeout time.Duration
// OpenBrowser is called to open the authorization URL in the user's browser.
// If nil, uses the platform default (open/xdg-open/start).
// Set to a custom function for testing or headless environments.
OpenBrowser func(url string) error
// HTTPClient is used for the token exchange request.
// If nil, uses http.DefaultClient.
HTTPClient *http.Client
}
BrowserLoginConfig configures the authorization code + PKCE flow for CLI and headless clients.
type ClientOption ¶
type ClientOption func(*AuthClient)
ClientOption configures an AuthClient
func WithHTTPClient ¶
func WithHTTPClient(client *http.Client) ClientOption
WithHTTPClient sets a custom base HTTP client (for timeouts, TLS config, etc.) The transport from this client will be wrapped with auth handling.
func WithTokenEndpoint ¶
func WithTokenEndpoint(path string) ClientOption
WithTokenEndpoint sets a custom token endpoint path
func WithTransport ¶
func WithTransport(transport http.RoundTripper) ClientOption
WithTransport sets a custom base transport (for connection pooling, proxies, etc.)
type CredentialStore ¶
type CredentialStore interface {
// GetCredential retrieves a credential for a server URL
// Returns nil, nil if no credential exists for the server
GetCredential(serverURL string) (*ServerCredential, error)
// SetCredential stores a credential for a server URL
SetCredential(serverURL string, cred *ServerCredential) error
// RemoveCredential removes a credential for a server URL
RemoveCredential(serverURL string) error
// ListServers returns all server URLs with stored credentials
ListServers() ([]string, error)
// Save persists any pending changes (for stores that batch writes)
Save() error
}
CredentialStore defines the interface for storing and retrieving credentials
type DiscoveryOption ¶ added in v0.0.56
type DiscoveryOption func(*discoveryConfig)
DiscoveryOption configures the discovery request.
func WithHTTPClientForDiscovery ¶ added in v0.0.56
func WithHTTPClientForDiscovery(client *http.Client) DiscoveryOption
WithHTTPClientForDiscovery sets a custom HTTP client for the discovery request. Useful for testing (httptest) and custom TLS configuration.
type OAuth2TokenRequest ¶
type OAuth2TokenRequest struct {
GrantType string `json:"grant_type"`
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
RefreshToken string `json:"refresh_token,omitempty"`
Scope string `json:"scope,omitempty"`
ClientID string `json:"client_id,omitempty"`
ClientSecret string `json:"client_secret,omitempty"`
Code string `json:"code,omitempty"` // For authorization_code grant
CodeVerifier string `json:"code_verifier,omitempty"` // PKCE verifier for authorization_code grant
RedirectURI string `json:"redirect_uri,omitempty"` // Redirect URI for authorization_code grant
}
OAuth2TokenRequest is the request body for token endpoint
type OAuth2TokenResponse ¶
type OAuth2TokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int64 `json:"expires_in"`
RefreshToken string `json:"refresh_token,omitempty"`
Scope string `json:"scope,omitempty"`
Error string `json:"error,omitempty"`
ErrorDesc string `json:"error_description,omitempty"`
}
OAuth2TokenResponse is the response from token endpoint
type ServerCredential ¶
type ServerCredential struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token,omitempty"`
TokenType string `json:"token_type,omitempty"`
UserID string `json:"user_id,omitempty"`
UserEmail string `json:"user_email,omitempty"`
Scope string `json:"scope,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
CreatedAt time.Time `json:"created_at"`
}
ServerCredential holds authentication info for a single server
func (*ServerCredential) HasRefreshToken ¶
func (c *ServerCredential) HasRefreshToken() bool
HasRefreshToken returns true if a refresh token is available
func (*ServerCredential) IsExpired ¶
func (c *ServerCredential) IsExpired() bool
IsExpired returns true if the access token has expired
func (*ServerCredential) IsExpiringSoon ¶
func (c *ServerCredential) IsExpiringSoon(within time.Duration) bool
IsExpiringSoon returns true if the token expires within the given duration