auth

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jan 8, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package auth provides OAuth 2.0 authentication with PKCE flow and JWT token management for AINative Code.

This package implements:

  • OAuth 2.0 Authorization Code Flow with PKCE (RFC 7636)
  • JWT token parsing and validation (RS256)
  • Secure token storage using OS keychain
  • Local callback server for OAuth redirect

OAuth 2.0 PKCE Flow

The PKCE (Proof Key for Code Exchange) flow prevents authorization code interception attacks by generating a code verifier and challenge:

  1. Generate PKCE parameters (code verifier, code challenge, state)
  2. Build authorization URL with challenge
  3. Open browser for user authorization
  4. Start local callback server
  5. Receive authorization code via redirect
  6. Validate state parameter (CSRF protection)
  7. Exchange code + verifier for tokens
  8. Parse and validate JWT tokens
  9. Store tokens in OS keychain

Example Usage

client := auth.NewClient(
    auth.WithClientID("ainative-code-cli"),
    auth.WithAuthEndpoint("https://auth.ainative.studio/oauth/authorize"),
    auth.WithTokenEndpoint("https://auth.ainative.studio/oauth/token"),
)
defer client.Close()

tokens, err := client.Authorize(ctx)
if err != nil {
    log.Fatal(err)
}

Security Measures

The package implements multiple security measures:

  • PKCE prevents code interception (RFC 7636)
  • State parameter prevents CSRF attacks
  • RS256 signature verification prevents token forgery
  • OS keychain provides encrypted token storage
  • Single-use callback server prevents replay attacks

Token Management

JWT tokens are parsed and validated with:

  • RS256 signature verification using public key
  • Expiry checking (access: 24h, refresh: 7d)
  • Issuer validation ("ainative-auth")
  • Audience validation ("ainative-code")

PKCE Generation

PKCE parameters are generated using cryptographically secure random:

  • Code verifier: 128 characters (A-Z, a-z, 0-9, -, ., _, ~)
  • Code challenge: SHA-256 hash of verifier, base64url encoded
  • Challenge method: "S256"

Architecture

The package follows the Provider Interface pattern from TASK-023, using functional options for flexible configuration and thread-safe operations with context-based cancellation support.

For detailed architecture documentation, see internal/auth/ARCHITECTURE.md.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrPKCEGeneration indicates failure to generate PKCE parameters.
	// This typically occurs when the cryptographic random number generator fails.
	ErrPKCEGeneration = errors.New("failed to generate PKCE parameters")

	// ErrInvalidCodeVerifier indicates the code verifier format is invalid.
	// Code verifiers must be 43-128 characters using [A-Z]/[a-z]/[0-9]/-/./\_/~
	ErrInvalidCodeVerifier = errors.New("invalid code verifier format")

	// ErrInvalidCodeChallenge indicates the code challenge is invalid.
	// Code challenges must be base64url-encoded SHA-256 hashes without padding.
	ErrInvalidCodeChallenge = errors.New("invalid code challenge")
)

PKCE Errors

Errors related to PKCE (Proof Key for Code Exchange) parameter generation and validation.

View Source
var (
	// ErrInvalidState indicates the state parameter validation failed.
	// This is a critical security error indicating a potential CSRF attack.
	ErrInvalidState = errors.New("invalid state parameter (CSRF check failed)")

	// ErrCodeExchangeFailed indicates the authorization code exchange failed.
	// This occurs when the token endpoint rejects the authorization code.
	ErrCodeExchangeFailed = errors.New("failed to exchange code for token")

	// ErrAuthorizationDenied indicates the user denied the authorization request.
	ErrAuthorizationDenied = errors.New("user denied authorization")

	// ErrAuthorizationTimeout indicates the authorization process timed out.
	// This occurs when the user doesn't complete authorization within the timeout period.
	ErrAuthorizationTimeout = errors.New("authorization timeout")

	// ErrMissingAuthorizationCode indicates no authorization code was received.
	ErrMissingAuthorizationCode = errors.New("missing authorization code in callback")
)

OAuth Flow Errors

Errors related to the OAuth 2.0 authorization code flow.

