Integration Guide

A deep dive into how AuthGate's proxy flow works and how to integrate it into your application.

How the flow works

AuthGate acts as an OAuth proxy between your application and OAuth providers. Here's the complete flow:

  1. Your app redirects the user to AuthGate's proxy endpoint
  2. AuthGate validates the request (project exists, provider enabled, callback URL registered)
  3. AuthGate generates a PKCE code verifier and state, then redirects to the provider's authorization page
  4. The user authenticates with the provider (e.g., Google, GitHub)
  5. The provider redirects back to AuthGate's callback endpoint
  6. AuthGate exchanges the authorization code for tokens
  7. AuthGate extracts and normalizes user info from the provider
  8. AuthGate creates or updates the end user in its database
  9. AuthGate signs a JWT with the user's info and redirects to your callback URL

Initiating the login flow

Call the proxy endpoint from your server with the API key in the Authorization header:

POST /api/proxy/{provider}
Authorization: Bearer {AUTHGATE_API_KEY}
Content-Type: application/json
  • Name
    provider
    Type
    string
    Description

    The OAuth provider to use. One of: google, github, discord, azure, apple.

  • Name
    callback_url
    Type
    string
    Description

    The URL to redirect to after authentication. Must be registered in your project's callback URLs.

  • Name
    state
    Type
    string
    Description

    Optional. An opaque value passed through to your callback URL. Useful for CSRF protection or storing redirect targets.

The project is resolved automatically from the API key. The response returns a redirect_url — redirect the user there to start the OAuth flow.

Handling the callback

After authentication, AuthGate redirects to your callback URL with tokens as query parameters:

{callback_url}?token={jwt_token}&refresh_token={refresh_token}&state={state}

The token is a short-lived JWT (5 minutes) signed with your project's secret. Always verify this token server-side using the Token Verification API — never trust it on the client.

// Server-side token verification
const res = await fetch(`${AUTHGATE_URL}/api/v1/token/verify`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ token }),
})

const { valid, user, expiresAt } = await res.json()

JWT payload

The JWT token contains the following claims:

  • Name
    sub
    Type
    string
    Description

    The AuthGate end user ID.

  • Name
    email
    Type
    string | null
    Description

    The user's email address from the provider.

  • Name
    name
    Type
    string | null
    Description

    The user's display name from the provider.

  • Name
    picture
    Type
    string | null
    Description

    URL to the user's avatar from the provider.

  • Name
    provider
    Type
    string
    Description

    The OAuth provider used (e.g., github, google).

Account linking

Account linking allows a single end user to authenticate through multiple OAuth providers. This must be explicitly enabled in your project settings (allowAccountLinking).

When enabled, there are two linking mechanisms:

Email-based linking — when a user authenticates with a new provider using an email that matches an existing end user, AuthGate links the new provider to the existing account. This only happens when allowAccountLinking is enabled; otherwise, a new end user is created.

Explicit linking — to link a new provider to a user who is already authenticated, pass link_to (the target user ID) and link_token (a valid JWT for that user, proving ownership) when initiating the OAuth flow:

{
  "callback_url": "https://myapp.com/auth/callback",
  "link_to": "user_abc123",
  "link_token": "eyJhbGciOiJIUzI1NiIs..."
}

The link_token must be a valid JWT issued by AuthGate where the sub claim matches link_to. This prevents unauthorized users from linking providers to accounts they don't own.

Error handling

Errors can occur at two stages: during request validation (before the OAuth flow starts) and during the OAuth flow itself (after the user has been redirected to the provider).

Validation errors (JSON responses)

If the initial request to /api/proxy/{provider} fails validation, AuthGate returns a JSON error response with an appropriate HTTP status code:

// 401 Unauthorized
{ "error": "Invalid API key" }

// 400 Bad Request
{ "error": "Missing callback_url parameter" }

// 400 Bad Request
{ "error": "Unsupported provider" }

// 404 Not Found
{ "error": "Project not found or inactive" }

// 403 Forbidden
{ "error": "Callback URL not registered for this provider" }

// 403 Forbidden
{ "error": "Provider not enabled for this project" }

// 429 Too Many Requests
{ "error": "Too many requests" }

OAuth callback errors (JSON responses)

If authentication fails during the callback phase (e.g., the user denies access or the code exchange fails), AuthGate returns a JSON error from the callback endpoint rather than redirecting to your app:

// 400 Bad Request — user denied access or missing params
{ "error": "Missing code or state" }

// 400 Bad Request — state was already consumed or invalid
{ "error": "Invalid state" }

// 400 Bad Request — state expired (10 minute TTL)
{ "error": "State expired" }

// 500 Internal Server Error — code exchange with provider failed
{ "error": "Token exchange failed" }

Was this page helpful?