Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions content/docs/auth/guides/manage-auth-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ The Neon API also provides endpoints for managing auth configuration at the bran
| `/email_and_password` | GET, PATCH | Configure email/password authentication |
| `/users` | POST, DELETE, PUT | Create, delete, and manage user roles |
| `/plugins` | GET, PATCH | View and configure [auth plugins](/docs/auth/guides/plugins) |
| `/plugins/magic-link` | PATCH | Configure the [Magic Link plugin](/docs/auth/guides/plugins/magic-link) |
| `/webhooks` | GET, PUT | Configure webhook notifications |
| `/allow_localhost` | GET, PATCH | Toggle localhost access for development |
| `/send_test_email` | POST | Send a test email to verify email configuration |
Expand Down
3 changes: 2 additions & 1 deletion content/docs/auth/guides/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ The following Better Auth plugins are currently supported in Neon Auth:
| [Admin](/docs/auth/guides/plugins/admin) | ✅ Supported |
| [Email OTP](/docs/auth/guides/plugins/email-otp) | ✅ Supported |
| [JWT](/docs/auth/guides/plugins/jwt) | ✅ Supported |
| [Magic Link](/docs/auth/guides/plugins/magic-link) | ✅ Supported |
| [Organization](/docs/auth/guides/plugins/organization) | ⚠️ Partial (JWT token claims under development) |
| [Open API](/docs/auth/guides/plugins/openapi) | ✅ Supported |