View Source
var (
	// ErrTokenExpired indicates the token has expired.
	// Check the "exp" claim and refresh the token if needed.
	ErrTokenExpired = errors.New("token has expired")

	// ErrInvalidSignature indicates the JWT signature verification failed.
	// This is a critical security error indicating potential token forgery.
	ErrInvalidSignature = errors.New("invalid token signature")

	// ErrInvalidClaims indicates required JWT claims are missing or invalid.
	// This includes validation of iss, aud, sub, exp claims.
	ErrInvalidClaims = errors.New("invalid token claims")

	// ErrInvalidIssuer indicates the token issuer doesn't match expected value.
	// Expected issuer: "ainative-auth"
	ErrInvalidIssuer = errors.New("invalid token issuer")

	// ErrInvalidAudience indicates the token audience doesn't match expected value.
	// Expected audience: "ainative-code"
	ErrInvalidAudience = errors.New("invalid token audience")

	// ErrTokenParseFailed indicates JWT token parsing failed.
	// This occurs when the token format is invalid or malformed.
	ErrTokenParseFailed = errors.New("failed to parse JWT token")

	// ErrMissingPublicKey indicates the RSA public key for signature verification is missing.
	ErrMissingPublicKey = errors.New("missing RSA public key for token verification")
)

JWT Token Errors

Errors related to JWT token parsing, validation, and verification.

View Source
var (
	// ErrKeychainAccess indicates keychain access was denied.
	// This may occur if the user denies keychain access or permissions are insufficient.
	ErrKeychainAccess = errors.New("keychain access denied")

	// ErrKeychainStore indicates storing data in the keychain failed.
	ErrKeychainStore = errors.New("failed to store data in keychain")

	// ErrKeychainRetrieve indicates retrieving data from the keychain failed.
	ErrKeychainRetrieve = errors.New("failed to retrieve data from keychain")

	// ErrKeychainDelete indicates deleting data from the keychain failed.
	ErrKeychainDelete = errors.New("failed to delete data from keychain")

	// ErrKeychainNotFound indicates the requested item was not found in the keychain.
	ErrKeychainNotFound = errors.New("item not found in keychain")
)

Keychain Storage Errors

Errors related to OS keychain operations for secure token storage.

View Source
var (
	// ErrCallbackServerStart indicates the callback server failed to start.
	// This typically occurs when the port is already in use.
	ErrCallbackServerStart = errors.New("failed to start callback server")

	// ErrCallbackServerShutdown indicates the callback server failed to shutdown gracefully.
	ErrCallbackServerShutdown = errors.New("failed to shutdown callback server")

	// ErrCallbackTimeout indicates the callback was not received within the timeout period.
	ErrCallbackTimeout = errors.New("callback timeout")

	// ErrCallbackError indicates the callback contained an error response.
	ErrCallbackError = errors.New("callback error response received")
)

Callback Server Errors

Errors related to the local OAuth callback server.

View Source
var (
	// ErrHTTPRequest indicates an HTTP request failed.
	ErrHTTPRequest = errors.New("HTTP request failed")

	// ErrHTTPResponse indicates the HTTP response status is not successful (not 2xx).
	ErrHTTPResponse = errors.New("HTTP response error")

	// ErrHTTPTimeout indicates the HTTP request timed out.
	ErrHTTPTimeout = errors.New("HTTP request timeout")

	// ErrResponseParseFailed indicates parsing the HTTP response body failed.
	ErrResponseParseFailed = errors.New("failed to parse HTTP response")
)

HTTP Client Errors

Errors related to HTTP requests to OAuth endpoints.

View Source
var (
	// ErrMissingClientID indicates the OAuth client ID is missing.
	ErrMissingClientID = errors.New("missing OAuth client ID")

	// ErrMissingAuthEndpoint indicates the authorization endpoint URL is missing.
	ErrMissingAuthEndpoint = errors.New("missing authorization endpoint")

	// ErrMissingTokenEndpoint indicates the token endpoint URL is missing.
	ErrMissingTokenEndpoint = errors.New("missing token endpoint")

	// ErrMissingRedirectURI indicates the redirect URI is missing.
	ErrMissingRedirectURI = errors.New("missing redirect URI")

	// ErrInvalidURL indicates a URL is malformed or invalid.
	ErrInvalidURL = errors.New("invalid URL")

	// ErrInvalidPort indicates the callback port is invalid.
	ErrInvalidPort = errors.New("invalid callback port")
)

