oauth

package
v0.1.1 Latest Latest
Warning

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

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

README ΒΆ

OAuth Package - Production-Ready OAuth 2.0 & OpenID Connect

A comprehensive, production-ready OAuth 2.0 and OpenID Connect implementation for Go applications. Part of the Beaver Kit ecosystem.

Features

πŸ” Security First
  • Apple JWT Validation: Full ECDSA/RSA signature verification with public key caching
  • PKCE Support: RFC 7636 compliant implementation (43-128 character verifiers)
  • State Management: Replay attack prevention with immediate session deletion
  • Token Encryption: AES-GCM encryption for sensitive token storage
  • Security Headers: CORS, HSTS, CSP, XSS protection middleware
🌐 Multi-Provider Architecture
  • Built-in Providers: Google, GitHub, Apple, Twitter
  • Custom Provider Support: Easy integration with any OAuth 2.0 provider
  • Dynamic Registration: Add/remove providers at runtime
  • Provider Isolation: Circuit breakers per provider
πŸ’Ύ Advanced Token Management
  • Automatic Refresh: Tokens refreshed before expiration
  • Encrypted Storage: Secure token persistence
  • Bulk Operations: Efficient cleanup of expired tokens
  • User Limits: Configurable token limits per user
  • Cache Integration: Built-in caching support
πŸ›‘οΈ Production Hardening
  • Rate Limiting: Token bucket and sliding window algorithms
  • Circuit Breakers: Protect against cascading failures
  • Health Checks: Liveness, readiness, and component health endpoints
  • Monitoring: Comprehensive metrics collection
  • Request Logging: Structured logging with sensitive data redaction

Installation

go get github.com/gobeaver/beaver-kit/oauth

Quick Start

Basic Usage
package main

import (
    "context"
    "log"
    
    "github.com/gobeaver/beaver-kit/oauth"
)

func main() {
    // Create OAuth configuration
    config := oauth.Config{
        Provider:     "github",
        ClientID:     "your_github_client_id",
        ClientSecret: "your_github_client_secret",
        RedirectURL:  "http://localhost:8080/callback",
    }
    
    // Initialize service
    service, err := oauth.New(config)
    if err != nil {
        log.Fatal(err)
    }
    
    // Use the service for OAuth flows
    // ... see examples below
}
Environment Configuration

Configure via environment variables with the BEAVER_OAUTH_ prefix:

# OAuth Provider Configuration
export BEAVER_OAUTH_PROVIDER=github
export BEAVER_OAUTH_CLIENT_ID=your_client_id
export BEAVER_OAUTH_CLIENT_SECRET=your_client_secret
export BEAVER_OAUTH_REDIRECT_URL=http://localhost:8080/callback

# Optional Configuration
export BEAVER_OAUTH_SCOPES=read:user,user:email
export BEAVER_OAUTH_PKCE_ENABLED=true
export BEAVER_OAUTH_DEBUG=false

Load from environment:

import (
    "github.com/gobeaver/beaver-kit/config"
    "github.com/gobeaver/beaver-kit/oauth"
)

// Load configuration from environment
cfg := &oauth.Config{}
if err := config.LoadFromEnv(cfg); err != nil {
    log.Fatal(err)
}

// Initialize service
service, err := oauth.New(*cfg)
Custom Environment Prefix

Use a custom prefix for multi-tenant applications:

// Use custom prefix
cfg := &oauth.Config{}
if err := config.LoadFromEnv(cfg, config.WithPrefix("MYAPP_")); err != nil {
    log.Fatal(err)
}
// Now reads from MYAPP_OAUTH_CLIENT_ID, etc.

OAuth Flow Implementation

1. Generate Authorization URL
// Start OAuth flow
authURL, state, err := service.GenerateAuthURL("github", true) // true enables PKCE
if err != nil {
    log.Fatal(err)
}

// Store state in session for CSRF protection
// Redirect user to authURL
2. Handle OAuth Callback
func handleCallback(w http.ResponseWriter, r *http.Request) {
    // Handle the OAuth callback
    resp, err := service.HandleCallback(r, "github")
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    
    // Verify state matches (CSRF protection)
    if resp.State != storedState {
        http.Error(w, "Invalid state", http.StatusBadRequest)
        return
    }
    
    // Get user information
    userInfo, err := service.GetUserInfo(context.Background(), "github", resp.Token.AccessToken)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    // User is authenticated!
    log.Printf("User: %s (%s)", userInfo.Name, userInfo.Email)
}
3. Direct Provider Usage
// Use provider directly for more control
provider := oauth.NewGitHub(oauth.ProviderConfig{
    ClientID:     "your_client_id",
    ClientSecret: "your_client_secret",
    RedirectURL:  "http://localhost:8080/callback",
    Scopes:       []string{"read:user", "user:email"},
})

// Generate auth URL with PKCE
pkce, err := oauth.GeneratePKCEChallenge("S256")
if err != nil {
    log.Fatal(err)
}

authURL := provider.GetAuthURL("state_token", pkce)

// After callback, exchange code for token
token, err := provider.Exchange(context.Background(), "auth_code", pkce)
if err != nil {
    log.Fatal(err)
}

// Get user info
userInfo, err := provider.GetUserInfo(context.Background(), token.AccessToken)

PKCE (Proof Key for Code Exchange)

PKCE provides additional security for OAuth flows, especially important for public clients:

// Generate PKCE challenge
pkce, err := oauth.GeneratePKCEChallenge("S256") // or "plain"
if err != nil {
    log.Fatal(err)
}

// Include in authorization URL
authURL := provider.GetAuthURL(state, pkce)

// Include verifier when exchanging code
token, err := provider.Exchange(ctx, code, pkce)

Provider-Specific Features

Google Provider
provider := oauth.NewGoogle(oauth.ProviderConfig{
    ClientID:     "google_client_id",
    ClientSecret: "google_client_secret",
    RedirectURL:  "http://localhost:8080/callback/google",
    Scopes:       []string{"openid", "profile", "email"},
})

// Google-specific features:
// - OpenID Connect support with ID tokens
// - Refresh token support (offline access)
// - PKCE support for enhanced security
// - Perfect for PWA and Flutter apps
Apple Provider
provider, err := oauth.NewApple(oauth.ProviderConfig{
    ClientID:     "com.yourapp.serviceid",
    RedirectURL:  "https://yourapp.com/callback/apple",
    TeamID:       "YOUR_TEAM_ID",
    KeyID:        "YOUR_KEY_ID", 
    PrivateKey:   "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",
    Scopes:       []string{"name", "email"},
})

// Apple-specific features:
// - Requires Apple Developer Program enrollment
// - Uses JWT-based client authentication
// - ID token contains user information (no separate userinfo endpoint)
// - PKCE support for enhanced security
// - form_post response mode for better security
Twitter (X) Provider
provider := oauth.NewTwitter(oauth.ProviderConfig{
    ClientID:     "twitter_client_id",
    ClientSecret: "twitter_client_secret", // Optional for public clients
    RedirectURL:  "https://yourapp.com/callback/twitter",
    Scopes:       []string{"tweet.read", "users.read", "offline.access"},
})

// Twitter-specific features:
// - OAuth 2.0 with PKCE (required for public clients)
// - API v2 support with enhanced user fields
// - No email in user profile (separate permission required)
// - Rich user metadata (followers, tweets, etc.)
GitHub Provider
provider := oauth.NewGitHub(oauth.ProviderConfig{
    ClientID:     "github_client_id",
    ClientSecret: "github_client_secret",
    RedirectURL:  "http://localhost:8080/callback/github",
    Scopes:       []string{"read:user", "user:email"},
})

// GitHub-specific features:
// - Automatic private email retrieval
// - No refresh token support (GitHub tokens don't expire)
// - PKCE support for enhanced security

Token Management

Caching Tokens
// Cache token for later use
err := service.CacheToken(userID, "github", token)

// Retrieve cached token
cachedToken, err := service.GetCachedToken(userID, "github")
if err != nil {
    // Token not found or expired
}

// Clear cached token
err = service.ClearCachedToken(userID, "github")
Token Refresh

For providers that support refresh tokens:

// Refresh access token
newToken, err := provider.RefreshToken(ctx, refreshToken)
if err != nil {
    if err == oauth.ErrNoRefreshToken {
        // Provider doesn't support refresh (e.g., GitHub)
    }
}

Error Handling

The package provides detailed error types for OAuth-specific errors:

// Handle OAuth errors
resp, err := service.HandleCallback(r, "github")
if err != nil {
    var oauthErr *oauth.OAuthError
    if errors.As(err, &oauthErr) {
        log.Printf("OAuth error: %s - %s", oauthErr.Code, oauthErr.Description)
        
        switch oauthErr.Code {
        case "access_denied":
            // User denied access
        case "invalid_grant":
            // Invalid authorization code
        }
    }
}

// Common errors
var (
    ErrInvalidState      // State parameter mismatch (CSRF)
    ErrProviderNotFound  // Unknown provider
    ErrNoRefreshToken    // Provider doesn't support refresh
    ErrSessionNotFound   // Session data not found
    ErrTokenExpired      // Access token expired
)

Configuration Options

Full Configuration
type Config struct {
    // OAuth provider (github, google, etc.)
    Provider string
    
    // OAuth app credentials
    ClientID     string
    ClientSecret string
    RedirectURL  string
    
    // Comma-separated scopes
    Scopes string
    
    // State generation and validation
    State          string
    StateGenerator string // "uuid", "secure", "custom"
    
    // PKCE settings
    PKCEEnabled bool
    PKCEMethod  string // "S256" or "plain"
    
    // Token caching
    TokenCacheDuration time.Duration
    
    // HTTP settings
    HTTPTimeout time.Duration
    
    // Debug mode
    Debug bool
    
    // Custom provider URLs
    AuthURL     string
    TokenURL    string
    UserInfoURL string
}
Provider Configuration
type ProviderConfig struct {
    ClientID     string
    ClientSecret string
    RedirectURL  string
    Scopes       []string
    
    // Optional: Override default URLs
    AuthURL     string
    TokenURL    string
    UserInfoURL string
    
    // Optional: Custom HTTP client
    HTTPClient HTTPClient
    
    // Provider-specific settings
    TeamID     string // Apple
    KeyID      string // Apple
    PrivateKey string // Apple
    APIVersion string // Twitter
}

Testing

The package includes comprehensive tests. To run tests:

go test ./oauth/...

Example test:

func TestOAuthFlow(t *testing.T) {
    // Create test provider
    provider := oauth.NewGitHub(oauth.ProviderConfig{
        ClientID:     "test_id",
        ClientSecret: "test_secret",
        RedirectURL:  "http://test.local/callback",
    })
    
    // Test auth URL generation
    authURL := provider.GetAuthURL("test_state", nil)
    assert.Contains(t, authURL, "client_id=test_id")
    
    // Test PKCE
    pkce, err := oauth.GeneratePKCEChallenge("S256")
    assert.NoError(t, err)
    assert.NotEmpty(t, pkce.Challenge)
}

Security Best Practices

  1. Always use PKCE when available, especially for public clients
  2. Validate state parameter to prevent CSRF attacks
  3. Use HTTPS in production for redirect URLs
  4. Store tokens securely - never in client-side storage
  5. Implement token rotation when refresh tokens are available
  6. Validate scopes returned by the provider
  7. Set appropriate timeouts for HTTP requests

Supported Providers

Provider Status Refresh Token PKCE Support Notes
GitHub βœ… Complete ❌ βœ… Tokens don't expire
Google βœ… Complete βœ… βœ… OpenID Connect, perfect for PWA/Flutter
Apple βœ… Complete βœ… βœ… JWT client auth, ID tokens, iOS apps
Twitter βœ… Complete βœ… βœ… OAuth 2.0 API v2, social integration
Custom πŸ“‹ Planned Varies Varies Generic OAuth 2.0

PWA and Flutter App Integration

The OAuth package is specifically designed to work well with Progressive Web Apps (PWA) and Flutter applications that need secure OAuth flows:

Google OAuth for PWA/Flutter
// Perfect configuration for PWA/Flutter apps
provider := oauth.NewGoogle(oauth.ProviderConfig{
    ClientID:     "your_app.googleusercontent.com",
    ClientSecret: "your_client_secret", // For server-side flow
    RedirectURL:  "https://yourapp.com/auth/callback",
    Scopes:       []string{"openid", "profile", "email"},
})

// Always use PKCE for enhanced security in public clients
pkce, err := oauth.GeneratePKCEChallenge("S256")
if err != nil {
    log.Fatal(err)
}

// Generate authorization URL with PKCE
authURL := provider.GetAuthURL(state, pkce)
// Redirect user or open in browser

// After callback, exchange with PKCE verifier
token, err := provider.Exchange(ctx, authCode, pkce)
if err != nil {
    log.Fatal(err)
}

// Parse ID token for additional user claims
if token.IDToken != "" {
    claims, err := provider.ParseIDToken(token.IDToken)
    if err == nil {
        // Access additional user information from ID token
        fmt.Printf("User email from ID token: %v", claims["email"])
    }
}
Key Benefits for PWA/Flutter:
  1. PKCE Security - Essential for public clients (PWA/mobile apps)
  2. Refresh Tokens - Google provides refresh tokens for offline access
  3. ID Tokens - OpenID Connect support for additional user claims
  4. Cross-Platform - Same backend code works for web and mobile
  5. Secure Flow - Server-side token exchange prevents token exposure