For more runnable Neon Auth samples, see [Example applications](/docs/auth/overview#example-applications). The **Organization** plugin demo is **[neon-auth-orgs-example](https://github.com/neondatabase/neon-js/tree/main/examples/neon-auth-orgs-example)**; see the [Organization plugin](/docs/auth/guides/plugins/organization) page for context.
For more runnable Neon Auth samples, see [Example applications](/docs/auth/overview#example-applications). The **Organization** plugin demo is **[neon-auth-orgs-example](https://github.com/neondatabase/neon-js/tree/main/examples/neon-auth-orgs-example)** and the **Magic Link** demo is **[neon-auth-magic-link-example](https://github.com/neondatabase/neon-js/tree/main/examples/neon-auth-magic-link-example)**.

For the latest status (including what’s coming next), see the [Neon Auth roadmap](/docs/auth/roadmap).

Expand Down
130 changes: 130 additions & 0 deletions content/docs/auth/guides/plugins/magic-link.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
---
title: Magic Link
subtitle: Passwordless sign-in via email magic links
summary: >-
Covers the setup of Magic Link functionality in Neon Auth, enabling users to
sign in by clicking a link sent to their email, with no password required.
enableTableOfContents: true
updatedOn: '2026-04-14T00:00:00.000Z'
---

<FeatureBetaProps feature_name="Neon Auth with Better Auth" />

Neon Auth is built on [Better Auth](https://www.better-auth.com/) and supports the [Magic Link](https://www.better-auth.com/docs/plugins/magic-link) plugin through the Neon SDK. You don't need to install or configure the Better Auth Magic Link plugin directly.

Magic Link lets users sign in by clicking a link sent to their email. No password is required. The flow works like this:

1. The user enters their email address.
2. Neon Auth sends an email containing a unique, time-limited link.
3. The user clicks the link, which verifies the token, creates a session, and redirects them to your app.

## Prerequisites

- A Neon project with **Auth enabled**
- The **Magic Link plugin enabled** (see [Enable Magic Link](#enable-magic-link) below)

## Enable Magic Link

<Tabs labels={["Console", "API"]}>

<TabItem>

1. Open the [Neon Console](https://console.neon.tech).
2. Select your project and go to **Auth** > **Plugins**.
3. Toggle **Magic Link** on.
4. Configure the options:
- **Link Expiration** (5-1440 minutes, default: 5) controls how long a magic link stays valid.
- **Allow New User Registration**, when disabled, restricts magic links to existing users only (sign-in only, no sign-up).

![Neon Console Auth Plugins tab with Magic Link settings](/docs/auth/neon_auth_plugins_magic_link.png)

</TabItem>

<TabItem>

Send a `PATCH` request to configure the Magic Link plugin. All request body fields are optional; send only the fields you want to change.

```bash shouldWrap
curl -X PATCH \
"https://console.neon.tech/api/v2/projects/{project_id}/branches/{branch_id}/auth/plugins/magic-link" \
-H "Authorization: Bearer $NEON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"enabled": true,
"expires_in": 5,
"disable_sign_up": false
}'
```

| Field | Type | Default | Description |
| ----------------- | ------- | ------- | ------------------------------------------------------- |
| `enabled` | boolean | `false` | Whether the Magic Link plugin is active |
| `expires_in` | integer | `5` | Minutes before the magic link expires (5-1440) |
| `disable_sign_up` | boolean | `false` | When `true`, magic links only work for existing users |

</TabItem>

</Tabs>

## Use Magic Link with SDK methods

Build a custom magic link flow using the [Neon SDK](/docs/reference/javascript-sdk). Call `signIn.magicLink()` with the user's email and a callback URL. Neon Auth sends the email and redirects the user to `callbackURL` after they click the link.

```ts shouldWrap filename="src/send-magic-link.ts"
import { authClient } from '@/lib/auth/client';

export async function sendMagicLink(email: string) {
const { error } = await authClient.signIn.magicLink({
email,
callbackURL: '/dashboard',
});

if (error) throw error;
}
```

After calling `signIn.magicLink()`, show the user a "check your email" message. For a complete working example with error handling, resend, and state management, see the [magic link example app](https://github.com/neondatabase/neon-js/tree/main/examples/neon-auth-magic-link-example) in the neon-js repository.

## Use Magic Link with UI components

If you're already using Neon Auth UI components, you can enable Magic Link with a single prop instead of building a custom form. Pass the `magicLink` prop to `NeonAuthUIProvider`:

```tsx shouldWrap filename="app/layout.tsx"
'use client';

import { authClient } from '@/lib/auth/client';
import { NeonAuthUIProvider } from '@neondatabase/neon-js/auth/react/ui';
import '@neondatabase/neon-js/ui/css';
import './globals.css';

export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
return (
<html lang="en" suppressHydrationWarning>
<body className={'antialiased'}>
<NeonAuthUIProvider
authClient={authClient}
magicLink // [!code ++]
>
{children}
</NeonAuthUIProvider>
</body>
</html>
);
}
```

Users can now sign in with a magic link by selecting the option on the sign-in screen and entering their email.

> If you haven't set up Neon Auth UI components yet, see the [UI components reference](/docs/auth/reference/ui-components) for setup, or the [Next.js](/docs/auth/quick-start/nextjs-api-only) or [React](/docs/auth/quick-start/react) quick start for building custom forms instead.

## Webhooks

When a magic link needs to be delivered, Neon Auth fires the `send.magic_link` webhook event with `link_type: "sign-in"`. If you subscribe to this event, Neon Auth skips its built-in email and your webhook handler is responsible for delivering the link (for example, via a custom email template or SMS).

See the [Webhooks guide](/docs/auth/guides/webhooks) for configuration details and payload format.

## Email provider configuration

For production environments, we strongly recommend using a dedicated email provider. The default shared SMTP should be used only during development. See the [Email provider configuration guide](/docs/auth/production-checklist#email-provider) for setup instructions.

<NeedHelp/>
4 changes: 2 additions & 2 deletions content/docs/auth/guides/webhooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,14 @@ The `user` object fields are all optional and vary by event. Available fields: `

| Field | Type | Description |
| ------------ | ------------ | --------------------------------------------- |
| `link_type` | string | `"email-verification"` or `"forget-password"` |
| `link_type` | string | `"sign-in"`, `"email-verification"`, or `"forget-password"` |
| `link_url` | string | Full verification URL with embedded token |
| `token` | string | Raw token for building custom redirect URLs |
| `expires_at` | ISO datetime | Expiry time |
| `ip_address` | string | Requester's IP address |
| `user_agent` | string | Requester's user agent |

Magic links do not include a `delivery_preference` field. Your webhook handler determines the delivery channel.
The `"sign-in"` link type is sent when a user signs in via the [Magic Link plugin](/docs/auth/guides/plugins/magic-link). Magic links do not include a `delivery_preference` field. Your webhook handler determines the delivery channel.

### `user.before_create` and `user.created` event data

Expand Down
2 changes: 1 addition & 1 deletion content/docs/auth/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ See [Branching authentication](/docs/auth/branching-authentication) for details

## Example applications

Beyond the quick starts on this site, the [neondatabase/neon-js](https://github.com/neondatabase/neon-js) monorepo ships **more runnable Neon Auth and `neon-js` samples** under [`examples/`](https://github.com/neondatabase/neon-js/tree/main/examples)Next.js and React apps, cross-subdomain setups, the Organization plugin, alternative UI stacks, and Data API patterns. Each folder includes its own README (many workflows use **bun** from the repository root). Browse there when you want a full project to clone next to the guides here.
Beyond the quick starts on this site, the [neondatabase/neon-js](https://github.com/neondatabase/neon-js) monorepo ships **more runnable Neon Auth and `neon-js` samples** under [`examples/`](https://github.com/neondatabase/neon-js/tree/main/examples), including the [Organization plugin](https://github.com/neondatabase/neon-js/tree/main/examples/neon-auth-orgs-example) and [Magic Link](https://github.com/neondatabase/neon-js/tree/main/examples/neon-auth-magic-link-example) demos, Next.js and React apps, cross-subdomain setups, alternative UI stacks, and Data API patterns. Each folder includes its own README (many workflows use **bun** from the repository root). Browse there when you want a full project to clone next to the guides here.

## Availability

Expand Down
30 changes: 30 additions & 0 deletions content/docs/auth/reference/ui-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function App() {
| `avatar` | `AvatarOptions` | Avatar upload and display configuration | `avatar={{ size: 256, extension: 'webp' }}` |
| `additionalFields` | `AdditionalFields` | Custom fields for sign-up and account settings | See example below |
| `credentials.forgotPassword` | `boolean` | Enable forgot password flow | `credentials={{ forgotPassword: true }}` |
| `magicLink` | `boolean` | Enable passwordless magic link sign-in option | `magicLink` |

### Enable OAuth Providers

Expand Down Expand Up @@ -206,6 +207,35 @@ function App() {
}
```

### Next.js App Router

Create a route file at `app/auth/[path]/page.tsx` to render `AuthView` for sign-in, sign-up, and other auth views:

```tsx
import { AuthView } from '@neondatabase/neon-js/auth/react/ui';
import { authViewPaths } from '@neondatabase/neon-js/auth/react/ui/server';

export const dynamicParams = false;

export function generateStaticParams() {
return Object.values(authViewPaths).map((path) => ({ path }));
}

export default async function AuthPage({
params,
}: {
params: Promise<{ path: string }>;
}) {
const { path } = await params;

return (
<main className="flex min-h-screen items-center justify-center p-4">
<AuthView path={path} />
</main>
);
}
```

### User Menu

```tsx
Expand Down
2 changes: 1 addition & 1 deletion content/docs/auth/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Neon Auth is built on [Better Auth](https://www.better-auth.com/). Not all Bette
| [Admin](/docs/auth/guides/plugins/admin) | ✅ Supported |
| [Organization](/docs/auth/guides/plugins/organization) | ⚠️ Partial (JWT token claims under development) |
| [JWT](/docs/auth/guides/plugins/jwt) | ✅ Supported |
| [Magic Link](/docs/auth/guides/plugins/magic-link) | ✅ Supported |
| [Open API](/docs/auth/guides/plugins/openapi) | ✅ Supported |

See [Set up OAuth](/docs/auth/guides/setup-oauth) for Neon-specific OAuth configuration (including Vercel). Email flows such as verification and password reset are covered in [Email verification](/docs/auth/guides/email-verification), [Password reset](/docs/auth/guides/password-reset), and [User management](/docs/auth/guides/user-management).
Expand All @@ -75,7 +76,6 @@ Branch-aware auth (separate auth state per Neon branch) is supported; see [Branc

| Plugin | Status |
| ----------------------------------------------------------------- | --------------- |
| [Magic link](https://www.better-auth.com/docs/plugins/magic-link) | 🔜 Coming soon |
| Phone number (bring your own SMS provider) | 🔜 Coming soon |
| MFA support | 🔜 Coming soon |
| [Admin](/docs/auth/guides/plugins/admin) plugin customization | 🔜 Coming soon |
Expand Down
2 changes: 2 additions & 0 deletions content/docs/navigation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,8 @@
slug: auth/guides/plugins/email-otp
- title: JWT
slug: auth/guides/plugins/jwt
- title: Magic Link
slug: auth/guides/plugins/magic-link
- title: OpenAPI
slug: auth/guides/plugins/openapi
- title: Organization
Expand Down
Binary file added public/docs/auth/neon_auth_plugins_magic_link.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.