Skip to main content
BunShip ships with Google and GitHub OAuth built in. This guide explains the auth system architecture and walks through adding a new OAuth provider from scratch.

Current Auth System

BunShip supports five authentication methods, all controlled by feature flags in packages/config/src/features.ts: The auth flow produces the same result regardless of method: a user record in the database and a JWT session (access token + refresh token).

How OAuth Works in BunShip

1

User clicks 'Sign in with Provider'

The frontend redirects to GET /api/v1/auth/{provider}.
2

API generates an authorization URL

BunShip creates a state parameter, stores it in a short-lived cookie, and redirects the user to the provider’s consent screen.
3

Provider redirects back

After the user approves, the provider redirects to GET /api/v1/auth/{provider}/callback with an authorization code.
4

API exchanges the code for tokens

BunShip calls the provider’s token endpoint, then fetches the user’s profile (email, name, avatar).
5

User is created or matched

If the email matches an existing user, the accounts are linked. Otherwise, a new user is created. A JWT session is issued either way.
6

Frontend receives tokens

The callback redirects to the frontend with tokens in the URL fragment or via a secure cookie handoff.

Adding a New OAuth Provider

This walkthrough adds Twitter (X) OAuth 2.0 as an example. The same pattern works for any OAuth 2.0 provider (Discord, Slack, LinkedIn, etc.).

Step 1: Install the OAuth Library

BunShip uses Arctic for OAuth. It provides type-safe, zero-dependency clients for 50+ providers.
Arctic already includes Twitter support. For providers not in Arctic, you can implement the OAuth flow manually or use a generic OAuth 2.0 client.

Step 2: Add Environment Variables

Add the provider’s credentials to .env:
To get these credentials:
  1. Go to the Twitter Developer Portal
  2. Create a new project and app
  3. Enable OAuth 2.0 under “User authentication settings”
  4. Set the callback URL to http://localhost:3000/api/v1/auth/twitter/callback
  5. Copy the Client ID and Client Secret

Step 3: Add the Feature Flag

Update packages/config/src/features.ts:

Step 4: Create the OAuth Routes

Create a new route file for the provider:

Step 5: Register the Routes

Add the new routes to the auth module in apps/api/src/routes/auth/index.ts:
Or register directly in the main app entry point if you prefer to keep auth providers separate.

Step 6: Update the Frontend

Add a “Sign in with Twitter” button that navigates to the OAuth endpoint:

Provider Configuration Pattern

To keep OAuth provider setup consistent, follow this pattern for each new provider:

Database Changes for OAuth

The default users table stores basic profile data (email, name, avatar) but does not track which OAuth provider a user signed up with. If you need to:
  • Track which providers a user has connected
  • Support linking multiple providers to one account
  • Store provider-specific tokens for API access
Add an oauth_accounts table:
Then update the callback handler to store the OAuth account:

Linking Accounts

To let users connect multiple providers to one account, add a “Link Account” flow:
Before unlinking, verify the user has at least one other login method (a password or another linked provider). Otherwise they could lock themselves out of their account.

Common Providers

Here are the Arctic constructor patterns for popular OAuth providers:

Next Steps

Configuration

Enable feature flags for your new providers

Database Schema

Add the oauth_accounts table to your database