Skip to main content

Magic links

Passwordless login via emailed single-use tokens. Enable it by passing a magicLink config to useAuth.

import { InMemoryVerificationTokenStore } from "covara";

useAuth({
adapter,
magicLink: {
store: new InMemoryVerificationTokenStore(),
sendLink: async ({ identifier, token }) =>
sendEmail(identifier, `https://app.com/magic?token=${token}`),
findUserByEmail: async (email) => db.query.users.findFirst({ where: eq(users.email, email) }),
ttlMs: 15 * 60 * 1000, // default 15m
hashTokens: true, // store SHA-256 instead of the raw token
},
});

Routes

RouteMethodDescription
/magic-link/requestPOST{ email } — issues a single-use token and calls sendLink only if the user exists, but always returns { success: true } (no email enumeration).
/magic-link/verifyPOST{ email, token } — consumes the token and creates the session, returning { user, sessionId }; invalid/expired returns 401.

Low-level helpers

import { issueMagicLinkToken, consumeMagicLinkToken } from "covara";

Use these for custom flows (e.g. issuing a link from a different channel).

Token store

magicLink.store implements the VerificationTokenStore interface (create/consume/deleteByIdentifier), shared with email verification and password reset. InMemoryVerificationTokenStore ships for development; back it with your own table for production.