Deployment Considerations:
  • PWA: Use server-side callback URL, handle PKCE on client
  • Flutter: Integrate with deep links for callback handling
  • Security: Always validate state parameter and use HTTPS
  • Tokens: Store refresh tokens securely, never in client storage

Integration with Authentication Systems

The OAuth package is designed to integrate seamlessly with authentication systems and auth flows:

Complete Auth Flow Implementation
package auth

import (
    "context"
    "net/http"
    "time"
    
    "github.com/gobeaver/beaver-kit/oauth"
    "github.com/gobeaver/beaver-kit/krypto"
)

type AuthService struct {
    oauth   *oauth.Service
    users   UserRepository
    tokens  TokenRepository
}

func NewAuthService() *AuthService {
    // Initialize OAuth service
    oauthService := oauth.New()
    config := oauth.Config{
        Providers: map[string]oauth.ProviderConfig{
            "google": {
                ClientID:     os.Getenv("GOOGLE_CLIENT_ID"),
                ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"),
                RedirectURL:  "https://yourapp.com/auth/google/callback",
                Scopes:       []string{"openid", "profile", "email"},
            },
            "github": {
                ClientID:     os.Getenv("GITHUB_CLIENT_ID"),
                ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"),
                RedirectURL:  "https://yourapp.com/auth/github/callback",
                Scopes:       []string{"read:user", "user:email"},
            },
        },
    }
    oauthService.Init(config)
    
    return &AuthService{
        oauth: oauthService,
        users: NewUserRepository(),
        tokens: NewTokenRepository(),
    }
}

// StartOAuthFlow initiates OAuth authentication
func (a *AuthService) StartOAuthFlow(provider string, w http.ResponseWriter, r *http.Request) error {
    // Generate auth URL with PKCE
    authURL, state, err := a.oauth.GenerateAuthURL(provider, true)
    if err != nil {
        return err
    }
    
    // Store state and PKCE in session for callback verification
    session := &AuthSession{
        State:     state,
        Provider:  provider,
        ExpiresAt: time.Now().Add(10 * time.Minute),
    }
    
    // Store session (in production, use Redis/database)
    a.storeSession(r, session)
    
    // Redirect to OAuth provider
    http.Redirect(w, r, authURL, http.StatusFound)
    return nil
}

// HandleOAuthCallback processes OAuth callback and completes authentication
func (a *AuthService) HandleOAuthCallback(provider string, w http.ResponseWriter, r *http.Request) (*User, error) {
    // Retrieve and validate session
    session, err := a.getSession(r)
    if err != nil {
        return nil, fmt.Errorf("invalid session: %w", err)
    }
    
    if session.Provider != provider {
        return nil, fmt.Errorf("provider mismatch")
    }
    
    // Handle OAuth callback
    resp, err := a.oauth.HandleCallback(r, provider)
    if err != nil {
        return nil, fmt.Errorf("oauth callback failed: %w", err)
    }
    
    // Verify state (CSRF protection)
    if resp.State != session.State {
        return nil, fmt.Errorf("state mismatch - possible CSRF attack")
    }
    
    // Get user information from OAuth provider
    userInfo, err := a.oauth.GetUserInfo(r.Context(), provider, resp.Token.AccessToken)
    if err != nil {
        return nil, fmt.Errorf("failed to get user info: %w", err)
    }
    
    // Find or create user in your system
    user, err := a.findOrCreateUser(userInfo, provider)
    if err != nil {
        return nil, fmt.Errorf("failed to create user: %w", err)
    }
    
    // Cache OAuth token for API calls
    err = a.oauth.CacheToken(user.ID, provider, resp.Token)
    if err != nil {
        // Log error but don't fail auth
        log.Printf("Failed to cache OAuth token: %v", err)
    }
    
    // Generate your application's session token
    sessionToken, err := a.generateSessionToken(user)
    if err != nil {
        return nil, fmt.Errorf("failed to generate session: %w", err)
    }
    
    // Set session cookie
    http.SetCookie(w, &http.Cookie{
        Name:     "session",
        Value:    sessionToken,
        Path:     "/",
        HttpOnly: true,
        Secure:   true,
        SameSite: http.SameSiteLaxMode,
        Expires:  time.Now().Add(30 * 24 * time.Hour), // 30 days
    })
    
    return user, nil
}

// findOrCreateUser handles user registration/login
func (a *AuthService) findOrCreateUser(userInfo *oauth.UserInfo, provider string) (*User, error) {
    // Check if user exists by OAuth provider ID
    user, err := a.users.FindByOAuthID(provider, userInfo.ID)
    if err == nil {
        // Existing user - update their info
        user.Email = userInfo.Email
        user.Name = userInfo.Name
        user.Picture = userInfo.Picture
        user.LastLoginAt = time.Now()
        return a.users.Update(user)
    }
    
    // Check if user exists by email
    if userInfo.Email != "" {
        user, err = a.users.FindByEmail(userInfo.Email)
        if err == nil {
            // Link OAuth account to existing user
            oauthAccount := &OAuthAccount{
                UserID:     user.ID,
                Provider:   provider,
                ProviderID: userInfo.ID,
                Email:      userInfo.Email,
            }
            a.users.AddOAuthAccount(oauthAccount)
            return user, nil
        }
    }
    
    // Create new user
    user = &User{
        Email:       userInfo.Email,
        Name:        userInfo.Name,
        Picture:     userInfo.Picture,
        EmailVerified: userInfo.EmailVerified,
        CreatedAt:   time.Now(),
        LastLoginAt: time.Now(),
    }
    
    user, err = a.users.Create(user)
    if err != nil {
        return nil, err
    }
    
    // Create OAuth account link
    oauthAccount := &OAuthAccount{
        UserID:     user.ID,
        Provider:   provider,
        ProviderID: userInfo.ID,
        Email:      userInfo.Email,
    }
    
    err = a.users.AddOAuthAccount(oauthAccount)
    if err != nil {
        return nil, err
    }
    
    return user, nil
}

// generateSessionToken creates a secure session token
func (a *AuthService) generateSessionToken(user *User) (string, error) {
    claims := map[string]interface{}{
        "user_id": user.ID,
        "email":   user.Email,
        "exp":     time.Now().Add(30 * 24 * time.Hour).Unix(),
        "iat":     time.Now().Unix(),
    }
    
    // Use krypto package to generate JWT
    return krypto.GenerateJWT(claims)
}

// Middleware for protecting routes
func (a *AuthService) RequireAuth(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        // Get session token from cookie
        cookie, err := r.Cookie("session")
        if err != nil {
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
            return
        }
        
        // Validate session token
        claims, err := krypto.ValidateJWT(cookie.Value)
        if err != nil {
            http.Error(w, "Invalid session", http.StatusUnauthorized)
            return
        }
        
        // Get user from claims
        userID, ok := claims["user_id"].(string)
        if !ok {
            http.Error(w, "Invalid session", http.StatusUnauthorized)
            return
        }
        
        user, err := a.users.FindByID(userID)
        if err != nil {
            http.Error(w, "User not found", http.StatusUnauthorized)
            return
        }
        
        // Add user to request context
        ctx := context.WithValue(r.Context(), "user", user)
        next.ServeHTTP(w, r.WithContext(ctx))
    }
}

// Helper types
type User struct {
    ID            string    `json:"id"`
    Email         string    `json:"email"`
    Name          string    `json:"name"`
    Picture       string    `json:"picture"`
    EmailVerified bool      `json:"email_verified"`
    CreatedAt     time.Time `json:"created_at"`
    LastLoginAt   time.Time `json:"last_login_at"`
}

type OAuthAccount struct {
    UserID     string `json:"user_id"`
    Provider   string `json:"provider"`
    ProviderID string `json:"provider_id"`
    Email      string `json:"email"`
}

type AuthSession struct {
    State     string    `json:"state"`
    Provider  string    `json:"provider"`
    ExpiresAt time.Time `json:"expires_at"`
}
HTTP Routes Setup
func SetupAuthRoutes(auth *AuthService) *http.ServeMux {
    mux := http.NewServeMux()
    
    // OAuth initiation routes
    mux.HandleFunc("/auth/google", func(w http.ResponseWriter, r *http.Request) {
        auth.StartOAuthFlow("google", w, r)
    })
    
    mux.HandleFunc("/auth/github", func(w http.ResponseWriter, r *http.Request) {
        auth.StartOAuthFlow("github", w, r)
    })
    
    mux.HandleFunc("/auth/apple", func(w http.ResponseWriter, r *http.Request) {
        auth.StartOAuthFlow("apple", w, r)
    })
    
    mux.HandleFunc("/auth/twitter", func(w http.ResponseWriter, r *http.Request) {
        auth.StartOAuthFlow("twitter", w, r)
    })
    
    // OAuth callback routes
    mux.HandleFunc("/auth/google/callback", func(w http.ResponseWriter, r *http.Request) {
        user, err := auth.HandleOAuthCallback("google", w, r)
        if err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }
        
        // Redirect to app dashboard
        http.Redirect(w, r, "/dashboard", http.StatusFound)
    })
    
    mux.HandleFunc("/auth/github/callback", func(w http.ResponseWriter, r *http.Request) {
        user, err := auth.HandleOAuthCallback("github", w, r)
        if err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }
        
        http.Redirect(w, r, "/dashboard", http.StatusFound)
    })
    
    // Protected routes
    mux.HandleFunc("/dashboard", auth.RequireAuth(func(w http.ResponseWriter, r *http.Request) {
        user := r.Context().Value("user").(*User)
        fmt.Fprintf(w, "Welcome %s!", user.Name)
    }))
    
    mux.HandleFunc("/api/user", auth.RequireAuth(func(w http.ResponseWriter, r *http.Request) {
        user := r.Context().Value("user").(*User)
        json.NewEncoder(w).Encode(user)
    }))
    
    return mux
}
Database Schema
-- Users table
CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email VARCHAR(255) UNIQUE NOT NULL,
    name VARCHAR(255) NOT NULL,
    picture VARCHAR(500),
    email_verified BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT NOW(),
    last_login_at TIMESTAMP DEFAULT NOW()
);

-- OAuth accounts table for linking multiple providers
CREATE TABLE oauth_accounts (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    provider VARCHAR(50) NOT NULL,
    provider_id VARCHAR(255) NOT NULL,
    email VARCHAR(255),
    created_at TIMESTAMP DEFAULT NOW(),
    UNIQUE(provider, provider_id)
);

-- Sessions table (optional - for server-side sessions)
CREATE TABLE sessions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    token_hash VARCHAR(255) NOT NULL,
    expires_at TIMESTAMP NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);

-- Indexes
CREATE INDEX idx_oauth_accounts_user_id ON oauth_accounts(user_id);
CREATE INDEX idx_oauth_accounts_provider ON oauth_accounts(provider, provider_id);
CREATE INDEX idx_sessions_token_hash ON sessions(token_hash);
CREATE INDEX idx_sessions_expires_at ON sessions(expires_at);
Environment Configuration
# OAuth Providers
BEAVER_OAUTH_GOOGLE_CLIENT_ID=your_google_client_id
BEAVER_OAUTH_GOOGLE_CLIENT_SECRET=your_google_client_secret

BEAVER_OAUTH_GITHUB_CLIENT_ID=your_github_client_id  
BEAVER_OAUTH_GITHUB_CLIENT_SECRET=your_github_client_secret

BEAVER_OAUTH_APPLE_CLIENT_ID=com.yourapp.serviceid
BEAVER_OAUTH_APPLE_TEAM_ID=YOUR_TEAM_ID
BEAVER_OAUTH_APPLE_KEY_ID=YOUR_KEY_ID
BEAVER_OAUTH_APPLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----"

BEAVER_OAUTH_TWITTER_CLIENT_ID=your_twitter_client_id
BEAVER_OAUTH_TWITTER_CLIENT_SECRET=your_twitter_client_secret

# Security
JWT_SECRET=your_jwt_secret_key
COOKIE_SECRET=your_cookie_secret_key

# Database
DATABASE_URL=postgres://user:pass@localhost/dbname
Frontend Integration
// Login buttons
<button onclick="loginWith('google')">Sign in with Google</button>
<button onclick="loginWith('github')">Sign in with GitHub</button>
<button onclick="loginWith('apple')">Sign in with Apple</button>
<button onclick="loginWith('twitter')">Sign in with Twitter</button>

<script>
function loginWith(provider) {
    // For PWA/SPA apps, you might handle PKCE on the client side
    window.location.href = `/auth/${provider}`;
}

// Handle post-login redirect
if (window.location.pathname === '/dashboard') {
    // User successfully authenticated
    loadUserDashboard();
}
</script>
Key Security Considerations
  1. CSRF Protection - Always verify state parameter
  2. PKCE for Public Clients - Essential for PWA/mobile apps
  3. Secure Cookies - HttpOnly, Secure, SameSite attributes
  4. Token Expiration - Implement proper session management
  5. Email Verification - Verify email ownership when needed
  6. Account Linking - Handle users with multiple OAuth accounts
  7. Error Handling - Secure error messages without information leakage

This complete auth implementation provides a production-ready authentication system using the OAuth package! πŸ”

Advanced Usage

Custom State Generator
// Implement custom state generator
type MyStateGenerator struct{}

func (g *MyStateGenerator) Generate() (string, error) {
    // Your custom implementation
    return "custom_state_" + uuid.New().String(), nil
}

// Use in service
service.SetStateGenerator(&MyStateGenerator{})
Custom Session Store
// Implement custom session store (e.g., Redis)
type RedisSessionStore struct {
    client *redis.Client
}

