6. Authentication Setup
Alex needs to let law firm employees sign into LexVault securely.
The Auth settings page lets you configure how end-users authenticate in your application. Eurobase provides a built-in email/password auth system — no external providers required.
Auth methods
- Email + Password — traditional sign-up and sign-in with email and password
- Magic Links — passwordless sign-in via a one-time email link (no password needed)
- Phone (SMS OTP) — sign in with phone number via a 6-digit SMS code (EU-sovereign SMS via GatewayAPI). Paid plans only — every send has a per-message cost.
- Passkeys — coming soon (WebAuthn / FaceID / fingerprint)
- Social Login — Google, GitHub, LinkedIn, Apple (configure in Auth settings)
Configuration options
- Password rules — set minimum length (8–128 characters)
- Email confirmation — require users to verify their email before signing in
- Session duration — how long access tokens remain valid (1h to 30 days)
- Redirect URLs — whitelist URLs your app can redirect to after auth callbacks
- CORS origins — browser origins (scheme://host[:port]) allowed to call this project's API. Add your dev and production app origins. Eurobase platform origins (
*.eurobase.app) are always allowed. Loopback port wildcard supported: addhttp://localhost:*(or the127.0.0.1/[::1]spellings) to match any port — the standard carve-out for local dev tools that bind a fresh random port each run. Wildcards on non-loopback hosts are rejected at save time.
Email confirmation — end-to-end
When you enable Email confirmation, signups aren't complete until the user clicks a link in the verification email. Same shape for password reset and magic-link sign-in. All three flows follow the same three-step pattern:
- User signs up / requests a reset / requests a magic link via the SDK.
- Eurobase sends an email with a link to a page on your app (not Eurobase's console) with a
?token=...query parameter. - Your page reads the token from the query string and calls the corresponding SDK method to complete the flow.
Configure the URLs
In Auth → Settings → Email-flow redirect URLs, set the three URLs your app will host:
- Email verification URL — e.g.
https://yourapp.example/verify. Required when "Require email confirmation" is on. - Password reset URL — e.g.
https://yourapp.example/reset-password. - Magic link URL — e.g.
https://yourapp.example/magic-link.
Each URL must appear in the Allowed redirect URLs list above (same allowlist). The console blocks Save inline if a URL isn't allowed; the backend rejects the update for the same reason. This is the standard open-redirect defence — without it, an attacker could put your project's URL in a phishing email and land users on their own page. Add both your dev and prod URLs to the redirect list before configuring the three fields.
The verify-email page (copy-paste starter)
This is the minimum — a static HTML file works. Adapt to your framework (Next.js page, SvelteKit route, Vue component — same three lines of logic).
<!-- verify.html -->
<!DOCTYPE html>
<html lang="en">
<head><title>Verifying your email…</title></head>
<body>
<h1 id="status">Verifying…</h1>
<script type="module">
import { createClient } from 'https://cdn.jsdelivr.net/npm/@eurobase/sdk/+esm'
const eb = createClient({
url: 'https://your-project.eurobase.app',
apiKey: 'eb_pk_YOUR_PUBLIC_KEY',
})
const token = new URL(location.href).searchParams.get('token')
const status = document.getElementById('status')
if (!token) {
status.textContent = 'Missing verification token in the URL.'
} else {
const { error } = await eb.auth.verifyEmail(token)
status.textContent = error ? 'Verification failed: ' + error : 'Verified!'
}
</script>
</body>
</html>Password reset page
Same shape, but you collect a new password from the user first, then call eb.auth.resetPassword(token, newPassword). Trigger the email with eb.auth.forgotPassword(email).
Magic link page
Same shape. Trigger with eb.auth.requestMagicLink(email); complete with eb.auth.signInWithMagicLink(token). On success the user is signed in and you can redirect to your app's home page.
Per-request override (multi-tenant apps)
If you serve multiple environments or subdomains from one project, pass emailRedirectTo on the SDK call to override the default for that user:
await eb.auth.signUp({
email: 'user@example.com',
password: 'SecurePass123!',
emailRedirectTo: 'https://staging.yourapp.example/verify',
})The per-request URL must still be in your Allowed redirect URLs list, or the signup returns 400 (same open-redirect defence).
Migrating from the broken default
If your project had Require email confirmation enabled before July 2026, signups were silently broken — the email linked to a Eurobase-hosted URL that never existed. If any users were created with an unconfirmed email in that window, run this SQL from the SQL Runner to check who's affected:
SELECT id, email, created_at FROM users WHERE email_confirmed_at IS NULL ORDER BY created_at ASC;
After you configure the three redirect URLs, those users can request a fresh verification email with eb.auth.resendVerification(email) from a "verify your email" prompt in your app.
SDK auth flow
// Sign up a new user
const { user, error } = await eb.auth.signUp({
email: 'lawyer@acmelegal.eu',
password: 'SecurePass123!'
})
// Sign in
const { session, error: signInError } = await eb.auth.signIn({
email: 'lawyer@acmelegal.eu',
password: 'SecurePass123!'
})
// Listen for auth state changes
eb.auth.onAuthStateChange((event, session) => {\
console.log('Auth event:', event) // 'SIGNED_IN', 'SIGNED_OUT', 'TOKEN_REFRESHED'
console.log('Session:', session)
})
// Sign out
await eb.auth.signOut()Magic Links (passwordless)
Magic links let users sign in without a password. They enter their email, receive a link, and click it to sign in. The link expires after 15 minutes and can only be used once. Email is automatically verified on first magic link sign-in.
Enable magic links in Auth → Settings → Magic Links toggle. Both email/password and magic links can be active at the same time.
// 1. Send magic link to user's email
await eb.auth.requestMagicLink('user@example.com')
// 2. User clicks the link in their inbox
// Your app receives the token via URL: /auth/callback?token=abc123
const token = new URL(location.href).searchParams.get('token')
// 3. Exchange the token for a session
const { data, error } = await eb.auth.signInWithMagicLink(token)
// data.access_token, data.user.email — user is now signed inHow it works under the hood
requestMagicLinksends a POST to/v1/auth/request-magic-linkwith the email- The server generates a one-time token (32 random bytes), stores a SHA-256 hash in the database, and emails the raw token in a link
- The user clicks the link, your app extracts the
tokenquery parameter signInWithMagicLinksends the token to/v1/auth/signin-magic-link- The server verifies the token (not expired, not used), marks it as consumed, and returns a JWT + refresh token
Phone Auth (SMS OTP)
Phone auth lets users sign in with their phone number instead of an email. They receive a 6-digit verification code via SMS that expires after 10 minutes. Phone numbers must be in E.164 format (e.g., +33612345678).
Enable phone auth in Auth → Settings → Phone (SMS OTP) toggle. The gateway must have GATEWAYAPI_TOKEN configured. SMS is sent via GatewayAPI, an EU-based provider (Denmark) — no data leaves EU infrastructure.
Paid plan required. SMS auth is available on Pro and above because every OTP send has a per-message cost. Free projects see the toggle grayed out; a direct API call to /v1/auth/phone/send-otp from a Free project returns 402 paid_plan_required.
// 1. Send OTP to phone POST /v1/auth/phone/send-otp Body: {"phone": "+33612345678"} // 2. Verify code and get session POST /v1/auth/phone/verify Body: {"phone": "+33612345678", "code": "123456"} // Returns: access_token, refresh_token, user
How it works
- Your app sends the phone number to
/v1/auth/phone/send-otp - Eurobase creates a user (if new) and sends a 6-digit code via SMS
- The user enters the code in your app
- Your app sends the phone + code to
/v1/auth/phone/verify - Eurobase verifies the code, confirms the phone number, and returns JWT tokens
Phone-only users: Users who sign in with only a phone number are created without an email. They can later add an email via account linking. Phone auth can coexist with email/password and social login.
Social Login (OAuth)
Eurobase supports social login with Google, GitHub, LinkedIn, and Apple. Users authenticate with their existing account at the provider — Eurobase only receives their verified email, name, and profile picture. No application data is shared with the provider, and all user records remain in EU infrastructure.
Setting up a provider
- Go to Auth → Settings and toggle on the provider you want
- Create an OAuth app on the provider's developer console (links are shown in the setup instructions)
- Set the redirect/callback URL to your Eurobase API URL +
/v1/auth/oauth/{provider}/callback - Copy the Client ID and Client Secret into the Eurobase console
- Add your app's URL to the Allowed redirect URLs list in Session Settings
Provider-specific notes
Google & GitHub
Standard OAuth 2.0 setup. You need a Client ID and Client Secret from their developer consoles. GitHub fetches the primary verified email if the user's email is private.
Uses OpenID Connect. When creating your LinkedIn app, you must request the "Sign In with LinkedIn using OpenID Connect" product under the Products tab. Standard Client ID + Client Secret setup.
Apple
Requires additional configuration: a Service ID (used as Client ID), Team ID, Key ID, and a .p8 private key file from the Apple Developer Portal. Apple only sends the user's name on the first authorization — subsequent logins won't include it. Users may also receive a private relay email address if they choose to hide their real email.
SDK usage
// Redirect to provider's login page
eb.auth.signInWithOAuth('google', {
redirectTo: 'https://myapp.com/auth/callback'
})
// Supported providers: 'google', 'github', 'linkedin', 'apple', 'microsoft'
// On your callback page — extract tokens from URL fragment
const { data, error } = await eb.auth.handleOAuthCallback()
// data.access_token, data.user — user is now signed inREST API
How it works under the hood
- Your app redirects the user to
/v1/auth/oauth/{provider}with aredirect_url - Eurobase generates a CSRF state token, encodes the redirect URL in it, and redirects the browser to the provider's consent screen
- The user authenticates at the provider (Google, GitHub, LinkedIn, or Apple)
- The provider redirects back to Eurobase's callback endpoint with an authorization code
- Eurobase exchanges the code for user info (email, name, avatar), finds or creates the user, and links the OAuth identity
- The user is redirected to your app with JWT access and refresh tokens in the URL fragment
Account linking: If a user signs up with email/password and later signs in with an OAuth provider using the same email, the accounts are automatically linked — same user ID, no duplicates. OAuth sign-in also auto-verifies the user's email.
After sign-in, the SDK automatically includes the JWT with every database and storage request. Row-Level Security (RLS) policies on your tables use this token to enforce per-user access.