Skip to main content

Authentication

Learn how SvelteBolt's authentication system works and how to add new OAuth providers for seamless user login.

Overview

SvelteBolt uses Supabase Auth for authentication, providing multiple sign-in methods:

  • Magic Link - Passwordless login via email
  • Password Authentication - Traditional email/password login
  • OAuth Providers - Social login with Google, GitHub, Twitter, and more

How Authentication Works

Current Implementation

The authentication system is built around these key components:

  1. Login/Signup Forms - Located in src/lib/components/
  2. Auth Actions - Server-side handlers in src/routes/auth/+page.server.ts
  3. Database Adapter - Abstraction layer in src/lib/server/database/
  4. Auth Callbacks - Handle OAuth redirects in src/routes/api/auth/

Adding New OAuth Providers

Step 1: Configure in Supabase

  1. Go to your Supabase Dashboard

    • Navigate to AuthenticationProviders
  2. Enable your desired provider (e.g., Discord, LinkedIn, etc.)

    • Click on the provider you want to add
    • Toggle Enable to true
  3. Add provider credentials

    • Client ID: From your OAuth app
    • Client Secret: From your OAuth app
    • Redirect URL: Copy the provided URL for your provider setup
  4. Configure redirect URL in your OAuth app

    • Use the format: https://your-project-id.supabase.co/auth/v1/callback

Step 2: Add Provider to Your Forms

Add the new provider button to both login and signup forms:

Login Form (src/lib/components/login-form.svelte)

<!-- Add this after the existing OAuth providers -->
<form action="/auth?/oauth" method="POST">
<input type="hidden" name="provider" value="discord" />
<button type="submit" variant="outline" class="w-full">
<Icon icon="logos:discord-icon" />
Login with Discord
</button>
</form>

Signup Form (src/lib/components/signup-form.svelte)

<!-- Add this after the existing OAuth providers -->
<form action="/auth?/oauth" method="POST">
<input type="hidden" name="provider" value="discord" />
<button type="submit" variant="outline" class="w-full">
<Icon icon="logos:discord-icon" />
Sign up with Discord
</button>
</form>

Step 3: Verify Server Implementation

The OAuth action in src/routes/auth/+page.server.ts already handles any provider:

oauth: async ({ request, url, locals }) => {
const db = createDatabaseAdapter(locals);
const formData = await request.formData();
const provider = (formData.get("provider") as Provider) ?? "";

const { data, error } = await db.auth.signInWithOAuth(provider, {
redirectTo: `${url.origin}/api/auth/callback`,
});

if (error) {
console.error(error);
redirect(303, "/auth/login");
}

redirect(303, data.url);
};

This automatically works with any Supabase-supported provider!

Supported OAuth Providers

Supabase supports these OAuth providers out of the box:

  • Social: Google, GitHub, Twitter, Facebook, Discord
  • Professional: LinkedIn, Microsoft, Slack, Notion
  • Developer: GitLab, Bitbucket, WorkOS
  • Other: Apple, Spotify, Twitch, Zoom, Keycloak

Common OAuth Provider Setups

Discord

  1. Create Discord Application

  2. Configure OAuth2

    • Add redirect URI: https://your-project-id.supabase.co/auth/v1/callback
    • Copy Client ID and Client Secret
  3. Add to Supabase

    • Enable Discord provider
    • Paste credentials

LinkedIn

  1. Create LinkedIn App

  2. Configure OAuth

    • Add redirect URL in app settings
    • Copy Client ID and Client Secret
  3. Add to Supabase

    • Enable LinkedIn OIDC provider
    • Paste credentials

Microsoft/Azure

  1. Create Azure App Registration

    • Go to Azure Portal
    • Register new application
    • Configure authentication
  2. Set Redirect URI

    • Add the Supabase callback URL
    • Copy Application (client) ID and secret
  3. Add to Supabase

    • Enable Azure provider
    • Paste credentials

Code Locations for Customization

Form Components

src/lib/components/
├── login-form.svelte # Login page OAuth buttons
└── signup-form.svelte # Signup page OAuth buttons

Server Actions

src/routes/auth/
├── +page.server.ts # OAuth action handler
└── schema.ts # Form validation schema

Auth Callbacks

src/routes/api/auth/
├── callback/+server.ts # OAuth callback handler
├── confirm/+server.ts # Email confirmation handler
└── logout/+server.ts # Logout handler

Database Adapter

src/lib/server/database/
├── index.ts # Database adapter factory
├── supabase.ts # Supabase implementation
└── types.ts # Interface definitions

Adding Custom Icons

SvelteBolt uses @iconify/svelte for icons. Find provider icons at Iconify:

<!-- Examples -->
<Icon icon="logos:discord-icon" />
<Icon icon="logos:linkedin-icon" />
<Icon icon="logos:microsoft-icon" />
<Icon icon="simple-icons:slack" />

Customization Tips

Styling OAuth Buttons

All OAuth buttons use the same base styling. Customize them in your form components:

<button type="submit" variant="outline" class="w-full custom-oauth-button">
<Icon icon="your-icon" />
Sign in with Provider
</button>

Error Handling

OAuth errors are automatically handled by the server action. Custom error messages can be added:

if (error) {
console.error(`OAuth error for ${provider}:`, error);
// Add custom error handling here
redirect(303, "/auth/login?error=oauth_failed");
}

Provider-Specific Scopes

Some providers need specific scopes. Configure them in Supabase:

// This is handled in Supabase dashboard, not in code
// But you can pass additional options:
const { data, error } = await db.auth.signInWithOAuth(provider, {
redirectTo: `${url.origin}/api/auth/callback`,
options: {
scopes: "email profile", // Provider-specific scopes
},
});

Troubleshooting

Common Issues

"Invalid redirect URI"

  • Ensure redirect URI matches exactly in provider settings
  • Check for trailing slashes or protocol mismatches

"Provider not enabled"

  • Verify provider is enabled in Supabase dashboard
  • Check credentials are correctly entered

"CORS errors"

  • Ensure site URL is configured in Supabase
  • Check redirect URLs are whitelisted

Next Steps