Current Auth System
BunShip supports five authentication methods, all controlled by feature flags inpackages/config/src/features.ts:
| Method | Config Flag | Status |
|---|---|---|
| Email + password | enableEmailPassword | Built-in |
| Magic link | enableMagicLink | Built-in |
| Google OAuth | enableGoogleOAuth | Built-in |
| GitHub OAuth | enableGithubOAuth | Built-in |
| TOTP two-factor | enableTwoFactor | Built-in |
user record in the database and a JWT session (access token + refresh token).
How OAuth Works in BunShip
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.
Provider redirects back
After the user approves, the provider redirects to
GET /api/v1/auth/{provider}/callback with
an authorization code.API exchanges the code for tokens
BunShip calls the provider’s token endpoint, then fetches the user’s profile (email, name,
avatar).
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.
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.Step 2: Add Environment Variables
Add the provider’s credentials to.env:
- Go to the Twitter Developer Portal
- Create a new project and app
- Enable OAuth 2.0 under “User authentication settings”
- Set the callback URL to
http://localhost:3000/api/v1/auth/twitter/callback - Copy the Client ID and Client Secret
Step 3: Add the Feature Flag
Updatepackages/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 inapps/api/src/routes/auth/index.ts:
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:| Step | File | What to add |
|---|---|---|
| 1 | .env | PROVIDER_CLIENT_ID and PROVIDER_CLIENT_SECRET |
| 2 | packages/config/src/features.ts | enableProviderOAuth: true flag |
| 3 | apps/api/src/routes/auth/{provider}.ts | OAuth redirect and callback routes |
| 4 | apps/api/src/routes/auth/index.ts | Import and .use() the new routes |
Database Changes for OAuth
The defaultusers 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
oauth_accounts table:
Linking Accounts
To let users connect multiple providers to one account, add a “Link Account” flow:Common Providers
Here are the Arctic constructor patterns for popular OAuth providers:Google
GitHub
GitHub
Discord
Discord
Slack
Slack

