> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/trailbaseio/trailbase/llms.txt
> Use this file to discover all available pages before exploring further.

# OAuth Providers

> Configure third-party authentication with OAuth 2.0 providers

## Overview

TrailBase supports OAuth 2.0 authentication with popular identity providers. Users can sign in with their existing accounts from Google, GitHub, Microsoft, and other providers.

## Supported Providers

TrailBase includes built-in support for:

<CardGroup cols={3}>
  <Card title="Google" icon="google">
    Google OAuth 2.0
  </Card>

  <Card title="GitHub" icon="github">
    GitHub OAuth
  </Card>

  <Card title="Microsoft" icon="microsoft">
    Microsoft Azure AD
  </Card>

  <Card title="GitLab" icon="gitlab">
    GitLab OAuth
  </Card>

  <Card title="Facebook" icon="facebook">
    Facebook Login
  </Card>

  <Card title="Discord" icon="discord">
    Discord OAuth 2.0
  </Card>

  <Card title="Twitch" icon="twitch">
    Twitch Authentication
  </Card>

  <Card title="Yandex" icon="y">
    Yandex OAuth
  </Card>

  <Card title="Apple" icon="apple">
    Sign in with Apple
  </Card>

  <Card title="OIDC" icon="key">
    Custom OpenID Connect
  </Card>
</CardGroup>

## Configuration

<Warning>
  OAuth requires a public URL for redirects. Configure `server.site_url` in your config:

  ```protobuf theme={null}
  server {
    site_url: "https://yourdomain.com"
  }
  ```
</Warning>

### Basic Provider Configuration

```protobuf theme={null}
auth {
  oauth_providers {
    key: "google"
    value {
      provider_id: GOOGLE
      client_id: "your-client-id.apps.googleusercontent.com"
      client_secret: "your-client-secret"
    }
  }
  
  oauth_providers {
    key: "github"
    value {
      provider_id: GITLAB  # Note: Use GITLAB provider_id for GitHub
      client_id: "your-github-oauth-app-id"
      client_secret: "your-github-oauth-app-secret"
    }
  }
}
```

## Provider Setup Guides

### Google OAuth

