Skip to content

OAuth

Cloudflare Zero Trust is great, and it's the easiest. But it limits you to 100 MAU on free plans. So, you can also configure Pixelflare with your OAuth providers directly. We use Auth.js under the hood to handle OAuth flows, session management, and secure cookie storage.

1. Generate Auth Secret

You'll need to generate a secure random secret for JWT encryption. You can do this with:

bash
openssl rand -base64 32

3. Set Environment Variables

Development (.env):

bash
# Required
AUTH_MODE=authjs
AUTH_SECRET=your-generated-secret-from-step-2
GITHUB_OAUTH_CLIENT_ID=your-development-github-client-id
GITHUB_OAUTH_CLIENT_SECRET=your-development-github-client-secret

How It Works

  • User clicks "Sign in with GitHub" on login page
  • User is redirected to GitHub OAuth authorization
  • After approval, GitHub redirects to /auth/callback/github
  • Auth.js exchanges code for access token
  • User is automatically provisioned with owner ID based on GitHub username or email
  • Session is stored as encrypted JWT in secure, httpOnly cookie
  • Cookie name changes based on environment:
    • Development: authjs.session-token
    • Production: __Secure-authjs.session-token (requires HTTPS)

JWT Verification

  • JWT in authjs.session-token cookie (__Secure-authjs.session-token in production)
  • Decrypts using AUTH_SECRET and cookie name as salt
  • Validates expiration (7-day default)
  • Extracts user email and session ID
  • No external cert fetching (symmetric encryption)

Flow

mermaid
sequenceDiagram
    participant Browser
    participant App Server
    participant Auth Server (GitHub)
    Note left of Browser: User clicks on "Sign in"
    Browser->>App Server: GET<br/>"api/auth/signin"
    App Server->>App Server: Computes the available<br/>sign in providers<br/>from the "providers" option
    App Server->>Browser: Redirects to Sign in page
    Note left of Browser: Sign in options<br/>are shown the user<br/>(GitHub, Twitter, etc...)
    Note left of Browser: User clicks on<br/>"Sign in with GitHub"
    Browser->>App Server: POST<br/>"api/auth/signin/github"
    App Server->>App Server: Computes sign in<br/>options for GitHub<br/>(scopes, callback URL, etc...)
    App Server->>Auth Server (GitHub): GET<br/>"github.com/login/oauth/authorize"
    Note left of Auth Server (GitHub): Sign in options<br> are supplied as<br/>query params<br/>(clientId, <br/>scope, etc...)
    Auth Server (GitHub)->>Browser: Shows sign in page<br/>in GitHub.com<br/>to the user
    Note left of Browser: User inserts their<br/>credentials in GitHub
    Browser->>Auth Server (GitHub): GitHub validates the inserted credentials
    Auth Server (GitHub)->>Auth Server (GitHub): Generates one time access code<br/>and calls callback<br>URL defined in<br/>App settings
    Auth Server (GitHub)->>App Server: GET<br/>"api/auth/github/callback?code=123"
    App Server->>App Server: Grabs code<br/>to exchange it for<br/>access token
    App Server->>Auth Server (GitHub): POST<br/>"github.com/login/oauth/access_token"<br/>{code: 123}
    Auth Server (GitHub)->>Auth Server (GitHub): Verifies code is<br/>valid and generates<br/>access token
    Auth Server (GitHub)->>App Server: { access_token: 16C7x... }
    App Server->>App Server: Generates session token<br/>and stores session
    App Server->>Browser: You're now logged in!

Development:

authjs.session-token: HttpOnly, SameSite=Lax, Path=/
authjs.csrf-token: SameSite=Lax, Path=/ (readable by JavaScript)

Production:

__Secure-authjs.session-token: HttpOnly, Secure, SameSite=Lax, Path=/
__Host-authjs.csrf-token: Secure, SameSite=Lax, Path=/ (readable by JavaScript)

Cookie Prefixes:

  • __Secure-: Requires Secure flag (HTTPS only)
  • __Host-: Requires Secure flag + Path=/ + no Domain attribute (prevents subdomain attacks)

CSRF Protection

Auth.js requires CSRF tokens for all state-changing operations:

  1. Frontend fetches CSRF token from /auth/csrf
  2. CSRF token stored in authjs.csrf-token cookie (readable by JavaScript)
  3. Form submission includes CSRF token as form field or header
  4. Backend validates token matches cookie value
  5. Prevents cross-site request forgery attacks

Login Flow:

1. User visits /login
2. Page fetches /auth/csrf, stores token in cookie
3. User clicks "Sign in with GitHub"
4. Form POSTs to /auth/signin/github with CSRF token
5. Backend validates CSRF, redirects to GitHub OAuth
6. After OAuth, user redirected to /app

Logout Flow:

1. User clicks logout
2. Frontend fetches fresh /auth/csrf token
3. Sends POST to /auth/signout with token
4. Backend validates CSRF, clears session cookie
5. Frontend clears local state and redirects to homepage

Released under the MIT License.