Email Authentication

AuthGate supports email + password authentication alongside OAuth providers. End users can sign up with an email and password, verify their email address, and reset their password. AuthGate also supports Magic Link authentication as a separate, independently toggleable provider.


Overview

Email authentication is a separate auth method from OAuth — it doesn't redirect users to a provider. Instead, your application calls AuthGate's email endpoints directly and receives JWT tokens in the response body.

Key differences from OAuth:

  • No redirects — signup/signin return JSON with a JWT token directly
  • Email verification — users receive a verification email after signup
  • Password reset — users can request a password reset link via email
  • JWT includes provider: "email" and email_verified: boolean

Enable email auth

Email authentication is enabled by default for new projects. You can toggle it in the dashboard under your project's Providers settings.

To enable it via the API, toggle the email provider for your project the same way you'd toggle any OAuth provider.


Signup flow

To register a new user, send a POST request to the signup endpoint:

curl -X POST https://auth.example.com/api/proxy/email/signup \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "securePassword1",
    "name": "Jane Doe",
    "callback_url": "https://myapp.com/auth/callback"
  }'

The response includes a JWT token and user info:

{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "user": {
    "id": "user_abc123",
    "email": "user@example.com",
    "name": "Jane Doe",
    "email_verified": false
  }
}

A verification email is sent automatically after signup.

Password requirements

  • Minimum 8 characters
  • Maximum 128 characters
  • At least 1 letter
  • At least 1 number

Signin flow

To authenticate an existing user:

curl -X POST https://auth.example.com/api/proxy/email/signin \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "securePassword1",
    "callback_url": "https://myapp.com/auth/callback"
  }'

Returns the same format as signup, with email_verified reflecting the current verification status.


Email verification

After signup, users receive an email with a 6-digit verification code. They enter this code in your app to verify their email address.

curl -X POST https://auth.example.com/api/proxy/email/verify \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "code": "123456"
  }'

You can also resend the verification email:

curl -X POST https://auth.example.com/api/proxy/email/verify/resend \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "callback_url": "https://myapp.com/auth/callback"
  }'

Verification codes expire after 5 minutes and are invalidated after 3 failed attempts.


Password reset

To request a password reset:

curl -X POST https://auth.example.com/api/proxy/email/reset-password \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "callback_url": "https://myapp.com/auth/callback"
  }'

This always returns 200 regardless of whether the email exists (to prevent enumeration).

To confirm the reset with a new password:

curl -X POST https://auth.example.com/api/proxy/email/reset-password/confirm \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "token": "reset-token-from-email",
    "password": "newSecurePassword1"
  }'

Reset tokens expire after 1 hour.


Magic link authentication is a separate provider from email + password. It allows users to sign in by clicking a link sent to their email — no password required. If the email doesn't match an existing account, AuthGate automatically creates a new end user, so magic links work for both sign-in and sign-up.

The Magic Link provider is toggled independently in the dashboard. Disabling "Email" does not affect magic link, and vice versa.

Send magic link

curl -X POST https://auth.example.com/api/proxy/email/magic-link/send \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "callback_url": "https://myapp.com/auth/callback"
  }'

This sends an email with a magic link. When the user clicks it, they are redirected to your callback_url with a token query parameter (a JWT signed with your project's signing secret).

Verify magic link

The verification happens automatically when the user clicks the link. The JWT includes provider: "magic-link" and email_verified: true.

Magic link tokens expire after 15 minutes.

See the Email Auth Endpoints for the full API reference.


Locale / i18n

All email authentication endpoints accept an optional locale parameter to set the user's preferred language. This locale is stored on the user record and will be used for localized email templates.

Detection priority

AuthGate resolves the user's locale using this priority chain:

  1. Explicit locale param in the request body (e.g. "locale": "it")
  2. Stored user preference from a previous request
  3. Accept-Language header from the HTTP request
  4. Project default locale (configurable in Dashboard > Emails > Email Branding)
  5. Fallback: "en"

Passing locale via SDK

All SDK email methods accept an optional locale parameter:

// Next.js / React SDK — the locale is forwarded automatically
// when your frontend sends it in the request body
await fetch('/api/auth/email/signup', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    email: 'user@example.com',
    password: 'securePassword1',
    locale: 'it', // Optional
  }),
});

Or when calling the core SDK directly:

await authgate.emailSignup({
  email: 'user@example.com',
  password: 'securePassword1',
  callbackUrl: 'https://myapp.com/auth/callback',
  locale: 'it',
});

Passing locale via API

Add locale to the JSON body of any email endpoint:

curl -X POST https://auth.example.com/api/proxy/email/signup \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "securePassword1",
    "callback_url": "https://myapp.com/auth/callback",
    "locale": "it"
  }'

OAuth flows

For OAuth authentication (Google, GitHub, etc.), locale is detected automatically from the Accept-Language header during the OAuth initiation request. You can also pass an explicit locale parameter:

// Core SDK
await authgate.getOAuthUrl('google', callbackUrl, { locale: 'it' });
# API — POST handler
curl -X POST https://auth.example.com/api/proxy/google \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "callback_url": "https://myapp.com/auth/callback",
    "locale": "it"
  }'

# API — GET handler
curl "https://auth.example.com/api/proxy/google?callback_url=https://myapp.com/auth/callback&locale=it"

Supported locales

en, it, es, fr, de, pt, ja, ko, zh, nl, pl, ru, sv, da, nb, fi, ar, he, th, vi

Setting the project default

In the dashboard, go to your project's Emails page. Under Email Branding, select a Default Locale from the dropdown. This is used as the fallback when no user-specific locale is available.

Was this page helpful?