Configuration Errors

Errors related to client configuration and validation.

View Source
var (
	// ErrEmptyUserID indicates the user ID is empty.
	ErrEmptyUserID = errors.New("empty user ID")

	// ErrEmptySessionID indicates the session ID is empty.
	ErrEmptySessionID = errors.New("empty session ID")

	// ErrNilContext indicates a nil context was provided.
	ErrNilContext = errors.New("nil context provided")

	// ErrNilRequest indicates a nil request was provided.
	ErrNilRequest = errors.New("nil request provided")
)

Validation Errors

Errors related to parameter validation.

View Source
var (
	// ErrBrowserOpen indicates opening the browser failed.
	// This may occur if no browser is available or the command fails.
	ErrBrowserOpen = errors.New("failed to open browser")
)

Browser Errors

Errors related to opening the browser for user authorization.

Functions

func ValidateCodeChallenge

func ValidateCodeChallenge(challenge string) error

ValidateCodeChallenge checks if a code challenge is valid.

Returns ErrInvalidCodeChallenge if:

  • Not a valid base64url-encoded string
  • Length doesn't match SHA-256 output (43 characters when base64url-encoded)

Note: This performs format validation only. To verify a challenge matches a verifier, use generateCodeChallenge(verifier) and compare the result.

func ValidateCodeVerifier

func ValidateCodeVerifier(verifier string) error

ValidateCodeVerifier checks if a code verifier meets RFC 7636 requirements.

Returns ErrInvalidCodeVerifier if:

  • Length is not between 43-128 characters
  • Contains characters outside allowed set

This function can be used to validate code verifiers before using them in token exchange requests.

Types

type AccessToken

type AccessToken struct {
	// Raw is the original JWT token string
	Raw string

	// ExpiresAt is when the token expires (from "exp" claim)
	ExpiresAt time.Time

	// UserID is the unique user identifier (from "sub" claim)
	UserID string

	// Email is the user's email address (from "email" claim)
	Email string

	// Roles are the user's roles (from "roles" claim)
	Roles []string

	// Issuer is the token issuer (from "iss" claim, should be "ainative-auth")
	Issuer string

	// Audience is the intended audience (from "aud" claim, should be "ainative-code")
	Audience string
}

AccessToken represents a parsed and validated JWT access token.

Access tokens are short-lived (24 hours) and used to authenticate API requests to AINative services.

func ParseAccessToken

func ParseAccessToken(tokenString string, publicKey *rsa.PublicKey) (*AccessToken, error)

ParseAccessToken parses and validates a JWT access token.

This function:

  • Parses the JWT token string
  • Verifies the RS256 signature using the provided public key
  • Validates standard claims (iss, aud, sub, exp)
  • Extracts custom claims (email, roles)
  • Returns a populated AccessToken struct

The token must:

  • Have a valid RS256 signature
  • Not be expired (exp claim)
  • Have issuer = "ainative-auth"
  • Have audience = "ainative-code"
  • Contain required claims: sub, email

Returns:

  • ErrMissingPublicKey if publicKey is nil
  • ErrTokenParseFailed if token parsing fails
  • ErrInvalidSignature if signature verification fails
  • ErrInvalidClaims if required claims are missing or invalid
  • ErrInvalidIssuer if issuer doesn't match "ainative-auth"
  • ErrInvalidAudience if audience doesn't match "ainative-code"
  • ErrTokenExpired if token has expired

Example:

token, err := ParseAccessToken(tokenString, publicKey)
if err != nil {
    return fmt.Errorf("invalid access token: %w", err)
}
fmt.Printf("Authenticated user: %s\n", token.Email)

func (*AccessToken) IsExpired

func (t *AccessToken) IsExpired() bool