func (s *RedisSessionStore) Store(ctx context.Context, key string, data *oauth.SessionData) error {
    // Store in Redis
}

func (s *RedisSessionStore) Retrieve(ctx context.Context, key string) (*oauth.SessionData, error) {
    // Retrieve from Redis
}

func (s *RedisSessionStore) Delete(ctx context.Context, key string) error {
    // Delete from Redis
}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This package is part of the Beaver Kit project and follows its licensing terms.

Documentation ΒΆ

Index ΒΆ

Constants ΒΆ

View Source
const (
	StateClosed   = "closed"
	StateOpen     = "open"
	StateHalfOpen = "half_open"
)

CircuitBreaker states

Variables ΒΆ

View Source
var (
	ErrCircuitOpen     = errors.New("circuit breaker is open")
	ErrTooManyRequests = errors.New("too many requests in half-open state")
)

CircuitBreaker errors

View Source
var (
	// ErrInvalidConfig indicates invalid configuration
	ErrInvalidConfig = errors.New("invalid configuration")

	// ErrNotInitialized indicates the service hasn't been initialized
	ErrNotInitialized = errors.New("oauth service not initialized")

	// ErrProviderNotFound indicates the requested provider doesn't exist
	ErrProviderNotFound = errors.New("oauth provider not found")

	// ErrInvalidState indicates state parameter mismatch (CSRF protection)
	ErrInvalidState = errors.New("invalid state parameter")

	// ErrTokenExpired indicates the token has expired
	ErrTokenExpired = errors.New("token expired")

	// ErrNoRefreshToken indicates no refresh token is available
	ErrNoRefreshToken = errors.New("no refresh token available")

	// ErrPKCENotSupported indicates PKCE is not supported by provider
	ErrPKCENotSupported = errors.New("PKCE not supported by provider")

	// ErrSessionNotFound indicates session data not found
	ErrSessionNotFound = errors.New("session not found")

	// ErrInvalidCode indicates invalid authorization code
	ErrInvalidCode = errors.New("invalid authorization code")

	// ErrNetworkError indicates a network error occurred
	ErrNetworkError = errors.New("network error")

	// ErrInvalidResponse indicates invalid response from provider
	ErrInvalidResponse = errors.New("invalid response from provider")

	// ErrAccessDenied indicates user denied access
	ErrAccessDenied = errors.New("access denied by user")

	// ErrUnsupportedResponseType indicates unsupported response type
	ErrUnsupportedResponseType = errors.New("unsupported response type")

	// ErrInvalidScope indicates invalid or unauthorized scope
	ErrInvalidScope = errors.New("invalid scope")

	// ErrServerError indicates provider server error
	ErrServerError = errors.New("provider server error")

	// ErrTemporarilyUnavailable indicates service temporarily unavailable
	ErrTemporarilyUnavailable = errors.New("service temporarily unavailable")
)

Package-level errors

Functions ΒΆ

func GetRecommendedPKCEMethod ΒΆ added in v0.1.1

func GetRecommendedPKCEMethod() string

GetRecommendedPKCEMethod returns the recommended PKCE method

func Init ΒΆ

func Init(configs ...Config) error

Init initializes the global OAuth service instance

func InitMultiProvider ΒΆ added in v0.1.1

func InitMultiProvider(configs ...MultiProviderConfig) error

InitMultiProvider initializes the global multi-provider service

func IsPKCESupported ΒΆ

func IsPKCESupported(provider string) bool

IsPKCESupported checks if a provider supports PKCE based on provider name

func IsRetryable ΒΆ

func IsRetryable(err error) bool

IsRetryable checks if an error is retryable

func PKCEParams ΒΆ

func PKCEParams(pkce *PKCEChallenge) map[string]string

PKCEParams returns URL parameters for PKCE

func PKCETokenParams ΒΆ

func PKCETokenParams(pkce *PKCEChallenge) map[string]string

PKCETokenParams returns token exchange parameters for PKCE

func Reset ΒΆ

func Reset()

Reset clears the global instance (for testing)

func ValidatePKCEChallenge ΒΆ

func ValidatePKCEChallenge(verifier, challenge, method string) bool

ValidatePKCEChallenge validates that a verifier matches a challenge

func ValidateVerifier ΒΆ added in v0.1.1

func ValidateVerifier(verifier string) error

ValidateVerifier validates a PKCE verifier per RFC 7636

Types ΒΆ

type AESGCMEncryptor ΒΆ added in v0.1.1

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

AESGCMEncryptor implements TokenEncryptor using AES-GCM

func NewAESGCMEncryptor ΒΆ added in v0.1.1

func NewAESGCMEncryptor(key []byte) (*AESGCMEncryptor, error)

NewAESGCMEncryptor creates a new AES-GCM encryptor

func (*AESGCMEncryptor) Decrypt ΒΆ added in v0.1.1

func (e *AESGCMEncryptor) Decrypt(ciphertext []byte) ([]byte, error)

Decrypt decrypts data using AES-GCM

func (*AESGCMEncryptor) Encrypt ΒΆ added in v0.1.1

func (e *AESGCMEncryptor) Encrypt(plaintext []byte) ([]byte, error)

Encrypt encrypts data using AES-GCM

type AdvancedTokenManager ΒΆ added in v0.1.1

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

AdvancedTokenManager implements TokenManager with advanced features

func NewAdvancedTokenManager ΒΆ added in v0.1.1

func NewAdvancedTokenManager(config TokenManagerConfig) *AdvancedTokenManager

NewAdvancedTokenManager creates a new advanced token manager

func (*AdvancedTokenManager) CacheToken ΒΆ added in v0.1.1

func (tm *AdvancedTokenManager) CacheToken(ctx context.Context, userID, provider string, token *Token) error

CacheToken stores a token with encryption if configured

func (*AdvancedTokenManager) CleanupExpiredTokens ΒΆ added in v0.1.1

func (tm *AdvancedTokenManager) CleanupExpiredTokens(ctx context.Context) error

CleanupExpiredTokens removes expired tokens from cache

func (*AdvancedTokenManager) DeleteToken ΒΆ added in v0.1.1

func (tm *AdvancedTokenManager) DeleteToken(ctx context.Context, userID, provider string) error

DeleteToken removes a token from cache

func (*AdvancedTokenManager) GetAllUserTokens ΒΆ added in v0.1.1

func (tm *AdvancedTokenManager) GetAllUserTokens(ctx context.Context, userID string) (map[string]*Token, error)

GetAllUserTokens retrieves all tokens for a user

func (*AdvancedTokenManager) GetCachedToken ΒΆ added in v0.1.1

func (tm *AdvancedTokenManager) GetCachedToken(ctx context.Context, userID, provider string) (*Token, error)

GetCachedToken retrieves and decrypts a cached token

func (*AdvancedTokenManager) GetTokenStats ΒΆ added in v0.1.1

func (tm *AdvancedTokenManager) GetTokenStats() *TokenStats

GetTokenStats returns current token statistics

func (*AdvancedTokenManager) RefreshExpiredTokens ΒΆ added in v0.1.1

func (tm *AdvancedTokenManager) RefreshExpiredTokens(ctx context.Context) error

RefreshExpiredTokens refreshes all tokens that are about to expire

func (*AdvancedTokenManager) RefreshIfNeeded ΒΆ added in v0.1.1

func (tm *AdvancedTokenManager) RefreshIfNeeded(ctx context.Context, userID, provider string) (*Token, error)

RefreshIfNeeded checks if a token needs refresh and refreshes it

func (*AdvancedTokenManager) RevokeToken ΒΆ added in v0.1.1

func (tm *AdvancedTokenManager) RevokeToken(ctx context.Context, userID, provider string) error

RevokeToken revokes a token with the provider and removes it from cache

func (*AdvancedTokenManager) Stop ΒΆ added in v0.1.1

func (tm *AdvancedTokenManager) Stop()

Stop stops background tasks

type AppleIDTokenClaims ΒΆ added in v0.1.1

type AppleIDTokenClaims struct {
	// Standard JWT claims
	Issuer         string        `json:"iss"`
	Subject        string        `json:"sub"`
	Audience       StringOrArray `json:"aud"`
	ExpirationTime int64         `json:"exp"`
	IssuedAt       int64         `json:"iat"`
	AuthTime       int64         `json:"auth_time,omitempty"`
	Nonce          string        `json:"nonce,omitempty"`
	NonceSupported bool          `json:"nonce_supported,omitempty"`

	// Apple-specific claims
	Email          string      `json:"email,omitempty"`
	EmailVerified  interface{} `json:"email_verified,omitempty"`   // Can be bool or string
	IsPrivateEmail interface{} `json:"is_private_email,omitempty"` // Can be bool or string
	RealUserStatus int         `json:"real_user_status,omitempty"`
	TransferSub    string      `json:"transfer_sub,omitempty"`
	AtHash         string      `json:"at_hash,omitempty"`

	// Additional claims
	Extra map[string]interface{} `json:"-"`
}

AppleIDTokenClaims represents the claims in an Apple ID token

func (*AppleIDTokenClaims) IsEmailVerified ΒΆ added in v0.1.1

func (c *AppleIDTokenClaims) IsEmailVerified() bool

IsEmailVerified returns whether the email is verified

func (*AppleIDTokenClaims) IsPrivateEmailAddress ΒΆ added in v0.1.1

func (c *AppleIDTokenClaims) IsPrivateEmailAddress() bool

IsPrivateEmailAddress returns whether the email is a private relay address

type AppleJWTValidator ΒΆ added in v0.1.1

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

AppleJWTValidator handles Apple ID token validation

func NewAppleJWTValidator ΒΆ added in v0.1.1

func NewAppleJWTValidator(clientID string, httpClient HTTPClient) *AppleJWTValidator

NewAppleJWTValidator creates a new Apple JWT validator

func (*AppleJWTValidator) EnableTestMode ΒΆ added in v0.1.1

func (v *AppleJWTValidator) EnableTestMode()

EnableTestMode enables test mode which skips signature verification (TESTING ONLY)

func (*AppleJWTValidator) ValidateIDToken ΒΆ added in v0.1.1

func (v *AppleJWTValidator) ValidateIDToken(ctx context.Context, idToken string, nonce string) (*AppleIDTokenClaims, error)

ValidateIDToken validates an Apple ID token

type AppleKeysResponse ΒΆ added in v0.1.1

type AppleKeysResponse struct {
	Keys []ApplePublicKey `json:"keys"`
}

AppleKeysResponse represents the response from Apple's keys endpoint

type AppleProvider ΒΆ added in v0.1.1

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

AppleProvider implements OAuth provider for Apple Sign-In

func NewApple ΒΆ added in v0.1.1

func NewApple(config ProviderConfig) (*AppleProvider, error)

NewApple creates a new Apple OAuth provider

func (*AppleProvider) EnableTestMode ΒΆ added in v0.1.1

func (a *AppleProvider) EnableTestMode()

EnableTestMode enables test mode which skips JWT signature verification (TESTING ONLY)

func (*AppleProvider) Exchange ΒΆ added in v0.1.1

func (a *AppleProvider) Exchange(ctx context.Context, code string, pkce *PKCEChallenge) (*Token, error)

Exchange exchanges an authorization code for tokens

func (*AppleProvider) GetAuthURL ΒΆ added in v0.1.1

func (a *AppleProvider) GetAuthURL(state string, pkce *PKCEChallenge) string

GetAuthURL returns the authorization URL with PKCE parameters if enabled

func (*AppleProvider) GetUserInfo ΒΆ added in v0.1.1

func (a *AppleProvider) GetUserInfo(ctx context.Context, accessToken string) (*UserInfo, error)