<Steps>
  <Step title="Create OAuth Client">
    1. Go to [Google Cloud Console](https://console.cloud.google.com/)
    2. Create a new project or select existing
    3. Navigate to "APIs & Services" → "Credentials"
    4. Click "Create Credentials" → "OAuth client ID"
    5. Choose "Web application"
  </Step>

  <Step title="Configure Redirect URIs">
    Add authorized redirect URI:

    ```
    https://yourdomain.com/api/auth/v1/oauth/google/callback
    ```
  </Step>

  <Step title="Add to Configuration">
    ```protobuf theme={null}
    auth {
      oauth_providers {
        key: "google"
        value {
          provider_id: GOOGLE
          client_id: "123456789.apps.googleusercontent.com"
          client_secret: "your-client-secret"
        }
      }
    }
    ```
  </Step>
</Steps>

### GitHub OAuth

<Steps>
  <Step title="Create OAuth App">
    1. Go to [GitHub Developer Settings](https://github.com/settings/developers)
    2. Click "New OAuth App"
    3. Fill in application details
  </Step>

  <Step title="Set Callback URL">
    ```
    https://yourdomain.com/api/auth/v1/oauth/github/callback
    ```
  </Step>

  <Step title="Configure TrailBase">
    ```protobuf theme={null}
    auth {
      oauth_providers {
        key: "github"
        value {
          provider_id: GITLAB  # Uses GitLab provider internally
          client_id: "your-client-id"
          client_secret: "your-client-secret"
          # GitHub uses GitLab OAuth URL structure
        }
      }
    }
    ```
  </Step>
</Steps>

### Microsoft Azure AD

<Steps>
  <Step title="Register Application">
    1. Go to [Azure Portal](https://portal.azure.com/)
    2. Navigate to "Azure Active Directory" → "App registrations"
    3. Click "New registration"
    4. Name your application
  </Step>

  <Step title="Configure Redirect URI">
    Under "Authentication", add:

    ```
    https://yourdomain.com/api/auth/v1/oauth/microsoft/callback
    ```
  </Step>

  <Step title="Create Client Secret">
    1. Go to "Certificates & secrets"
    2. Click "New client secret"
    3. Copy the secret value immediately
  </Step>

  <Step title="Add to TrailBase">
    ```protobuf theme={null}
    auth {
      oauth_providers {
        key: "microsoft"
        value {
          provider_id: MICROSOFT
          client_id: "your-application-id"
          client_secret: "your-client-secret"
        }
      }
    }
    ```
  </Step>
</Steps>

### Discord

<Steps>
  <Step title="Create Application">
    1. Go to [Discord Developer Portal](https://discord.com/developers/applications)
    2. Click "New Application"
    3. Go to "OAuth2" settings
  </Step>

  <Step title="Add Redirect">
    ```
    https://yourdomain.com/api/auth/v1/oauth/discord/callback
    ```
  </Step>

  <Step title="Configure">
    ```protobuf theme={null}
    auth {
      oauth_providers {
        key: "discord"
        value {
          provider_id: DISCORD
          client_id: "your-client-id"
          client_secret: "your-client-secret"
        }
      }
    }
    ```
  </Step>
</Steps>

### GitLab

```protobuf theme={null}
auth {
  oauth_providers {
    key: "gitlab"
    value {
      provider_id: GITLAB
      client_id: "your-application-id"
      client_secret: "your-secret"
      # Optional: self-hosted GitLab
      # gitlab_url: "https://gitlab.example.com"
    }
  }
}
```

Redirect URI: `https://yourdomain.com/api/auth/v1/oauth/gitlab/callback`

### Custom OIDC Provider

For providers not explicitly supported, use OpenID Connect:

```protobuf theme={null}
auth {
  oauth_providers {
    key: "custom_oidc"
    value {
      provider_id: OIDC_0
      client_id: "your-client-id"
      client_secret: "your-client-secret"
      
      # OIDC discovery URL
      oidc_discovery_url: "https://accounts.example.com/.well-known/openid-configuration"
      
      # Or specify endpoints manually:
      # oidc_authorization_url: "https://accounts.example.com/oauth2/auth"
      # oidc_token_url: "https://accounts.example.com/oauth2/token"
      # oidc_userinfo_url: "https://accounts.example.com/oauth2/userinfo"
    }
  }
}
```

## OAuth Flow

TrailBase implements the OAuth 2.0 authorization code flow with PKCE:

```
┌─────────┐                                         ┌──────────┐
│ Browser │                                         │ Provider │
└────┬────┘                                         └────┬─────┘
     │                                                   │
     │  1. Click "Sign in with Google"                  │
     ├──────────────────────────────────►               │
     │     /api/auth/v1/oauth/google                    │
     │                                                   │
     │  2. Redirect to provider with                    │
     │     state, code_challenge                        │
     ├──────────────────────────────────────────────────►
     │                                                   │
     │  3. User authorizes                              │
     │                                                   │
     │  4. Redirect with auth code                      │
     │◄──────────────────────────────────────────────────┤
     │     /api/auth/v1/oauth/google/callback           │
     │                                                   │
     │  5. Exchange code for token                      │
     │     (with code_verifier)                         │
     ├──────────────────────────────────────────────────►
     │                                                   │
     │  6. Return access token                          │
     │◄──────────────────────────────────────────────────┤
     │                                                   │
     │  7. Fetch user profile                           │
     ├──────────────────────────────────────────────────►
     │                                                   │
     │  8. Return user data                             │
     │◄──────────────────────────────────────────────────┤
     │                                                   │
     │  9. Create/login user, set session cookies       │
     │◄──────────────────────────────────────────        │
     │                                                   │
```

## Security Features

### PKCE (Proof Key for Code Exchange)

TrailBase uses PKCE for all OAuth flows:

```rust theme={null}
// From crates/core/src/auth/oauth/state.rs
pub(crate) struct OAuthState {
    /// OAuth CSRF protection
    pub state: String,
    
    /// PKCE code verifier
    pub code_verifier: String,
    
    /// Optional redirect URL after successful auth
    pub redirect_url: Option<String>,
}
```

### State Parameter

Prevents CSRF attacks by validating state:

```rust theme={null}
// State is stored in encrypted JWT cookie
let state = jwt_encode(OAuthState {
    state: random_string(),
    code_verifier: generate_code_verifier(),
    redirect_url: Some("/dashboard".to_string()),
});
```

## User Linking

Users can link multiple OAuth providers to one account:

```sql theme={null}
-- User table tracks OAuth provider associations
CREATE TABLE _user (
  id BLOB PRIMARY KEY,
  email TEXT UNIQUE,
  verified INTEGER NOT NULL DEFAULT 0,
  provider_id INTEGER,  -- OAuth provider ID
  provider_user_id TEXT,  -- User ID from provider
  -- ...
);
```

## API Endpoints

### Initiate OAuth Flow

```http theme={null}
GET /api/auth/v1/oauth/{provider}
```

Redirects user to provider's authorization page.

**Query Parameters:**

* `redirect_url` (optional): Where to redirect after successful auth

**Example:**

```html theme={null}
<a href="/api/auth/v1/oauth/google?redirect_url=/dashboard">
  Sign in with Google
</a>
```

### OAuth Callback

```http theme={null}
GET /api/auth/v1/oauth/{provider}/callback
```

Handles the callback from OAuth provider. Automatically processes:

1. Validates state parameter
2. Exchanges authorization code for access token
3. Fetches user profile
4. Creates or updates user
5. Sets session cookies
6. Redirects to `redirect_url` or default page

### List Available Providers

```http theme={null}
GET /api/auth/v1/oauth/providers
```

**Response:**

```json theme={null}
{
  "providers": [
    {
      "name": "google",
      "display_name": "Google"
    },
    {
      "name": "github",
      "display_name": "GitHub"
    }
  ]
}
```

## Frontend Integration

### Sign In Buttons

```html theme={null}
<!DOCTYPE html>
<html>
<head>
  <title>Sign In</title>
  <style>
    .oauth-button {
      display: inline-flex;
      align-items: center;
      padding: 12px 24px;
      margin: 8px;
      border: 1px solid #ddd;
      border-radius: 4px;
      text-decoration: none;
      color: #333;
      background: white;
      font-family: system-ui;
    }
    .oauth-button:hover {
      background: #f5f5f5;
    }
    .oauth-button img {
      width: 20px;
      height: 20px;
      margin-right: 12px;
    }
  </style>
</head>
<body>
  <h1>Sign In</h1>
  
  <a href="/api/auth/v1/oauth/google" class="oauth-button">
    <img src="/icons/google.svg" alt="Google">
    Sign in with Google
  </a>
  
  <a href="/api/auth/v1/oauth/github" class="oauth-button">
    <img src="/icons/github.svg" alt="GitHub">
    Sign in with GitHub
  </a>
  
  <a href="/api/auth/v1/oauth/microsoft" class="oauth-button">
    <img src="/icons/microsoft.svg" alt="Microsoft">
    Sign in with Microsoft
  </a>
</body>
</html>
```

### React Component

```tsx theme={null}
import React, { useEffect, useState } from 'react';

interface Provider {
  name: string;
  display_name: string;
}

export function OAuthButtons() {
  const [providers, setProviders] = useState<Provider[]>([]);
  
  useEffect(() => {
    fetch('/api/auth/v1/oauth/providers')
      .then(res => res.json())
      .then(data => setProviders(data.providers));
  }, []);
  
  const handleOAuthLogin = (provider: string) => {
    const redirectUrl = encodeURIComponent(window.location.pathname);
    window.location.href = `/api/auth/v1/oauth/${provider}?redirect_url=${redirectUrl}`;
  };
  
  return (
    <div>
      {providers.map(provider => (
        <button
          key={provider.name}
          onClick={() => handleOAuthLogin(provider.name)}
          className="oauth-button"
        >
          Sign in with {provider.display_name}
        </button>
      ))}
    </div>
  );
}
```

## User Profile Data

OAuth providers return different user information:

```rust theme={null}
// From crates/core/src/auth/oauth/mod.rs
pub struct OAuthUser {
    pub provider_user_id: String,  // Provider's user ID
    pub provider_id: OAuthProviderId,
    pub email: Option<String>,
    pub verified: bool,
    pub name: Option<String>,
    pub avatar_url: Option<String>,
}
```

## Admin API

### List Available OAuth Providers

```bash theme={null}
curl -H "Authorization: Bearer $ADMIN_TOKEN" \
  https://api.example.com/_/admin/oauth/providers
```

**Response:**

```json theme={null}
{
  "providers": [
    {
      "id": 2,
      "name": "google",
      "display_name": "Google"
    },
    {
      "id": 3,
      "name": "github",
      "display_name": "GitHub"
    }
  ]
}
```

## Provider Implementation

Each provider implements the `OAuthProvider` trait:

```rust theme={null}
// From crates/core/src/auth/oauth/mod.rs
pub trait OAuthProvider: Send + Sync {
    fn name(&self) -> &str;
    fn provider(&self) -> OAuthProviderId;
    fn settings(&self) -> Result<OAuthClientSettings, AuthError>;
    fn oauth_scopes(&self) -> Vec<&'static str>;
    
    async fn get_user(
        &self,
        token_response: &TokenResponse
    ) -> Result<OAuthUser, AuthError>;
}
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Redirect URI mismatch">
    **Error:** "redirect\_uri\_mismatch"

    **Solution:** Ensure the callback URL in your provider settings exactly matches:

    ```
    https://yourdomain.com/api/auth/v1/oauth/{provider}/callback
    ```

    Check:

    * Protocol (http vs https)
    * Domain name
    * Port (if not 80/443)
    * Path (including `/callback`)
  </Accordion>

  <Accordion title="No site_url configured">
    **Error:** "OAuth requires a public URL"

    **Solution:** Add `site_url` to your config:

    ```protobuf theme={null}
    server {
      site_url: "https://yourdomain.com"
    }
    ```
  </Accordion>

  <Accordion title="Invalid client credentials">
    **Error:** "invalid\_client"

    **Solution:**

    * Verify client\_id is correct
    * Ensure client\_secret hasn't expired
    * Check provider dashboard for any issues
    * Regenerate credentials if necessary
  </Accordion>

  <Accordion title="Scope issues">
    **Error:** User data missing (email, name, etc.)

    **Solution:** Check OAuth scopes. TrailBase requests:

    * Google: `openid email profile`
    * GitHub: `user:email`
    * Discord: `identify email`

    Ensure these scopes are approved in your OAuth app settings.
  </Accordion>
</AccordionGroup>

## Best Practices

<Steps>
  <Step title="Use HTTPS in production">
    OAuth requires HTTPS for redirect URIs in production. Use certificates from Let's Encrypt or your provider.
  </Step>

  <Step title="Rotate secrets regularly">
    Periodically regenerate client secrets and update your configuration.
  </Step>

  <Step title="Request minimal scopes">
    Only request the OAuth scopes your application actually needs.
  </Step>

  <Step title="Handle provider outages">
    Implement fallback authentication methods (email/password) in case OAuth providers are unavailable.
  </Step>

  <Step title="Test thoroughly">
    Test OAuth flows in development before deploying to production.
  </Step>
</Steps>

## Next Steps

<CardGroup cols={2}>
  <Card title="Email" href="/advanced/email" icon="envelope">
    Configure email for fallback auth
  </Card>

  <Card title="Custom Endpoints" href="/advanced/custom-endpoints" icon="route">
    Build custom auth flows
  </Card>

  <Card title="Object Storage" href="/advanced/object-storage" icon="database">
    Store user avatars
  </Card>

  <Card title="Jobs Scheduler" href="/advanced/jobs-scheduler" icon="clock">
    Sync OAuth data
  </Card>
</CardGroup>