IsExpired returns true if the access token has expired.

func (*AccessToken) IsValid

func (t *AccessToken) IsValid() bool

IsValid performs basic validation checks on the access token.

Returns true if:

  • Token is not expired
  • Issuer is "ainative-auth"
  • Audience is "ainative-code"
  • UserID is not empty

type CallbackResult

type CallbackResult struct {
	// Code is the authorization code to exchange for tokens
	Code string

	// State is the CSRF token that must match the original request
	State string

	// Error is an error code if authorization failed
	Error string

	// ErrorDescription is a human-readable error description
	ErrorDescription string
}

CallbackResult contains the result of the OAuth callback.

After the user authorizes the application, the authorization server redirects to the callback URL with the authorization code and state.

func (*CallbackResult) HasError

func (r *CallbackResult) HasError() bool

HasError returns true if the callback contains an error.

type Client

type Client interface {
	// Authenticate initiates the OAuth 2.0 Authorization Code Flow with PKCE.
	//
	// This method:
	//   1. Generates PKCE parameters (code verifier, challenge, state)
	//   2. Builds authorization URL with required parameters
	//   3. Opens the user's browser to the authorization URL
	//   4. Starts local callback server to receive authorization code
	//   5. Waits for user to complete authorization
	//   6. Exchanges authorization code for tokens
	//   7. Stores tokens securely in OS keychain
	//   8. Returns the token pair
	//
	// The authorization flow respects context cancellation and timeouts.
	// Default timeout is 5 minutes, but can be configured via options.
	//
	// Returns:
	//   - ErrAuthorizationDenied if user denies authorization
	//   - ErrAuthorizationTimeout if user doesn't complete flow in time
	//   - ErrInvalidState if state parameter doesn't match (CSRF attack)
	//   - ErrCodeExchangeFailed if token endpoint rejects the code
	//   - ErrCallbackServerStart if local server fails to start
	//   - ErrBrowserOpen if browser cannot be opened
	//
	// Example:
	//
	//	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
	//	defer cancel()
	//
	//	tokens, err := client.Authenticate(ctx)
	//	if err != nil {
	//	    return fmt.Errorf("authentication failed: %w", err)
	//	}
	//	fmt.Printf("Authenticated as: %s\n", tokens.AccessToken.Email)
	Authenticate(ctx context.Context) (*TokenPair, error)

	// RefreshToken exchanges a refresh token for a new access token.
	//
	// This method:
	//   1. Sends refresh token to token endpoint
	//   2. Receives new access token (and optionally new refresh token)
	//   3. Updates tokens in OS keychain
	//   4. Returns updated token pair
	//
	// If the refresh token is expired or revoked, this method returns an error
	// and the client should re-authenticate using Authenticate().
	//
	// Returns:
	//   - ErrTokenExpired if refresh token has expired
	//   - ErrCodeExchangeFailed if token endpoint rejects refresh token
	//   - ErrHTTPRequest if network request fails
	//   - ErrHTTPResponse if server returns error status
	//
	// Example:
	//
	//	tokens, err := client.GetStoredTokens(ctx)
	//	if err != nil {
	//	    return client.Authenticate(ctx)
	//	}
	//
	//	if tokens.AccessToken.IsExpired() {
	//	    tokens, err = client.RefreshToken(ctx, tokens.RefreshToken)
	//	    if err != nil {
	//	        // Refresh failed, re-authenticate
	//	        return client.Authenticate(ctx)
	//	    }
	//	}
	RefreshToken(ctx context.Context, refreshToken *RefreshToken) (*TokenPair, error)

	// GetStoredTokens retrieves tokens from OS keychain.
	//
	// This method:
	//   1. Reads token data from secure keychain storage
	//   2. Parses and validates JWT tokens
	//   3. Returns token pair if found and valid
	//
	// The returned tokens may be expired. Callers should check
	// token.AccessToken.IsExpired() and refresh if needed.
	//
	// Returns:
	//   - ErrKeychainNotFound if no tokens are stored
	//   - ErrKeychainAccess if keychain access is denied
	//   - ErrKeychainRetrieve if reading from keychain fails
	//   - ErrTokenParseFailed if stored token data is corrupted
	//
	// Example:
	//
	//	tokens, err := client.GetStoredTokens(ctx)
	//	if errors.Is(err, auth.ErrKeychainNotFound) {
	//	    // No stored tokens, authenticate
	//	    return client.Authenticate(ctx)
	//	}
	//	if err != nil {
	//	    return fmt.Errorf("failed to get tokens: %w", err)
	//	}
	GetStoredTokens(ctx context.Context) (*TokenPair, error)

	// StoreTokens saves tokens to OS keychain.
	//
	// This method:
	//   1. Validates token format and expiration
	//   2. Encrypts token data using OS keychain
	//   3. Stores in platform-specific secure storage
	//
	// Tokens are stored with service identifier "ainative-code"
	// and account identifier derived from user ID.
	//
	// Returns:
	//   - ErrKeychainAccess if keychain access is denied
	//   - ErrKeychainStore if writing to keychain fails
	//
	// Example:
	//
	//	tokens, err := client.Authenticate(ctx)
	//	if err != nil {
	//	    return err
	//	}
	//	// Tokens are automatically stored by Authenticate(),
	//	// but you can manually store them if needed:
	//	if err := client.StoreTokens(ctx, tokens); err != nil {
	//	    log.Printf("Failed to store tokens: %v", err)
	//	}
	StoreTokens(ctx context.Context, tokens *TokenPair) error

	// ClearTokens removes tokens from OS keychain.
	//
	// This method:
	//   1. Deletes token data from OS keychain
	//   2. Clears any in-memory token cache
	//
	// Use this method to implement logout functionality.
	//
	// Returns:
	//   - ErrKeychainAccess if keychain access is denied
	//   - ErrKeychainDelete if deletion fails
	//
	// Note: This does NOT revoke tokens on the server. To fully logout,
	// you should also call the server's token revocation endpoint.
	//
	// Example:
	//
	//	if err := client.ClearTokens(ctx); err != nil {
	//	    log.Printf("Failed to clear tokens: %v", err)
	//	}
	ClearTokens(ctx context.Context) error

	// ValidateToken checks if an access token is valid and not expired.
	//
	// This method:
	//   1. Checks token expiration time
	//   2. Verifies JWT signature using public key
	//   3. Validates standard claims (iss, aud, sub, exp)
	//   4. Optionally performs introspection at server (if configured)
	//
	// Returns true if token is valid and can be used for API requests.
	// Returns false if token is expired, has invalid signature, or fails
	// server-side validation.
	//
	// This is a convenience method. Callers can also check
	// token.IsExpired() directly for simple expiration checks.
	//
	// Example:
	//
	//	tokens, _ := client.GetStoredTokens(ctx)
	//	if !client.ValidateToken(ctx, tokens.AccessToken) {
	//	    // Token invalid, refresh or re-authenticate
	//	    tokens, err = client.RefreshToken(ctx, tokens.RefreshToken)
	//	}
	ValidateToken(ctx context.Context, token *AccessToken) bool
}

