Skip to contentSkip to navigation

Magic Links

Passwordless sign-in via email. The user enters their email, receives a link, clicks it, and they are in. No password to remember, no password to steal.

How it works

  1. The application calls requestMagicLink({ email }).
  2. Own Auth generates a random token and hashes it with the token pepper.
  3. The hash is stored in own_auth_tokens with its type, expiry, email, and user ID when one exists.
  4. The raw token is placed in the email link but is never stored.
  5. The user opens the link and the application sends the token to its backend.
  6. The backend calls verifyMagicLink({ token }).
  7. Own Auth hashes the incoming token and looks up the matching database record.
  8. If the token exists, has not expired, and has not been consumed, Own Auth consumes it and creates a session.

The raw token never exists in the database. Reading own_auth_tokens does not reveal a usable magic link.

Auto-creating users

Magic links create new users by default. The user is created when a valid link is verified, not when the email is sent.

To restrict magic-link sign-in to existing users:

ts
const auth = createOwnAuth({
  tokenPepper: process.env.OWN_AUTH_TOKEN_PEPPER,
  allowMagicLinkSignup: false,
});

Configuration

ts
const appUrl = "https://myapp.com";

const auth = createOwnAuth({
  tokenPepper: process.env.OWN_AUTH_TOKEN_PEPPER,
  baseUrl: appUrl,
  redirectAllowlist: [appUrl],
  tokenTtlMs: {
    magic_link: 15 * 60 * 1000, // 15 minutes
  },
});

Keep the lifetime short because a magic link grants access to the account. The default is 15 minutes.

Next step

Add phone-based login with Phone login, or learn about Email verification for confirming user emails after sign-up.

Magic Links | Own Auth Docs