GetUserInfo retrieves user information from the ID token (Apple doesn't provide a userinfo endpoint)

func (*AppleProvider) GetUserInfoFromIDToken ΒΆ added in v0.1.1

func (a *AppleProvider) GetUserInfoFromIDToken(idToken string) (*UserInfo, error)

GetUserInfoFromIDToken extracts user information from Apple ID token

func (*AppleProvider) GetUserInfoFromIDTokenWithNonce ΒΆ added in v0.1.1

func (a *AppleProvider) GetUserInfoFromIDTokenWithNonce(idToken string, nonce string) (*UserInfo, error)

GetUserInfoFromIDTokenWithNonce extracts user information from Apple ID token with nonce verification

func (*AppleProvider) Name ΒΆ added in v0.1.1

func (a *AppleProvider) Name() string

Name returns the provider name

func (*AppleProvider) ParseIDToken ΒΆ added in v0.1.1

func (a *AppleProvider) ParseIDToken(idToken string) (map[string]interface{}, error)

ParseIDToken parses and validates Apple ID Token (JWT)

func (*AppleProvider) ParseIDTokenWithNonce ΒΆ added in v0.1.1

func (a *AppleProvider) ParseIDTokenWithNonce(idToken string, nonce string) (map[string]interface{}, error)

ParseIDTokenWithNonce parses and validates Apple ID Token with nonce verification

func (*AppleProvider) RefreshToken ΒΆ added in v0.1.1

func (a *AppleProvider) RefreshToken(ctx context.Context, refreshToken string) (*Token, error)

RefreshToken refreshes the access token using a refresh token

func (*AppleProvider) RevokeToken ΒΆ added in v0.1.1

func (a *AppleProvider) RevokeToken(ctx context.Context, token string) error

RevokeToken revokes the access token

func (*AppleProvider) SetHTTPClient ΒΆ added in v0.1.1

func (a *AppleProvider) SetHTTPClient(client HTTPClient)

SetHTTPClient sets a custom HTTP client

func (*AppleProvider) SupportsPKCE ΒΆ added in v0.1.1

func (a *AppleProvider) SupportsPKCE() bool

SupportsPKCE indicates if the provider supports PKCE

func (*AppleProvider) SupportsRefresh ΒΆ added in v0.1.1

func (a *AppleProvider) SupportsRefresh() bool

SupportsRefresh indicates if the provider supports token refresh

func (*AppleProvider) ValidateConfig ΒΆ added in v0.1.1

func (a *AppleProvider) ValidateConfig() error

ValidateConfig validates the provider configuration

type ApplePublicKey ΒΆ added in v0.1.1

type ApplePublicKey struct {
	KTY string `json:"kty"` // Key Type
	KID string `json:"kid"` // Key ID
	Use string `json:"use"` // Key Use
	Alg string `json:"alg"` // Algorithm
	N   string `json:"n"`   // Modulus (for RSA)
	E   string `json:"e"`   // Exponent (for RSA)
	X   string `json:"x"`   // X coordinate (for ECDSA)
	Y   string `json:"y"`   // Y coordinate (for ECDSA)
	CRV string `json:"crv"` // Curve (for ECDSA)
}

ApplePublicKey represents Apple's public key

type AppleUser ΒΆ added in v0.1.1

type AppleUser struct {
	ID    string `json:"sub"`
	Email string `json:"email"`
	Name  struct {
		FirstName string `json:"firstName"`
		LastName  string `json:"lastName"`
	} `json:"name"`
	EmailVerified string `json:"email_verified"` // Apple returns "true"/"false" as string
}

AppleUser represents the user data returned by Apple

type AuthOption ΒΆ added in v0.1.1

type AuthOption func(*authOptions)

AuthOption defines options for GetAuthURL

func WithMetadata ΒΆ added in v0.1.1

func WithMetadata(metadata map[string]interface{}) AuthOption

WithMetadata adds metadata to the session

func WithPKCE ΒΆ added in v0.1.1

func WithPKCE(enabled bool) AuthOption

WithPKCE enables or disables PKCE for this auth request

func WithPKCEMethod ΒΆ added in v0.1.1

func WithPKCEMethod(method string) AuthOption

WithPKCEMethod sets the PKCE method for this auth request

type AuthorizationRequest ΒΆ

type AuthorizationRequest struct {
	State         string
	PKCEChallenge *PKCEChallenge
	RedirectURL   string
	Scopes        []string
	ExtraParams   map[string]string
}

AuthorizationRequest represents an OAuth authorization request

type AuthorizationResponse ΒΆ

type AuthorizationResponse struct {
	Code  string
	State string
	Error string
}

AuthorizationResponse represents the response from an OAuth authorization

type Builder ΒΆ

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

Builder pattern for custom prefixes

func WithPrefix ΒΆ

func WithPrefix(prefix string) *Builder

WithPrefix creates a new Builder with the specified prefix

func (*Builder) Init ΒΆ

func (b *Builder) Init() error

Init initializes the OAuth service with the builder's prefix

func (*Builder) New ΒΆ

func (b *Builder) New() (*Service, error)

New creates a new OAuth service instance with the builder's prefix

type CacheIntegratedTokenStore ΒΆ added in v0.1.1

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

CacheIntegratedTokenStore integrates with external cache systems

func NewCacheIntegratedTokenStore ΒΆ added in v0.1.1

func NewCacheIntegratedTokenStore(primary, cache TokenStore, ttl time.Duration) *CacheIntegratedTokenStore

NewCacheIntegratedTokenStore creates a token store with cache integration

func (*CacheIntegratedTokenStore) Delete ΒΆ added in v0.1.1

Delete removes token from both stores

func (*CacheIntegratedTokenStore) Retrieve ΒΆ added in v0.1.1

func (c *CacheIntegratedTokenStore) Retrieve(ctx context.Context, key string) (*Token, error)

Retrieve gets token from cache first, then primary

func (*CacheIntegratedTokenStore) Store ΒΆ added in v0.1.1

func (c *CacheIntegratedTokenStore) Store(ctx context.Context, key string, token *Token) error

Store saves token to both primary and cache

type CheckResult ΒΆ added in v0.1.1

type CheckResult struct {
	Status      HealthStatus  `json:"status"`
	Message     string        `json:"message,omitempty"`
	Error       string        `json:"error,omitempty"`
	Duration    time.Duration `json:"duration,omitempty"`
	LastChecked time.Time     `json:"last_checked"`
}

CheckResult represents the result of a single health check

type CircuitBreaker ΒΆ added in v0.1.1

type CircuitBreaker interface {
	// Call executes the function if the circuit allows it
	Call(ctx context.Context, fn func() error) error
	// GetState returns the current state of the circuit
	GetState() string
	// GetStats returns circuit breaker statistics
	GetStats() *CircuitStats
	// Reset resets the circuit breaker
	Reset()
}

CircuitBreaker protects external API calls from cascading failures

type CircuitBreakerConfig ΒΆ added in v0.1.1

type CircuitBreakerConfig struct {
	// FailureThreshold is the number of consecutive failures before opening
	FailureThreshold int
	// SuccessThreshold is the number of consecutive successes in half-open before closing
	SuccessThreshold int
	// Timeout is how long to wait before trying half-open state
	Timeout time.Duration
	// MaxHalfOpenRequests is the maximum number of requests in half-open state
	MaxHalfOpenRequests int
	// OnStateChange is called when the circuit changes state
	OnStateChange func(from, to string)
}

CircuitBreakerConfig configures the circuit breaker

type CircuitBreakerManager ΒΆ added in v0.1.1

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

CircuitBreakerManager manages circuit breakers for multiple endpoints

func NewCircuitBreakerManager ΒΆ added in v0.1.1

func NewCircuitBreakerManager(config CircuitBreakerConfig) *CircuitBreakerManager

NewCircuitBreakerManager creates a new circuit breaker manager

func (*CircuitBreakerManager) Call ΒΆ added in v0.1.1

func (m *CircuitBreakerManager) Call(ctx context.Context, key string, fn func() error) error

Call executes the function using the circuit breaker for the given key

func (*CircuitBreakerManager) GetAllStats ΒΆ added in v0.1.1

func (m *CircuitBreakerManager) GetAllStats() map[string]*CircuitStats

GetAllStats returns statistics for all circuit breakers

func (*CircuitBreakerManager) GetBreaker ΒΆ added in v0.1.1

func (m *CircuitBreakerManager) GetBreaker(key string) CircuitBreaker

GetBreaker returns a circuit breaker for the given key

func (*CircuitBreakerManager) Reset ΒΆ added in v0.1.1

func (m *CircuitBreakerManager) Reset(key string)

Reset resets a specific circuit breaker

func (*CircuitBreakerManager) ResetAll ΒΆ added in v0.1.1

func (m *CircuitBreakerManager) ResetAll()

ResetAll resets all circuit breakers

type CircuitStats ΒΆ added in v0.1.1

type CircuitStats struct {
	State                string    `json:"state"`
	Requests             int64     `json:"requests"`
	TotalSuccesses       int64     `json:"total_successes"`
	TotalFailures        int64     `json:"total_failures"`
	ConsecutiveSuccesses int64     `json:"consecutive_successes"`
	ConsecutiveFailures  int64     `json:"consecutive_failures"`
	LastFailureTime      time.Time `json:"last_failure_time,omitempty"`
	LastSuccessTime      time.Time `json:"last_success_time,omitempty"`
	NextRetryTime        time.Time `json:"next_retry_time,omitempty"`
}

CircuitStats represents circuit breaker statistics

type Config ΒΆ

type Config struct {
	// Provider specifies the OAuth provider (google, github, apple, twitter, custom)
	Provider string `env:"OAUTH_PROVIDER,default:google"`

	// ClientID is the OAuth application's client ID
	ClientID string `env:"OAUTH_CLIENT_ID,required"`

	// ClientSecret is the OAuth application's client secret
	ClientSecret string `env:"OAUTH_CLIENT_SECRET,required"`

	// RedirectURL is the callback URL after authentication
	RedirectURL string `env:"OAUTH_REDIRECT_URL,required"`

	// Scopes is a comma-separated list of OAuth scopes
	Scopes string `env:"OAUTH_SCOPES,default:openid,profile,email"`

	// State is the default state parameter for CSRF protection
	State string `env:"OAUTH_STATE"`

	// StateGenerator defines how to generate state tokens (uuid, secure, custom)
	StateGenerator string `env:"OAUTH_STATE_GENERATOR,default:secure"`

	// PKCEEnabled enables PKCE flow for enhanced security
	PKCEEnabled bool `env:"OAUTH_PKCE_ENABLED,default:true"`

	// PKCEMethod is the PKCE challenge method (S256 or plain)
	PKCEMethod string `env:"OAUTH_PKCE_METHOD,default:S256"`

	// TokenCacheDuration is how long to cache tokens
	TokenCacheDuration time.Duration `env:"OAUTH_TOKEN_CACHE_DURATION,default:1h"`

	// StateTimeout is how long state parameters are valid
	StateTimeout time.Duration `env:"OAUTH_STATE_TIMEOUT,default:5m"`

	// HTTPTimeout is the timeout for HTTP requests
	HTTPTimeout time.Duration `env:"OAUTH_HTTP_TIMEOUT,default:30s"`

	// Debug enables debug logging
	Debug bool `env:"OAUTH_DEBUG,default:false"`

	// Custom provider configuration (for generic OAuth2 providers)
	AuthURL     string `env:"OAUTH_AUTH_URL"`
	TokenURL    string `env:"OAUTH_TOKEN_URL"`
	UserInfoURL string `env:"OAUTH_USERINFO_URL"`

	// Provider-specific configurations
	AppleTeamID     string `env:"OAUTH_APPLE_TEAM_ID"`
	AppleKeyID      string `env:"OAUTH_APPLE_KEY_ID"`
	ApplePrivateKey string `env:"OAUTH_APPLE_PRIVATE_KEY"`

	// Twitter API version (1.1 or 2)
	TwitterAPIVersion string `env:"OAUTH_TWITTER_API_VERSION,default:2"`
}

Config defines the OAuth service configuration

func GetConfig ΒΆ

func GetConfig(opts ...config.LoadOptions) (*Config, error)

GetConfig returns config loaded from environment with optional LoadOptions

type CustomProvider ΒΆ added in v0.1.1

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

CustomProvider implements a generic OAuth 2.0 provider

func NewCustom ΒΆ added in v0.1.1

func NewCustom(config ProviderConfig) (*CustomProvider, error)

NewCustom creates a new custom OAuth provider

func (*CustomProvider) Exchange ΒΆ added in v0.1.1

func (c *CustomProvider) Exchange(ctx context.Context, code string, pkce *PKCEChallenge) (*Token, error)

Exchange exchanges an authorization code for tokens

func (*CustomProvider) GetAuthURL ΒΆ added in v0.1.1

func (c *CustomProvider) GetAuthURL(state string, pkce *PKCEChallenge) string

GetAuthURL returns the authorization URL with optional PKCE parameters

func (*CustomProvider) GetUserInfo ΒΆ added in v0.1.1

func (c *CustomProvider) GetUserInfo(ctx context.Context, accessToken string) (*UserInfo, error)

GetUserInfo retrieves user information from the userinfo endpoint

func (*CustomProvider) Name ΒΆ added in v0.1.1

func (c *CustomProvider) Name() string

Name returns the provider name

func (*CustomProvider) RefreshToken ΒΆ added in v0.1.1

func (c *CustomProvider) RefreshToken(ctx context.Context, refreshToken string) (*Token, error)

RefreshToken refreshes the access token using a refresh token

func (*CustomProvider) RevokeToken ΒΆ added in v0.1.1

func (c *CustomProvider) RevokeToken(ctx context.Context, token string) error

RevokeToken revokes the access token

func (*CustomProvider) SetHTTPClient ΒΆ added in v0.1.1

func (c *CustomProvider) SetHTTPClient(client HTTPClient)

SetHTTPClient sets a custom HTTP client

func (*CustomProvider) SupportsPKCE ΒΆ added in v0.1.1

func (c *CustomProvider) SupportsPKCE() bool

SupportsPKCE indicates if the provider supports PKCE

func (*CustomProvider) SupportsRefresh ΒΆ added in v0.1.1

func (c *CustomProvider) SupportsRefresh() bool

SupportsRefresh indicates if the provider supports token refresh

func (*CustomProvider) ValidateConfig ΒΆ added in v0.1.1

func (c *CustomProvider) ValidateConfig() error

ValidateConfig validates the provider configuration

type DefaultCircuitBreaker ΒΆ added in v0.1.1

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

DefaultCircuitBreaker implements a circuit breaker with configurable thresholds

func NewDefaultCircuitBreaker ΒΆ added in v0.1.1

func NewDefaultCircuitBreaker(config CircuitBreakerConfig) *DefaultCircuitBreaker

NewDefaultCircuitBreaker creates a new circuit breaker with default settings

func (*DefaultCircuitBreaker) Call ΒΆ added in v0.1.1

func (cb *DefaultCircuitBreaker) Call(ctx context.Context, fn func() error) error

Call executes the function if the circuit allows it

func (*DefaultCircuitBreaker) GetState ΒΆ added in v0.1.1

func (cb *DefaultCircuitBreaker) GetState() string

GetState returns the current state of the circuit

func (*DefaultCircuitBreaker) GetStats ΒΆ added in v0.1.1

func (cb *DefaultCircuitBreaker) GetStats() *CircuitStats

GetStats returns circuit breaker statistics

func (*DefaultCircuitBreaker) Reset ΒΆ added in v0.1.1

func (cb *DefaultCircuitBreaker) Reset()

Reset resets the circuit breaker

type DefaultHealthChecker ΒΆ added in v0.1.1

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

DefaultHealthChecker implements HealthChecker

func NewDefaultHealthChecker ΒΆ added in v0.1.1

func NewDefaultHealthChecker(config HealthCheckerConfig) *DefaultHealthChecker

NewDefaultHealthChecker creates a new health checker

func (*DefaultHealthChecker) Check ΒΆ added in v0.1.1

Check performs a comprehensive health check

func (*DefaultHealthChecker) CheckComponent ΒΆ added in v0.1.1

func (h *DefaultHealthChecker) CheckComponent(ctx context.Context, component string) (*CheckResult, error)

CheckComponent checks a specific component

func (*DefaultHealthChecker) RegisterCheck ΒΆ added in v0.1.1

func (h *DefaultHealthChecker) RegisterCheck(name string, check func(context.Context) error)

RegisterCheck registers a custom health check

type DefaultMetricsCollector ΒΆ added in v0.1.1

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

DefaultMetricsCollector implements MetricsCollector with in-memory storage

func NewDefaultMetricsCollector ΒΆ added in v0.1.1

func NewDefaultMetricsCollector() *DefaultMetricsCollector

NewDefaultMetricsCollector creates a new default metrics collector

func (*DefaultMetricsCollector) GetMetrics ΒΆ added in v0.1.1

func (c *DefaultMetricsCollector) GetMetrics() *Metrics

GetMetrics returns current metrics

func (*DefaultMetricsCollector) RecordAuthRequest ΒΆ added in v0.1.1

func (c *DefaultMetricsCollector) RecordAuthRequest(provider string, success bool, duration time.Duration)

RecordAuthRequest records an authorization request

func (*DefaultMetricsCollector) RecordError ΒΆ added in v0.1.1

func (c *DefaultMetricsCollector) RecordError(provider string, operation string, errorType string)

RecordError records an error

func (*DefaultMetricsCollector) RecordRateLimitHit ΒΆ added in v0.1.1

func (c *DefaultMetricsCollector) RecordRateLimitHit(key string)

RecordRateLimitHit records a rate limit hit

func (*DefaultMetricsCollector) RecordTokenExchange ΒΆ added in v0.1.1

func (c *DefaultMetricsCollector) RecordTokenExchange(provider string, success bool, duration time.Duration)

RecordTokenExchange records a token exchange

func (*DefaultMetricsCollector) RecordTokenRefresh ΒΆ added in v0.1.1

func (c *DefaultMetricsCollector) RecordTokenRefresh(provider string, success bool, duration time.Duration)

RecordTokenRefresh records a token refresh

func (*DefaultMetricsCollector) RecordUserInfoRequest ΒΆ added in v0.1.1

func (c *DefaultMetricsCollector) RecordUserInfoRequest(provider string, success bool, duration time.Duration)

RecordUserInfoRequest records a user info request

func (*DefaultMetricsCollector) Reset ΒΆ added in v0.1.1

func (c *DefaultMetricsCollector) Reset()

Reset resets all metrics

type EncryptedSessionStore ΒΆ added in v0.1.1

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

EncryptedSessionStore wraps a SessionStore with encryption

func NewEncryptedSessionStore ΒΆ added in v0.1.1

func NewEncryptedSessionStore(store SessionStore, key []byte) (*EncryptedSessionStore, error)

NewEncryptedSessionStore creates a new encrypted session store

func (*EncryptedSessionStore) Delete ΒΆ added in v0.1.1

func (e *EncryptedSessionStore) Delete(ctx context.Context, key string) error

Delete removes session data

func (*EncryptedSessionStore) Retrieve ΒΆ added in v0.1.1

func (e *EncryptedSessionStore) Retrieve(ctx context.Context, key string) (*SessionData, error)

Retrieve decrypts and retrieves session data

func (*EncryptedSessionStore) RetrieveAndDelete ΒΆ added in v0.1.1

func (e *EncryptedSessionStore) RetrieveAndDelete(ctx context.Context, key string) (*SessionData, error)

RetrieveAndDelete atomically retrieves and deletes session data

func (*EncryptedSessionStore) Store ΒΆ added in v0.1.1

func (e *EncryptedSessionStore) Store(ctx context.Context, key string, data *SessionData) error

Store encrypts and stores session data

type EncryptedTokenStore ΒΆ added in v0.1.1

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

EncryptedTokenStore wraps a TokenStore with encryption

func NewEncryptedTokenStore ΒΆ added in v0.1.1

func NewEncryptedTokenStore(store TokenStore, key []byte) (*EncryptedTokenStore, error)

NewEncryptedTokenStore creates a new encrypted token store

func (*EncryptedTokenStore) Delete ΒΆ added in v0.1.1

func (e *EncryptedTokenStore) Delete(ctx context.Context, key string) error

Delete removes a token

func (*EncryptedTokenStore) Retrieve ΒΆ added in v0.1.1

func (e *EncryptedTokenStore) Retrieve(ctx context.Context, key string) (*Token, error)

Retrieve decrypts and retrieves a token

func (*EncryptedTokenStore) Store ΒΆ added in v0.1.1

func (e *EncryptedTokenStore) Store(ctx context.Context, key string, token *Token) error

Store encrypts and stores a token

type GitHubProvider ΒΆ

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

GitHubProvider implements OAuth provider for GitHub

func NewGitHub ΒΆ

func NewGitHub(config ProviderConfig) *GitHubProvider

NewGitHub creates a new GitHub OAuth provider

func (*GitHubProvider) Exchange ΒΆ

func (g *GitHubProvider) Exchange(ctx context.Context, code string, pkce *PKCEChallenge) (*Token, error)

Exchange exchanges an authorization code for tokens

func (*GitHubProvider) GetAuthURL ΒΆ

func (g *GitHubProvider) GetAuthURL(state string, pkce *PKCEChallenge) string

GetAuthURL returns the authorization URL with PKCE parameters if enabled

func (*GitHubProvider) GetUserInfo ΒΆ

func (g *GitHubProvider) GetUserInfo(ctx context.Context, accessToken string) (*UserInfo, error)

GetUserInfo retrieves user information using the access token

func (*GitHubProvider) Name ΒΆ

func (g *GitHubProvider) Name() string

Name returns the provider name

func (*GitHubProvider) RefreshToken ΒΆ

func (g *GitHubProvider) RefreshToken(ctx context.Context, refreshToken string) (*Token, error)

RefreshToken refreshes the access token

func (*GitHubProvider) RevokeToken ΒΆ

func (g *GitHubProvider) RevokeToken(ctx context.Context, token string) error

RevokeToken revokes the access token

func (*GitHubProvider) SetHTTPClient ΒΆ

func (g *GitHubProvider) SetHTTPClient(client HTTPClient)

SetHTTPClient sets a custom HTTP client

func (*GitHubProvider) SupportsPKCE ΒΆ

func (g *GitHubProvider) SupportsPKCE() bool

SupportsPKCE indicates if the provider supports PKCE

func (*GitHubProvider) SupportsRefresh ΒΆ

func (g *GitHubProvider) SupportsRefresh() bool

SupportsRefresh indicates if the provider supports token refresh

func (*GitHubProvider) ValidateConfig ΒΆ

func (g *GitHubProvider) ValidateConfig() error

ValidateConfig validates the provider configuration

type GitHubUser ΒΆ

type GitHubUser struct {
	ID              int64  `json:"id"`
	Login           string `json:"login"`
	Email           string `json:"email"`
	Name            string `json:"name"`
	AvatarURL       string `json:"avatar_url"`
	Bio             string `json:"bio"`
	Company         string `json:"company"`
	Location        string `json:"location"`
	Blog            string `json:"blog"`
	TwitterUsername string `json:"twitter_username"`
}

GitHubUser represents the user data returned by GitHub

type GoogleProvider ΒΆ added in v0.1.1

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

GoogleProvider implements OAuth provider for Google

func NewGoogle ΒΆ added in v0.1.1

func NewGoogle(config ProviderConfig) *GoogleProvider

NewGoogle creates a new Google OAuth provider

func (*GoogleProvider) Exchange ΒΆ added in v0.1.1

func (g *GoogleProvider) Exchange(ctx context.Context, code string, pkce *PKCEChallenge) (*Token, error)

Exchange exchanges an authorization code for tokens

func (*GoogleProvider) GetAuthURL ΒΆ added in v0.1.1

func (g *GoogleProvider) GetAuthURL(state string, pkce *PKCEChallenge) string

GetAuthURL returns the authorization URL with PKCE parameters if enabled

func (*GoogleProvider) GetUserInfo ΒΆ added in v0.1.1

func (g *GoogleProvider) GetUserInfo(ctx context.Context, accessToken string) (*UserInfo, error)

GetUserInfo retrieves user information using the access token

func (*GoogleProvider) Name ΒΆ added in v0.1.1

func (g *GoogleProvider) Name() string

Name returns the provider name

func (*GoogleProvider) ParseIDToken ΒΆ added in v0.1.1

func (g *GoogleProvider) ParseIDToken(idToken string) (map[string]interface{}, error)

ParseIDToken parses and validates Google ID Token (JWT) This is a basic implementation - for production use, consider using a proper JWT library

func (*GoogleProvider) RefreshToken ΒΆ added in v0.1.1

func (g *GoogleProvider) RefreshToken(ctx context.Context, refreshToken string) (*Token, error)

RefreshToken refreshes the access token using a refresh token

func (*GoogleProvider) RevokeToken ΒΆ added in v0.1.1

func (g *GoogleProvider) RevokeToken(ctx context.Context, token string) error

RevokeToken revokes the access token

func (*GoogleProvider) SetHTTPClient ΒΆ added in v0.1.1

func (g *GoogleProvider) SetHTTPClient(client HTTPClient)

SetHTTPClient sets a custom HTTP client

func (*GoogleProvider) SupportsPKCE ΒΆ added in v0.1.1

func (g *GoogleProvider) SupportsPKCE() bool

SupportsPKCE indicates if the provider supports PKCE

func (*GoogleProvider) SupportsRefresh ΒΆ added in v0.1.1

func (g *GoogleProvider) SupportsRefresh() bool

SupportsRefresh indicates if the provider supports token refresh

func (*GoogleProvider) ValidateConfig ΒΆ added in v0.1.1

func (g *GoogleProvider) ValidateConfig() error

ValidateConfig validates the provider configuration

type GoogleUser ΒΆ added in v0.1.1

type GoogleUser struct {
	ID            string `json:"id"`
	Email         string `json:"email"`
	VerifiedEmail bool   `json:"verified_email"`
	Name          string `json:"name"`
	GivenName     string `json:"given_name"`
	FamilyName    string `json:"family_name"`
	Picture       string `json:"picture"`
	Locale        string `json:"locale"`
	HD            string `json:"hd"` // Hosted domain for G Suite accounts
}

GoogleUser represents the user data returned by Google

type HTTPClient ΒΆ

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

HTTPClient interface for mocking in tests

type HealthCheck ΒΆ added in v0.1.1

type HealthCheck struct {
	Status    HealthStatus           `json:"status"`
	Timestamp time.Time              `json:"timestamp"`
	Version   string                 `json:"version,omitempty"`
	Uptime    time.Duration          `json:"uptime,omitempty"`
	Checks    map[string]CheckResult `json:"checks,omitempty"`
	Metrics   *HealthMetrics         `json:"metrics,omitempty"`
}

HealthCheck represents a health check result

type HealthChecker ΒΆ added in v0.1.1

type HealthChecker interface {
	// Check performs a health check
	Check(ctx context.Context) (*HealthCheck, error)
	// CheckComponent checks a specific component
	CheckComponent(ctx context.Context, component string) (*CheckResult, error)
	// RegisterCheck registers a custom health check
	RegisterCheck(name string, check func(context.Context) error)
}

HealthChecker performs health checks

type HealthCheckerConfig ΒΆ added in v0.1.1

type HealthCheckerConfig struct {
	Version          string
	Service          *Service
	MultiService     *MultiProviderService
	TokenManager     TokenManager
	RateLimiter      RateLimiter
	MetricsCollector MetricsCollector
}

HealthCheckerConfig configures the health checker

type HealthHandler ΒΆ added in v0.1.1

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

HealthHandler provides HTTP handlers for health checks

func NewHealthHandler ΒΆ added in v0.1.1

func NewHealthHandler(checker HealthChecker) *HealthHandler

NewHealthHandler creates a new health handler

func (*HealthHandler) HandleHealth ΒΆ added in v0.1.1

func (h *HealthHandler) HandleHealth(w http.ResponseWriter, r *http.Request)

HandleHealth handles the main health check endpoint

func (*HealthHandler) HandleLiveness ΒΆ added in v0.1.1

func (h *HealthHandler) HandleLiveness(w http.ResponseWriter, r *http.Request)

HandleLiveness handles the liveness probe endpoint

func (*HealthHandler) HandleReadiness ΒΆ added in v0.1.1

func (h *HealthHandler) HandleReadiness(w http.ResponseWriter, r *http.Request)

HandleReadiness handles the readiness probe endpoint

type HealthMetrics ΒΆ added in v0.1.1

type HealthMetrics struct {
	RequestsPerSecond float64 `json:"requests_per_second"`
	ErrorRate         float64 `json:"error_rate"`
	AverageLatency    int64   `json:"average_latency_ms"`
	ActiveSessions    int64   `json:"active_sessions"`
	CachedTokens      int64   `json:"cached_tokens"`
}

HealthMetrics represents health-related metrics

type HealthStatus ΒΆ added in v0.1.1

type HealthStatus string

HealthStatus represents the health status of a component

const (
	HealthStatusHealthy   HealthStatus = "healthy"
	HealthStatusDegraded  HealthStatus = "degraded"
	HealthStatusUnhealthy HealthStatus = "unhealthy"
)

type InstrumentedService ΒΆ added in v0.1.1

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

InstrumentedService wraps Service with monitoring

func NewInstrumentedService ΒΆ added in v0.1.1

func NewInstrumentedService(service *Service, collector MetricsCollector) *InstrumentedService

NewInstrumentedService creates a new instrumented service

func (*InstrumentedService) Exchange ΒΆ added in v0.1.1

func (s *InstrumentedService) Exchange(ctx context.Context, code, state string) (*Token, error)

Exchange exchanges an authorization code for tokens with monitoring

func (*InstrumentedService) GetAuthURL ΒΆ added in v0.1.1

func (s *InstrumentedService) GetAuthURL(ctx context.Context) (string, error)

GetAuthURL generates an authorization URL with monitoring

type MemorySessionStore ΒΆ

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

MemorySessionStore implements SessionStore with in-memory storage

func NewMemorySessionStore ΒΆ

func NewMemorySessionStore(ttl time.Duration) *MemorySessionStore

func (*MemorySessionStore) Delete ΒΆ

func (s *MemorySessionStore) Delete(ctx context.Context, key string) error

func (*MemorySessionStore) Retrieve ΒΆ

func (s *MemorySessionStore) Retrieve(ctx context.Context, key string) (*SessionData, error)

func (*MemorySessionStore) RetrieveAndDelete ΒΆ added in v0.1.1

func (s *MemorySessionStore) RetrieveAndDelete(ctx context.Context, key string) (*SessionData, error)

func (*MemorySessionStore) Store ΒΆ

func (s *MemorySessionStore) Store(ctx context.Context, key string, data *SessionData) error

type MemoryTokenStore ΒΆ

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

MemoryTokenStore implements TokenStore with in-memory storage

func NewMemoryTokenStore ΒΆ

func NewMemoryTokenStore(ttl time.Duration) *MemoryTokenStore

func (*MemoryTokenStore) Delete ΒΆ

func (s *MemoryTokenStore) Delete(ctx context.Context, key string) error

func (*MemoryTokenStore) Retrieve ΒΆ

func (s *MemoryTokenStore) Retrieve(ctx context.Context, key string) (*Token, error)

func (*MemoryTokenStore) Store ΒΆ

func (s *MemoryTokenStore) Store(ctx context.Context, key string, token *Token) error

type MetricCounter ΒΆ added in v0.1.1

type MetricCounter struct {
	Total   int64 `json:"total"`
	Success int64 `json:"success"`
	Failed  int64 `json:"failed"`
}

MetricCounter represents a counter metric

type Metrics ΒΆ added in v0.1.1

type Metrics struct {
	// Request counts
	AuthRequests     MetricCounter `json:"auth_requests"`
	TokenExchanges   MetricCounter `json:"token_exchanges"`
	TokenRefreshes   MetricCounter `json:"token_refreshes"`
	UserInfoRequests MetricCounter `json:"user_info_requests"`

	// Error counts
	Errors map[string]MetricCounter `json:"errors"`

	// Rate limiting
	RateLimitHits MetricCounter `json:"rate_limit_hits"`

	// Performance metrics
	ResponseTimes map[string]ResponseTime `json:"response_times"`

	// Provider-specific metrics
	ProviderMetrics map[string]*ProviderMetric `json:"provider_metrics"`

	// System metrics
	ActiveSessions int64 `json:"active_sessions"`
	CachedTokens   int64 `json:"cached_tokens"`

	// Time window
	StartTime     time.Time `json:"start_time"`
	LastResetTime time.Time `json:"last_reset_time"`
}

Metrics represents collected OAuth metrics

type MetricsCollector ΒΆ added in v0.1.1

type MetricsCollector interface {
	// RecordAuthRequest records an authorization request
	RecordAuthRequest(provider string, success bool, duration time.Duration)
	// RecordTokenExchange records a token exchange
	RecordTokenExchange(provider string, success bool, duration time.Duration)
	// RecordTokenRefresh records a token refresh
	RecordTokenRefresh(provider string, success bool, duration time.Duration)
	// RecordUserInfoRequest records a user info request
	RecordUserInfoRequest(provider string, success bool, duration time.Duration)
	// RecordRateLimitHit records a rate limit hit
	RecordRateLimitHit(key string)
	// RecordError records an error
	RecordError(provider string, operation string, errorType string)
	// GetMetrics returns current metrics
	GetMetrics() *Metrics
	// Reset resets all metrics
	Reset()
}

MetricsCollector collects and reports OAuth metrics

type Middleware ΒΆ added in v0.1.1

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

Middleware provides HTTP middleware for OAuth operations

func NewMiddleware ΒΆ added in v0.1.1

func NewMiddleware(config MiddlewareConfig) *Middleware

NewMiddleware creates a new OAuth middleware

func (*Middleware) CORS ΒΆ added in v0.1.1

func (m *Middleware) CORS(next http.Handler) http.Handler

CORS handles Cross-Origin Resource Sharing

func (*Middleware) Chain ΒΆ added in v0.1.1

func (m *Middleware) Chain(handlers ...func(http.Handler) http.Handler) func(http.Handler) http.Handler

Chain combines multiple middleware functions

func (*Middleware) DefaultChain ΒΆ added in v0.1.1

func (m *Middleware) DefaultChain() func(http.Handler) http.Handler

DefaultChain returns the default middleware chain

func (*Middleware) RateLimit ΒΆ added in v0.1.1

func (m *Middleware) RateLimit(next http.Handler) http.Handler

RateLimit implements rate limiting middleware

func (*Middleware) RequestLogging ΒΆ added in v0.1.1

func (m *Middleware) RequestLogging(next http.Handler) http.Handler

RequestLogging logs incoming requests

func (*Middleware) RequireHTTPS ΒΆ added in v0.1.1

func (m *Middleware) RequireHTTPS(next http.Handler) http.Handler

RequireHTTPS ensures requests are made over HTTPS

func (*Middleware) SecurityHeaders ΒΆ added in v0.1.1

func (m *Middleware) SecurityHeaders(next http.Handler) http.Handler

SecurityHeaders adds security headers to responses

func (*Middleware) Timeout ΒΆ added in v0.1.1

func (m *Middleware) Timeout(next http.Handler) http.Handler

Timeout adds request timeout

func (*Middleware) WithMultiProviderService ΒΆ added in v0.1.1

func (m *Middleware) WithMultiProviderService(service *MultiProviderService) *Middleware

WithMultiProviderService sets the multi-provider service for the middleware

func (*Middleware) WithService ΒΆ added in v0.1.1

func (m *Middleware) WithService(service *Service) *Middleware

WithService sets the OAuth service for the middleware

type MiddlewareConfig ΒΆ added in v0.1.1

type MiddlewareConfig struct {
	// Security headers
	EnableSecurityHeaders bool `env:"OAUTH_SECURITY_HEADERS,default:true"`
	EnableHSTS            bool `env:"OAUTH_HSTS_ENABLED,default:true"`
	HSTSMaxAge            int  `env:"OAUTH_HSTS_MAX_AGE,default:31536000"`

	// CORS configuration
	EnableCORS       bool     `env:"OAUTH_CORS_ENABLED,default:true"`
	AllowedOrigins   []string `env:"OAUTH_CORS_ORIGINS"`
	AllowedMethods   []string `env:"OAUTH_CORS_METHODS,default:GET,POST,OPTIONS"`
	AllowedHeaders   []string `env:"OAUTH_CORS_HEADERS,default:Content-Type,Authorization"`
	AllowCredentials bool     `env:"OAUTH_CORS_CREDENTIALS,default:true"`
	MaxAge           int      `env:"OAUTH_CORS_MAX_AGE,default:3600"`

	// Rate limiting
	EnableRateLimiting bool          `env:"OAUTH_RATE_LIMITING,default:true"`
	RateLimit          int           `env:"OAUTH_RATE_LIMIT,default:100"`
	RateInterval       time.Duration `env:"OAUTH_RATE_INTERVAL,default:1m"`
	RateBurstSize      int           `env:"OAUTH_RATE_BURST,default:200"`

	// Request logging
	EnableLogging    bool `env:"OAUTH_REQUEST_LOGGING,default:true"`
	LogSensitiveData bool `env:"OAUTH_LOG_SENSITIVE,default:false"`

	// Timeout configuration
	RequestTimeout time.Duration `env:"OAUTH_REQUEST_TIMEOUT,default:30s"`
	IdleTimeout    time.Duration `env:"OAUTH_IDLE_TIMEOUT,default:120s"`

	// Security
	RequireHTTPS   bool     `env:"OAUTH_REQUIRE_HTTPS,default:true"`
	TrustedProxies []string `env:"OAUTH_TRUSTED_PROXIES"`
}

MiddlewareConfig configures the OAuth middleware

type MonitoringConfig ΒΆ added in v0.1.1

type MonitoringConfig struct {
	Enabled         bool          `env:"OAUTH_MONITORING_ENABLED,default:true"`
	MetricsInterval time.Duration `env:"OAUTH_METRICS_INTERVAL,default:1m"`
	RetentionPeriod time.Duration `env:"OAUTH_METRICS_RETENTION,default:24h"`
	ExportEndpoint  string        `env:"OAUTH_METRICS_ENDPOINT"`
	ExportFormat    string        `env:"OAUTH_METRICS_FORMAT,default:json"`
}

MonitoringConfig configures the monitoring service

type MonitoringService ΒΆ added in v0.1.1

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

MonitoringService provides monitoring capabilities

func NewMonitoringService ΒΆ added in v0.1.1

func NewMonitoringService(config MonitoringConfig) *MonitoringService

NewMonitoringService creates a new monitoring service

func (*MonitoringService) GetCollector ΒΆ added in v0.1.1

func (s *MonitoringService) GetCollector() MetricsCollector

GetCollector returns the metrics collector

func (*MonitoringService) Start ΒΆ added in v0.1.1

func (s *MonitoringService) Start()

Start starts the monitoring service

func (*MonitoringService) Stop ΒΆ added in v0.1.1

func (s *MonitoringService) Stop()

Stop stops the monitoring service

type MultiProviderBuilder ΒΆ added in v0.1.1

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

WithPrefix creates a builder for multi-provider with custom prefix

func WithMultiProviderPrefix ΒΆ added in v0.1.1

func WithMultiProviderPrefix(prefix string) *MultiProviderBuilder

WithPrefix creates a new multi-provider builder with custom prefix

func (*MultiProviderBuilder) Init ΒΆ added in v0.1.1

func (b *MultiProviderBuilder) Init() error

Init initializes multi-provider with the builder's prefix

type MultiProviderConfig ΒΆ added in v0.1.1

type MultiProviderConfig struct {
	// Provider configurations mapped by name
	Providers map[string]ProviderConfig `env:"OAUTH_PROVIDERS"`

	// Global settings
	PKCEEnabled        bool          `env:"OAUTH_PKCE_ENABLED,default:true"`
	PKCEMethod         string        `env:"OAUTH_PKCE_METHOD,default:S256"`
	SessionTimeout     time.Duration `env:"OAUTH_SESSION_TIMEOUT,default:5m"`
	TokenCacheDuration time.Duration `env:"OAUTH_TOKEN_CACHE_DURATION,default:1h"`
	StateGenerator     string        `env:"OAUTH_STATE_GENERATOR,default:secure"`
	HTTPTimeout        time.Duration `env:"OAUTH_HTTP_TIMEOUT,default:30s"`

	// Security settings
	EncryptSessions bool   `env:"OAUTH_ENCRYPT_SESSIONS,default:false"`
	SecretKey       string `env:"OAUTH_SECRET_KEY"`

	// Debug mode
	Debug bool `env:"OAUTH_DEBUG,default:false"`
}

MultiProviderConfig defines configuration for multi-provider service

func GetMultiProviderConfig ΒΆ added in v0.1.1

func GetMultiProviderConfig(opts ...config.LoadOptions) (*MultiProviderConfig, error)

GetMultiProviderConfig loads multi-provider config from environment

type MultiProviderConfigFromEnv ΒΆ added in v0.1.1

type MultiProviderConfigFromEnv struct {
	// Provider configurations as JSON string
	ProvidersJSON string `env:"OAUTH_PROVIDERS"`

	// Global settings
	PKCEEnabled        bool          `env:"OAUTH_PKCE_ENABLED,default:true"`
	PKCEMethod         string        `env:"OAUTH_PKCE_METHOD,default:S256"`
	SessionTimeout     time.Duration `env:"OAUTH_SESSION_TIMEOUT,default:5m"`
	TokenCacheDuration time.Duration `env:"OAUTH_TOKEN_CACHE_DURATION,default:1h"`
	StateGenerator     string        `env:"OAUTH_STATE_GENERATOR,default:secure"`
	HTTPTimeout        time.Duration `env:"OAUTH_HTTP_TIMEOUT,default:30s"`

	// Security settings
	EncryptSessions bool   `env:"OAUTH_ENCRYPT_SESSIONS,default:false"`
	SecretKey       string `env:"OAUTH_SECRET_KEY"`

	// Debug mode
	Debug bool `env:"OAUTH_DEBUG,default:false"`
}

MultiProviderConfigFromEnv loads multi-provider configuration from environment

type MultiProviderService ΒΆ added in v0.1.1

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

MultiProviderService manages multiple OAuth providers

func GetMultiProviderService ΒΆ added in v0.1.1

func GetMultiProviderService() *MultiProviderService

GetMultiProviderService returns the global multi-provider service

func NewMultiProviderService ΒΆ added in v0.1.1

func NewMultiProviderService(config MultiProviderConfig) (*MultiProviderService, error)

NewMultiProviderService creates a new multi-provider OAuth service

func OAuthMulti ΒΆ added in v0.1.1

func OAuthMulti() *MultiProviderService

OAuthMulti returns the global multi-provider service (alias)

func (*MultiProviderService) Exchange ΒΆ added in v0.1.1

func (s *MultiProviderService) Exchange(ctx context.Context, providerName, code, state string) (*Token, error)

Exchange exchanges an authorization code for tokens

func (*MultiProviderService) GetAuthURL ΒΆ added in v0.1.1

func (s *MultiProviderService) GetAuthURL(ctx context.Context, providerName string, opts ...AuthOption) (string, string, error)

GetAuthURL generates an authorization URL for the specified provider

func (*MultiProviderService) GetProvider ΒΆ added in v0.1.1

func (s *MultiProviderService) GetProvider(name string) (Provider, error)

GetProvider retrieves a registered provider by name

func (*MultiProviderService) GetUserInfo ΒΆ added in v0.1.1

func (s *MultiProviderService) GetUserInfo(ctx context.Context, providerName, accessToken string) (*UserInfo, error)

GetUserInfo retrieves user information from the specified provider

func (*MultiProviderService) ListProviders ΒΆ added in v0.1.1

func (s *MultiProviderService) ListProviders() []string

ListProviders returns a list of registered provider names

func (*MultiProviderService) RefreshToken ΒΆ added in v0.1.1

func (s *MultiProviderService) RefreshToken(ctx context.Context, providerName, refreshToken string) (*Token, error)

RefreshToken refreshes an access token for the specified provider

func (*MultiProviderService) RegisterProvider ΒΆ added in v0.1.1

func (s *MultiProviderService) RegisterProvider(name string, provider Provider) error

RegisterProvider registers a new OAuth provider

func (*MultiProviderService) RevokeToken ΒΆ added in v0.1.1

func (s *MultiProviderService) RevokeToken(ctx context.Context, providerName, token string) error

RevokeToken revokes a token for the specified provider

func (*MultiProviderService) UnregisterProvider ΒΆ added in v0.1.1

func (s *MultiProviderService) UnregisterProvider(name string) error

UnregisterProvider removes a provider

func (*MultiProviderService) ValidateState ΒΆ added in v0.1.1

func (s *MultiProviderService) ValidateState(ctx context.Context, state string) (*SessionData, error)

ValidateState validates the state parameter for CSRF protection

type OAuthError ΒΆ

type OAuthError struct {
	Code        string // OAuth error code (e.g., "invalid_request")
	Description string // Human-readable error description
	URI         string // Optional URI with error details
	Provider    string // Provider where error occurred
	Err         error  // Underlying error
}

OAuthError represents a detailed OAuth error

func NewOAuthError ΒΆ

func NewOAuthError(provider, code, description string) *OAuthError

NewOAuthError creates a new OAuth error

func ParseOAuthError ΒΆ

func ParseOAuthError(provider string, code, description, uri string) *OAuthError

ParseOAuthError parses OAuth error from response

func WrapOAuthError ΒΆ

func WrapOAuthError(provider string, err error) *OAuthError

WrapOAuthError wraps an error with OAuth context

func (*OAuthError) Error ΒΆ

func (e *OAuthError) Error() string

Error implements the error interface

func (*OAuthError) Is ΒΆ

func (e *OAuthError) Is(target error) bool

Is checks if the error matches a target error

func (*OAuthError) Unwrap ΒΆ

func (e *OAuthError) Unwrap() error

Unwrap returns the underlying error

type PKCEChallenge ΒΆ

type PKCEChallenge struct {
	Verifier        string `json:"verifier"`
	Challenge       string `json:"challenge"`
	ChallengeMethod string `json:"challenge_method"`
}

PKCEChallenge represents PKCE challenge parameters

func GeneratePKCEChallenge ΒΆ

func GeneratePKCEChallenge(method string) (*PKCEChallenge, error)

GeneratePKCEChallenge generates a PKCE challenge with verifier and challenge

func GeneratePKCEChallengeWithLength ΒΆ added in v0.1.1

func GeneratePKCEChallengeWithLength(method string, length int) (*PKCEChallenge, error)

GeneratePKCEChallengeWithLength generates a PKCE challenge with specified verifier length

type Provider ΒΆ

type Provider interface {
	// GetAuthURL returns the authorization URL with PKCE parameters if enabled
	GetAuthURL(state string, pkce *PKCEChallenge) string

	// Exchange exchanges an authorization code for tokens
	Exchange(ctx context.Context, code string, pkce *PKCEChallenge) (*Token, error)

	// RefreshToken refreshes an access token using a refresh token
	RefreshToken(ctx context.Context, refreshToken string) (*Token, error)

	// GetUserInfo retrieves user information using an access token
	GetUserInfo(ctx context.Context, accessToken string) (*UserInfo, error)

	// Name returns the provider name
	Name() string

	// SupportsRefresh indicates if the provider supports token refresh
	SupportsRefresh() bool

	// SupportsPKCE indicates if the provider supports PKCE
	SupportsPKCE() bool

	// RevokeToken revokes an access or refresh token
	RevokeToken(ctx context.Context, token string) error

	// ValidateConfig validates the provider configuration
	ValidateConfig() error
}

Provider defines the interface that all OAuth providers must implement

func NewAppleProvider ΒΆ

func NewAppleProvider(config ProviderConfig) (Provider, error)

func NewCustomProvider ΒΆ

func NewCustomProvider(config ProviderConfig) (Provider, error)

func NewGitHubProvider ΒΆ

func NewGitHubProvider(config ProviderConfig) (Provider, error)

func NewGoogleProvider ΒΆ

func NewGoogleProvider(config ProviderConfig) (Provider, error)

func NewTwitterProvider ΒΆ

func NewTwitterProvider(config ProviderConfig) (Provider, error)

type ProviderConfig ΒΆ

type ProviderConfig struct {
	// Provider type (google, github, apple, twitter, custom)
	Type         string     `json:"type,omitempty" env:"TYPE"`
	ClientID     string     `json:"client_id" env:"CLIENT_ID"`
	ClientSecret string     `json:"client_secret,omitempty" env:"CLIENT_SECRET"`
	RedirectURL  string     `json:"redirect_url" env:"REDIRECT_URL"`
	Scopes       []string   `json:"scopes,omitempty" env:"SCOPES"`
	AuthURL      string     `json:"auth_url,omitempty" env:"AUTH_URL"`
	TokenURL     string     `json:"token_url,omitempty" env:"TOKEN_URL"`
	UserInfoURL  string     `json:"userinfo_url,omitempty" env:"USERINFO_URL"`
	RevokeURL    string     `json:"revoke_url,omitempty" env:"REVOKE_URL"`
	HTTPClient   HTTPClient `json:"-"`
	Debug        bool       `json:"debug,omitempty" env:"DEBUG"`

	// Apple-specific
	TeamID     string `json:"team_id,omitempty" env:"APPLE_TEAM_ID"`
	KeyID      string `json:"key_id,omitempty" env:"APPLE_KEY_ID"`
	PrivateKey string `json:"private_key,omitempty" env:"APPLE_PRIVATE_KEY"`

	// Twitter-specific
	APIVersion string `json:"api_version,omitempty" env:"TWITTER_API_VERSION"`
}

ProviderConfig represents configuration for a specific OAuth provider

type ProviderMetric ΒΆ added in v0.1.1

type ProviderMetric struct {
	AuthRequests     MetricCounter `json:"auth_requests"`
	TokenExchanges   MetricCounter `json:"token_exchanges"`
	TokenRefreshes   MetricCounter `json:"token_refreshes"`
	UserInfoRequests MetricCounter `json:"user_info_requests"`
	Errors           int64         `json:"errors"`
	AverageLatency   time.Duration `json:"average_latency"`
	LastError        time.Time     `json:"last_error,omitempty"`
	LastSuccess      time.Time     `json:"last_success,omitempty"`
}

ProviderMetric represents metrics for a specific provider

type ProviderWithCircuitBreaker ΒΆ added in v0.1.1

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

ProviderWithCircuitBreaker wraps a Provider with circuit breaker protection

func NewProviderWithCircuitBreaker ΒΆ added in v0.1.1

func NewProviderWithCircuitBreaker(provider Provider, config CircuitBreakerConfig) *ProviderWithCircuitBreaker

NewProviderWithCircuitBreaker creates a new provider with circuit breaker

func (*ProviderWithCircuitBreaker) Exchange ΒΆ added in v0.1.1

func (p *ProviderWithCircuitBreaker) Exchange(ctx context.Context, code string, pkce *PKCEChallenge) (*Token, error)

Exchange exchanges an authorization code for tokens

func (*ProviderWithCircuitBreaker) GetAuthURL ΒΆ added in v0.1.1

func (p *ProviderWithCircuitBreaker) GetAuthURL(state string, pkce *PKCEChallenge) string

GetAuthURL generates an authorization URL

func (*ProviderWithCircuitBreaker) GetCircuitStats ΒΆ added in v0.1.1

func (p *ProviderWithCircuitBreaker) GetCircuitStats() *CircuitStats

GetCircuitStats returns circuit breaker statistics

func (*ProviderWithCircuitBreaker) GetUserInfo ΒΆ added in v0.1.1

func (p *ProviderWithCircuitBreaker) GetUserInfo(ctx context.Context, accessToken string) (*UserInfo, error)

GetUserInfo retrieves user information

func (*ProviderWithCircuitBreaker) Name ΒΆ added in v0.1.1

Name returns the provider name

func (*ProviderWithCircuitBreaker) RefreshToken ΒΆ added in v0.1.1

func (p *ProviderWithCircuitBreaker) RefreshToken(ctx context.Context, refreshToken string) (*Token, error)

RefreshToken refreshes an access token

func (*ProviderWithCircuitBreaker) RevokeToken ΒΆ added in v0.1.1

func (p *ProviderWithCircuitBreaker) RevokeToken(ctx context.Context, token string) error

RevokeToken revokes an access or refresh token

func (*ProviderWithCircuitBreaker) SupportsPKCE ΒΆ added in v0.1.1

func (p *ProviderWithCircuitBreaker) SupportsPKCE() bool

SupportsPKCE returns true if the provider supports PKCE

func (*ProviderWithCircuitBreaker) SupportsRefresh ΒΆ added in v0.1.1

func (p *ProviderWithCircuitBreaker) SupportsRefresh() bool

SupportsRefresh returns true if the provider supports token refresh

func (*ProviderWithCircuitBreaker) ValidateConfig ΒΆ added in v0.1.1

func (p *ProviderWithCircuitBreaker) ValidateConfig() error

ValidateConfig validates the provider configuration

type RateLimitStatus ΒΆ added in v0.1.1

type RateLimitStatus struct {
	Limit      int           `json:"limit"`
	Remaining  int           `json:"remaining"`
	Reset      time.Time     `json:"reset"`
	RetryAfter time.Duration `json:"retry_after,omitempty"`
}

RateLimitStatus provides information about current rate limit state

type RateLimiter ΒΆ added in v0.1.1

type RateLimiter interface {
	// Allow checks if a request should be allowed
	Allow(ctx context.Context, key string) (bool, error)
	// AllowN checks if n requests should be allowed
	AllowN(ctx context.Context, key string, n int) (bool, error)
	// Reset resets the rate limit for a key
	Reset(ctx context.Context, key string) error
	// GetStatus returns the current rate limit status for a key
	GetStatus(ctx context.Context, key string) (*RateLimitStatus, error)
}

RateLimiter provides rate limiting functionality for OAuth operations

type RateLimiterConfig ΒΆ added in v0.1.1

type RateLimiterConfig struct {
	Rate            int           // Number of tokens per interval
	Interval        time.Duration // Time interval for rate
	BurstSize       int           // Maximum burst size
	MaxEntries      int           // Maximum number of tracked entries
	CleanupInterval time.Duration // Interval for cleaning up old entries
}

RateLimiterConfig configures the rate limiter

type RequestLog ΒΆ added in v0.1.1

type RequestLog struct {
	Method       string        `json:"method"`
	Path         string        `json:"path"`
	StatusCode   int           `json:"status_code"`
	Duration     time.Duration `json:"duration"`
	RemoteAddr   string        `json:"remote_addr"`
	UserAgent    string        `json:"user_agent"`
	RequestID    string        `json:"request_id"`
	BytesWritten int           `json:"bytes_written"`
	StartTime    time.Time     `json:"start_time"`
}

RequestLog represents a logged request

type ResponseTime ΒΆ added in v0.1.1

type ResponseTime struct {
	Count   int64         `json:"count"`
	Total   time.Duration `json:"total"`
	Min     time.Duration `json:"min"`
	Max     time.Duration `json:"max"`
	Average time.Duration `json:"average"`
	P50     time.Duration `json:"p50"`
	P95     time.Duration `json:"p95"`
	P99     time.Duration `json:"p99"`
}

ResponseTime represents response time statistics

type SecureStateGenerator ΒΆ

type SecureStateGenerator struct{}

SecureStateGenerator generates cryptographically secure state tokens

func (*SecureStateGenerator) Generate ΒΆ

func (g *SecureStateGenerator) Generate() (string, error)

type Service ΒΆ

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

Service is the main OAuth service

func GetService ΒΆ

func GetService() *Service

GetService returns the global OAuth service instance

func New ΒΆ

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

New creates a new OAuth service instance

func OAuth ΒΆ

func OAuth() *Service

OAuth is an alias for GetService()

func (*Service) Config ΒΆ

func (s *Service) Config() Config

Config returns the service configuration

func (*Service) Exchange ΒΆ

func (s *Service) Exchange(ctx context.Context, code, state string) (*Token, error)

Exchange exchanges an authorization code for tokens

func (*Service) GetAuthURL ΒΆ

func (s *Service) GetAuthURL(ctx context.Context) (string, error)

GetAuthURL generates an authorization URL

func (*Service) GetUserInfo ΒΆ

func (s *Service) GetUserInfo(ctx context.Context, accessToken string) (*UserInfo, error)

GetUserInfo retrieves user information

func (*Service) Provider ΒΆ

func (s *Service) Provider() Provider

Provider returns the current provider

func (*Service) RefreshToken ΒΆ

func (s *Service) RefreshToken(ctx context.Context, refreshToken string) (*Token, error)

RefreshToken refreshes an access token

func (*Service) ValidateState ΒΆ

func (s *Service) ValidateState(ctx context.Context, state string) error

ValidateState validates the state parameter for CSRF protection

type SessionData ΒΆ

type SessionData struct {
	State         string                 `json:"state"`
	PKCEChallenge *PKCEChallenge         `json:"pkce_challenge,omitempty"`
	CreatedAt     time.Time              `json:"created_at"`
	ExpiresAt     time.Time              `json:"expires_at"`
	Provider      string                 `json:"provider"`
	Metadata      map[string]interface{} `json:"metadata,omitempty"`
}

SessionData represents OAuth session data that can be stored

func (*SessionData) IsExpired ΒΆ

func (s *SessionData) IsExpired() bool

IsExpired checks if the session data is expired

type SessionStore ΒΆ

type SessionStore interface {
	// Store stores session data with a key
	Store(ctx context.Context, key string, data *SessionData) error

	// Retrieve gets session data by key
	Retrieve(ctx context.Context, key string) (*SessionData, error)

	// Delete removes session data by key
	Delete(ctx context.Context, key string) error

	// RetrieveAndDelete atomically retrieves and deletes session data
	// This prevents replay attacks by ensuring a session can only be used once
	RetrieveAndDelete(ctx context.Context, key string) (*SessionData, error)
}

SessionStore interface for storing OAuth session data

type SlidingWindowLimiter ΒΆ added in v0.1.1

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

SlidingWindowLimiter implements sliding window algorithm for rate limiting

func NewSlidingWindowLimiter ΒΆ added in v0.1.1

func NewSlidingWindowLimiter(config RateLimiterConfig) *SlidingWindowLimiter

NewSlidingWindowLimiter creates a new sliding window rate limiter

func (*SlidingWindowLimiter) Allow ΒΆ added in v0.1.1

func (l *SlidingWindowLimiter) Allow(ctx context.Context, key string) (bool, error)

Allow checks if a single request should be allowed

func (*SlidingWindowLimiter) AllowN ΒΆ added in v0.1.1

func (l *SlidingWindowLimiter) AllowN(ctx context.Context, key string, n int) (bool, error)

AllowN checks if n requests should be allowed

func (*SlidingWindowLimiter) GetStatus ΒΆ added in v0.1.1

func (l *SlidingWindowLimiter) GetStatus(ctx context.Context, key string) (*RateLimitStatus, error)

GetStatus returns the current rate limit status for a key

func (*SlidingWindowLimiter) Reset ΒΆ added in v0.1.1

func (l *SlidingWindowLimiter) Reset(ctx context.Context, key string) error

Reset resets the rate limit for a key

type StateGenerator ΒΆ

type StateGenerator interface {
	Generate() (string, error)
}

StateGenerator interface for generating state tokens

type StringOrArray ΒΆ added in v0.1.1

type StringOrArray []string

StringOrArray handles fields that can be either string or []string

func (*StringOrArray) UnmarshalJSON ΒΆ added in v0.1.1

func (s *StringOrArray) UnmarshalJSON(data []byte) error

type Token ΒΆ

type Token struct {
	AccessToken  string    `json:"access_token"`
	TokenType    string    `json:"token_type"`
	RefreshToken string    `json:"refresh_token,omitempty"`
	ExpiresIn    int       `json:"expires_in,omitempty"`
	ExpiresAt    time.Time `json:"expires_at,omitempty"`
	IDToken      string    `json:"id_token,omitempty"` // For OpenID Connect
	Scope        string    `json:"scope,omitempty"`
}

Token represents OAuth tokens

func (*Token) IsExpired ΒΆ

func (t *Token) IsExpired() bool

IsExpired checks if the token is expired

func (*Token) TimeUntilExpiry ΒΆ

func (t *Token) TimeUntilExpiry() time.Duration

TimeUntilExpiry returns the duration until the token expires

type TokenBucketLimiter ΒΆ added in v0.1.1

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

TokenBucketLimiter implements token bucket algorithm for rate limiting

func NewTokenBucketLimiter ΒΆ added in v0.1.1

func NewTokenBucketLimiter(config RateLimiterConfig) *TokenBucketLimiter

NewTokenBucketLimiter creates a new token bucket rate limiter

func (*TokenBucketLimiter) Allow ΒΆ added in v0.1.1

func (l *TokenBucketLimiter) Allow(ctx context.Context, key string) (bool, error)

Allow checks if a single request should be allowed

func (*TokenBucketLimiter) AllowN ΒΆ added in v0.1.1

func (l *TokenBucketLimiter) AllowN(ctx context.Context, key string, n int) (bool, error)

AllowN checks if n requests should be allowed

func (*TokenBucketLimiter) GetStatus ΒΆ added in v0.1.1

func (l *TokenBucketLimiter) GetStatus(ctx context.Context, key string) (*RateLimitStatus, error)

GetStatus returns the current rate limit status for a key

func (*TokenBucketLimiter) Reset ΒΆ added in v0.1.1

func (l *TokenBucketLimiter) Reset(ctx context.Context, key string) error

Reset resets the rate limit for a key

type TokenEncryptor ΒΆ added in v0.1.1

type TokenEncryptor interface {
	Encrypt(data []byte) ([]byte, error)
	Decrypt(data []byte) ([]byte, error)
}

TokenEncryptor interface for token encryption

type TokenManager ΒΆ added in v0.1.1

type TokenManager interface {
	// Basic operations
	CacheToken(ctx context.Context, userID, provider string, token *Token) error
	GetCachedToken(ctx context.Context, userID, provider string) (*Token, error)
	DeleteToken(ctx context.Context, userID, provider string) error

	// Advanced operations
	RefreshIfNeeded(ctx context.Context, userID, provider string) (*Token, error)
	RevokeToken(ctx context.Context, userID, provider string) error
	GetAllUserTokens(ctx context.Context, userID string) (map[string]*Token, error)

	// Bulk operations
	RefreshExpiredTokens(ctx context.Context) error
	CleanupExpiredTokens(ctx context.Context) error

	// Statistics
	GetTokenStats() *TokenStats
}

TokenManager provides advanced token lifecycle management

type TokenManagerConfig ΒΆ added in v0.1.1

type TokenManagerConfig struct {
	Store            TokenStore
	ProviderService  *MultiProviderService
	Encryptor        TokenEncryptor
	AutoRefresh      bool
	RefreshThreshold time.Duration
	CleanupInterval  time.Duration
	MaxTokensPerUser int
}

TokenManagerConfig configures the advanced token manager

type TokenMetadata ΒΆ added in v0.1.1

type TokenMetadata struct {
	UserID       string    `json:"user_id"`
	Provider     string    `json:"provider"`
	CachedAt     time.Time `json:"cached_at"`
	LastAccessed time.Time `json:"last_accessed"`
	AccessCount  int       `json:"access_count"`
	RefreshCount int       `json:"refresh_count"`
	LastRefresh  time.Time `json:"last_refresh,omitempty"`
}

TokenMetadata stores additional information about a token

type TokenStats ΒΆ added in v0.1.1

type TokenStats struct {
	TotalTokens       int
	ActiveTokens      int
	ExpiredTokens     int
	RefreshableTokens int
	ProviderCounts    map[string]int
	LastCleanup       time.Time
	LastRefresh       time.Time
}

TokenStats provides statistics about cached tokens

type TokenStore ΒΆ

type TokenStore interface {
	// Store stores a token with a key
	Store(ctx context.Context, key string, token *Token) error

	// Retrieve gets a token by key
	Retrieve(ctx context.Context, key string) (*Token, error)

	// Delete removes a token by key
	Delete(ctx context.Context, key string) error
}

TokenStore interface for caching OAuth tokens

type TwitterProvider ΒΆ added in v0.1.1

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

TwitterProvider implements OAuth provider for Twitter (X)

func NewTwitter ΒΆ added in v0.1.1

func NewTwitter(config ProviderConfig) *TwitterProvider

NewTwitter creates a new Twitter OAuth provider

func (*TwitterProvider) Exchange ΒΆ added in v0.1.1

func (t *TwitterProvider) Exchange(ctx context.Context, code string, pkce *PKCEChallenge) (*Token, error)

Exchange exchanges an authorization code for tokens

func (*TwitterProvider) GetAuthURL ΒΆ added in v0.1.1

func (t *TwitterProvider) GetAuthURL(state string, pkce *PKCEChallenge) string

GetAuthURL returns the authorization URL Note: Twitter OAuth 2.0 with PKCE doesn't support the traditional PKCE interface but uses PKCE internally for public clients

func (*TwitterProvider) GetUserInfo ΒΆ added in v0.1.1

func (t *TwitterProvider) GetUserInfo(ctx context.Context, accessToken string) (*UserInfo, error)

GetUserInfo retrieves user information using the access token

func (*TwitterProvider) Name ΒΆ added in v0.1.1

func (t *TwitterProvider) Name() string

Name returns the provider name

func (*TwitterProvider) RefreshToken ΒΆ added in v0.1.1

func (t *TwitterProvider) RefreshToken(ctx context.Context, refreshToken string) (*Token, error)

RefreshToken refreshes the access token using a refresh token

func (*TwitterProvider) RevokeToken ΒΆ added in v0.1.1

func (t *TwitterProvider) RevokeToken(ctx context.Context, token string) error

RevokeToken revokes the access token

func (*TwitterProvider) SetHTTPClient ΒΆ added in v0.1.1

func (t *TwitterProvider) SetHTTPClient(client HTTPClient)

SetHTTPClient sets a custom HTTP client

func (*TwitterProvider) SupportsPKCE ΒΆ added in v0.1.1

func (t *TwitterProvider) SupportsPKCE() bool

SupportsPKCE indicates if the provider supports PKCE

func (*TwitterProvider) SupportsRefresh ΒΆ added in v0.1.1

func (t *TwitterProvider) SupportsRefresh() bool

SupportsRefresh indicates if the provider supports token refresh

func (*TwitterProvider) ValidateConfig ΒΆ added in v0.1.1

func (t *TwitterProvider) ValidateConfig() error

ValidateConfig validates the provider configuration

type TwitterUser ΒΆ added in v0.1.1

type TwitterUser struct {
	ID              string `json:"id"`
	Username        string `json:"username"`
	Name            string `json:"name"`
	ProfileImageURL string `json:"profile_image_url"`
	Description     string `json:"description"`
	Location        string `json:"location"`
	URL             string `json:"url"`
	Verified        bool   `json:"verified"`
	Protected       bool   `json:"protected"`
	PublicMetrics   struct {
		FollowersCount int `json:"followers_count"`
		FollowingCount int `json:"following_count"`
		TweetCount     int `json:"tweet_count"`
		ListedCount    int `json:"listed_count"`
	} `json:"public_metrics"`
}

TwitterUser represents the user data returned by Twitter API v2

type TwitterUserResponse ΒΆ added in v0.1.1

type TwitterUserResponse struct {
	Data   TwitterUser `json:"data"`
	Errors []struct {
		Detail string `json:"detail"`
		Title  string `json:"title"`
		Type   string `json:"type"`
	} `json:"errors,omitempty"`
}

TwitterUserResponse represents the response from Twitter user endpoint

type UUIDStateGenerator ΒΆ

type UUIDStateGenerator struct{}

UUIDStateGenerator generates UUID-based state tokens

func (*UUIDStateGenerator) Generate ΒΆ

func (g *UUIDStateGenerator) Generate() (string, error)

type UserInfo ΒΆ

type UserInfo struct {
	ID            string                 `json:"id"`
	Email         string                 `json:"email"`
	EmailVerified bool                   `json:"email_verified"`
	Name          string                 `json:"name"`
	FirstName     string                 `json:"first_name"`
	LastName      string                 `json:"last_name"`
	Picture       string                 `json:"picture"`
	Locale        string                 `json:"locale"`
	Provider      string                 `json:"provider"`
	Raw           map[string]interface{} `json:"raw"` // Raw response from provider
}

UserInfo represents user information from OAuth providers

Directories ΒΆ

Path Synopsis

Jump to

Keyboard shortcuts

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