Client defines the interface for OAuth 2.0 authentication operations.

This interface abstracts the OAuth 2.0 Authorization Code Flow with PKCE, providing methods for user authentication, token management, and secure storage integration.

Implementation Requirements:

  • Thread-safe operations
  • Context-aware for cancellation and timeouts
  • Secure token storage via OS keychain
  • Automatic token refresh when possible
  • PKCE (RFC 7636) support for all authorization flows

Typical Usage Flow:

// 1. Create client
client, err := NewClient(config, options...)

// 2. Check for existing valid tokens
tokens, err := client.GetStoredTokens(ctx)
if err == nil && tokens.IsValid() {
    return tokens, nil
}

// 3. Authenticate user if needed
tokens, err = client.Authenticate(ctx)

// 4. Use tokens for API requests
// If access token expires, refresh it
if tokens.AccessToken.IsExpired() {
    tokens, err = client.RefreshToken(ctx, tokens.RefreshToken)
}

type ClientOptions

type ClientOptions struct {
	// ClientID is the OAuth 2.0 client identifier
	ClientID string

	// AuthEndpoint is the authorization endpoint URL
	// Default: https://auth.ainative.studio/oauth/authorize
	AuthEndpoint string

	// TokenEndpoint is the token endpoint URL
	// Default: https://auth.ainative.studio/oauth/token
	TokenEndpoint string

	// RedirectURI is the callback URL for OAuth redirect
	// Default: http://localhost:8080/callback
	RedirectURI string

	// Scopes are the OAuth 2.0 scopes to request
	// Default: ["read", "write", "offline_access"]
	Scopes []string

	// Timeout is the timeout for HTTP requests
	// Default: 30 seconds
	Timeout time.Duration

	// PublicKey is the RSA public key for JWT signature verification
	// This should be fetched from the auth server's JWKS endpoint
	PublicKey *rsa.PublicKey

	// CallbackPort is the port for the local callback server
	// Default: 8080
	CallbackPort int
}

