---
title: Magic link
description: Magic link plugin
---

Magic link or email link is a way to authenticate users without a password. When a user enters their email, a link is sent to their email. When the user clicks on the link, they are authenticated.

## Installation

<Steps>
    <Step>
    ### Add the server Plugin

    Add the magic link plugin to your server:

    ```ts title="server.ts"
    import { betterAuth } from "better-auth";
    import { magicLink } from "better-auth/plugins";

    export const auth = betterAuth({
        plugins: [
            magicLink({
                sendMagicLink: async ({ email, token, url }, request) => {
                    // send email to user
                }
            })
        ]
    })
    ```
    </Step>

    <Step>
    ### Add the client Plugin

    Add the magic link plugin to your client:

    ```ts title="auth-client.ts"
    import { createAuthClient } from "better-auth/client";
    import { magicLinkClient } from "better-auth/client/plugins";
    export const authClient = createAuthClient({
        plugins: [
            magicLinkClient()
        ]
    });
    ```
    </Step>

</Steps>

## Usage

### Sign In with Magic Link

To sign in with a magic link, you need to call `signIn.magicLink` with the user's email address. The `sendMagicLink` function is called to send the magic link to the user's email.


<APIMethod
  path="/sign-in/magic-link"
  method="POST"
  requireSession
>
  
```ts
type signInMagicLink = {
    /**
     * Email address to send the magic link. 
     */
    email: string = "user@email.com"
    /**
     * User display name. Only used if the user is registering for the first time. 
     */
    name?: string = "my-name"
    /**
     * URL to redirect after magic link verification. 
     */
    callbackURL?: string = "/dashboard"
    /**
     * URL to redirect after new user signup
     */
    newUserCallbackURL?: string = "/welcome"
    /**
     * URL to redirect if an error happen on verification
     * If only callbackURL is provided but without an `errorCallbackURL` then they will be 
     * redirected to the callbackURL with an `error` query parameter.
     */
    errorCallbackURL?: string = "/error"
}
```
</APIMethod>

<Callout>
If the user has not signed up, unless `disableSignUp` is set to `true`, the user will be signed up automatically.
</Callout>

### Verify Magic Link

When you send the URL generated by the `sendMagicLink` function to a user, clicking the link will authenticate them and redirect them to the `callbackURL` specified in the `signIn.magicLink` function. If an error occurs, the user will be redirected to the `callbackURL` with an error query parameter.

<Callout type="warn">
  If no `callbackURL` is provided, the user will be redirected to the root URL.
</Callout>

If you want to handle the verification manually, (e.g, if you send the user a different URL), you can use the `verify` function.


<APIMethod
  path="/magic-link/verify"
  method="GET"
  requireSession
>
```ts
type magicLinkVerify = {
    /**
     * Verification token. 
     */
    token: string = "123456"
    /**
     * URL to redirect after magic link verification, if not provided will return the session. 
     */
    callbackURL?: string = "/dashboard"
}
```
</APIMethod>

## Configuration Options

**sendMagicLink**: The `sendMagicLink` function is called when a user requests a magic link. It takes an object with the following properties:

- `email`: The email address of the user.
- `url`: The URL to be sent to the user. This URL contains the token.
- `token`: The token if you want to send the token with custom URL.

and a `request` object as the second parameter.

**expiresIn**: specifies the time in seconds after which the magic link will expire. The default value is `300` seconds (5 minutes).

**disableSignUp**: If set to `true`, the user will not be able to sign up using the magic link. The default value is `false`.

**generateToken**: The `generateToken` function is called to generate a token which is used to uniquely identify the user. The default value is a random string. There is one parameter:

- `email`: The email address of the user.

<Callout type="warn">
  When using `generateToken`, ensure that the returned string is hard to guess
  because it is used to verify who someone actually is in a confidential way. By
  default, we return a long and cryptographically secure string.
</Callout>

**storeToken**: The `storeToken` function is called to store the magic link token in the database. The default value is `"plain"`.

The `storeToken` function can be one of the following:

- `"plain"`: The token is stored in plain text.
- `"hashed"`: The token is hashed using the default hasher.
- `{ type: "custom-hasher", hash: (token: string) => Promise<string> }`: The token is hashed using a custom hasher.