ClientOptions contains configuration for the OAuth client.

Use functional options (WithXxx functions) to configure the client:

client := auth.NewClient(
    auth.WithClientID("ainative-code-cli"),
    auth.WithAuthEndpoint("https://auth.ainative.studio/oauth/authorize"),
    auth.WithTokenEndpoint("https://auth.ainative.studio/oauth/token"),
)

func DefaultClientOptions

func DefaultClientOptions() *ClientOptions

DefaultClientOptions returns the default client options.

type Config

type Config = ClientOptions

Config is an alias for ClientOptions for backward compatibility.

type PKCEParams

type PKCEParams struct {
	// CodeVerifier is a cryptographically random string (43-128 characters)
	// using the characters [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"
	CodeVerifier string

	// CodeChallenge is the SHA-256 hash of CodeVerifier, base64url-encoded
	// without padding (RFC 4648 Section 5)
	CodeChallenge string

	// Method is the code challenge method, always "S256" for SHA-256
	Method string

	// State is a CSRF token that must be validated in the callback
	State string
}

PKCEParams contains parameters for OAuth 2.0 PKCE flow (RFC 7636).

PKCE (Proof Key for Code Exchange) prevents authorization code interception attacks by requiring the client to prove possession of a code verifier that corresponds to the code challenge sent in the authorization request.

func GeneratePKCE

func GeneratePKCE() (*PKCEParams, error)

GeneratePKCE creates PKCE parameters for OAuth 2.0 PKCE flow.

This function generates:

  • Code verifier: 128-character cryptographically random string
  • Code challenge: SHA-256 hash of verifier, base64url-encoded (no padding)
  • Challenge method: "S256"
  • State: 32-byte cryptographically random CSRF token, base64url-encoded

The PKCE flow prevents authorization code interception attacks by requiring the client to prove possession of the code verifier during token exchange.

Returns ErrPKCEGeneration if cryptographic random generation fails.

Example:

pkce, err := GeneratePKCE()
if err != nil {
    return fmt.Errorf("PKCE generation failed: %w", err)
}
// Use pkce.CodeChallenge in authorization URL
// Use pkce.CodeVerifier in token exchange
// Use pkce.State for CSRF validation

type RefreshToken

type RefreshToken struct {
	// Raw is the original JWT token string
	Raw string

	// ExpiresAt is when the token expires (from "exp" claim)
	ExpiresAt time.Time

	// UserID is the unique user identifier (from "sub" claim)
	UserID string

	// SessionID is the session identifier (from "session_id" claim)
	SessionID string

	// Issuer is the token issuer (from "iss" claim, should be "ainative-auth")
	Issuer string

	// Audience is the intended audience (from "aud" claim, should be "ainative-code")
	Audience string
}

RefreshToken represents a parsed and validated JWT refresh token.

Refresh tokens are long-lived (7 days) and used to obtain new access tokens without re-authentication.

func ParseRefreshToken

func ParseRefreshToken(tokenString string, publicKey *rsa.PublicKey) (*RefreshToken, error)

ParseRefreshToken parses and validates a JWT refresh token.

This function:

  • Parses the JWT token string
  • Verifies the RS256 signature using the provided public key
  • Validates standard claims (iss, aud, sub, exp)
  • Extracts custom claims (session_id)
  • Returns a populated RefreshToken struct

The token must:

  • Have a valid RS256 signature
  • Not be expired (exp claim)
  • Have issuer = "ainative-auth"
  • Have audience = "ainative-code"
  • Contain required claims: sub, session_id

Returns:

  • ErrMissingPublicKey if publicKey is nil
  • ErrTokenParseFailed if token parsing fails
  • ErrInvalidSignature if signature verification fails
  • ErrInvalidClaims if required claims are missing or invalid
  • ErrInvalidIssuer if issuer doesn't match "ainative-auth"
  • ErrInvalidAudience if audience doesn't match "ainative-code"
  • ErrTokenExpired if token has expired

Example:

token, err := ParseRefreshToken(tokenString, publicKey)
if err != nil {
    return fmt.Errorf("invalid refresh token: %w", err)
}
fmt.Printf("Session ID: %s\n", token.SessionID)

func (*RefreshToken) IsExpired

func (t *RefreshToken) IsExpired() bool

IsExpired returns true if the refresh token has expired.

func (*RefreshToken) IsValid

func (t *RefreshToken) IsValid() bool

IsValid performs basic validation checks on the refresh token.

Returns true if:

  • Token is not expired
  • Issuer is "ainative-auth"
  • Audience is "ainative-code"
  • UserID is not empty
  • SessionID is not empty

type TokenPair

type TokenPair struct {
	// AccessToken is the JWT access token used for API authentication.
	AccessToken *AccessToken

	// RefreshToken is the JWT refresh token used to obtain new access tokens.
	RefreshToken *RefreshToken

	// ReceivedAt is when this token pair was received from the server.
	// Used for calculating token age and refresh timing.
	ReceivedAt time.Time
}

TokenPair represents a pair of access and refresh tokens.

Both tokens are JWT tokens signed with RS256. The access token is short-lived (typically 1 hour) and used for API authentication. The refresh token is long-lived (typically 30 days) and used to obtain new access tokens without re-authentication.

func (*TokenPair) IsValid

func (tp *TokenPair) IsValid() bool

IsValid checks if the token pair is valid and usable.

A token pair is considered valid if:

  • Both access and refresh tokens are non-nil
  • Access token is not expired (or expires in more than 1 minute)
  • Refresh token is not expired

This method provides a quick check for token validity. For more detailed validation, use Client.ValidateToken().

func (*TokenPair) NeedsRefresh

func (tp *TokenPair) NeedsRefresh() bool

NeedsRefresh checks if the access token should be refreshed.

Returns true if the access token:

  • Is expired, OR
  • Will expire within the next 5 minutes

This provides a safety buffer to avoid using tokens that might expire during a long-running API request.

type TokenResponse

type TokenResponse struct {
	// AccessToken is the parsed access token
	AccessToken *AccessToken

	// RefreshToken is the parsed refresh token (may be nil)
	RefreshToken *RefreshToken

	// ExpiresIn is the number of seconds until access token expires
	ExpiresIn int64

	// TokenType is the type of token, always "Bearer" for JWT
	TokenType string

	// Scope is the granted scopes (space-separated string)
	Scope string
}

TokenResponse contains the OAuth 2.0 token response.

This is returned by the token endpoint after successful code exchange or refresh token usage.

Directories

Path Synopsis
Package jwt provides JSON Web Token (JWT) functionality for authentication.
Package jwt provides JSON Web Token (JWT) functionality for authentication.
Package keychain provides cross-platform secure credential storage.
Package keychain provides cross-platform secure credential storage.
Package local provides local authentication for offline operation.
Package local provides local authentication for offline operation.
Package oauth provides OAuth 2.0 authentication with PKCE (Proof Key for Code Exchange).
Package oauth provides OAuth 2.0 authentication with PKCE (Proof Key for Code Exchange).
Package refresh provides automatic token refresh functionality.
Package refresh provides automatic token refresh functionality.

Jump to

Keyboard shortcuts

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