Supabase Magic Link Simplified for NextJS

published on 06 December 2023

Most site owners would agree: implementing authentication can be a major pain point when building a NextJS app.

But what if you could add passwordless login to your NextJS site in just a few lines of code? With Supabase's Magic Link feature, you can simplify auth and start converting visitors into users in minutes.

In this post, we'll walk through exactly how Supabase's Magic Link works under the hood. You'll see step-by-step code snippets for setting up Magic Link login in a NextJS project, handling auth state, customizing the experience, and best practices for user session management.

Supabase Magic Link is a passwordless authentication service provided by Supabase that makes it easy to add login functionality to Next.js applications. With Magic Link, users can sign in with just an email address, no password required.

Here are some of the key benefits of using Supabase Magic Link in Next.js projects:

  • Passwordless login - Users don't need to remember passwords. Instead, Magic Link emails them a login link. This enhances security and convenience.

  • Quick setup - It only takes a few lines of code to get Magic Link working in a Next.js app. Supabase handles the authentication logic behind the scenes.

  • User management - Magic Link integrates with Supabase's user management features like user profiles, access control, and more.

  • Customizable - Developers can customize the login page, email templates, and more to match their app's branding.

  • Scalable - Magic Link leverages Supabase's backend infrastructure, making it easy to scale auth across projects.

Overall, Supabase Magic Link is a great way to quickly implement secure and passwordless login flows in Next.js apps. The convenience of email-based authentication paired with Supabase's user management tools make it a compelling authentication option for many projects.

Magic links are a seamless way to enable passwordless authentication in your NextJS application. With Supabase, integrating magic links takes just a few lines of code.

Here's how it works:

  1. The user enters their email address on your site
  2. Your backend code requests a magic link from Supabase to be sent to that address
  3. Supabase emails the user a unique, encrypted login link
  4. When the user clicks the link, they are instantly logged into your app!

Magic links provide a frictionless login experience as users don't need to remember passwords or go through cumbersome signup flows.

Some key benefits:

  • Enhanced user experience - no more forgotten passwords!
  • Quick integration with Supabase's authentication APIs
  • Security - magic links are temporary, one-time use, and encrypted

Let's look at a code example for adding magic link logins in NextJS with Supabase:

// Import Supabase client
import { createClient } from '@supabase/supabase-js'

// Initialize client
const supabase = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.NEXT_PUBLIC_SUPABASE_KEY)

// Function to request magic link 
async function loginWithMagicLink() {

  const { error } = await supabase.auth.signInWithOtp({
    email: enteredEmail,
  })

  if (error) console.log('Error sending magic link:', error)  
}

We simply call supabase.auth.signInWithOtp() to instantly send a login link to the user's email.

Once they click the link, we can listen for login state changes using onAuthStateChange() and retrieve the logged in user with getUser():

// Listen for auth changes
supabase.auth.onAuthStateChange((event, session) => {

  // Get current user
  const user = supabase.auth.getUser()  

})

That's all there is to it! Magic links abstract away the complexity of building custom auth systems, so you can focus on creating amazing user experiences.

By leveraging Supabase's simple APIs and realtime auth features, you can start shipping passwordless logins in your Next app today. Give it a try!

Magic links provide a convenient way to log in without passwords, but have tradeoffs in terms of security.

On the plus side, magic links avoid vulnerabilities like weak or reused passwords. Users don't need to remember login credentials at all. This improves the login experience while eliminating common attack vectors.

However, magic links have their own risks. Most importantly, they only authenticate the user once at the time the link is clicked. There is no continuous authentication after that. This means that if the user leaves their device unattended after clicking the link, an attacker could gain access.

Here are some best practices to secure magic link logins:

  • Use limited validity periods - links should expire after a single use or short duration. Supabase links expire after 180 seconds.

  • Implement second factors where applicable, like 2FA or device verification. Supabase supports integrating TouchID.

  • Log users out after periods of inactivity with onAuthStateChanged.

  • Use checks like getUser() to re-verify the user's session.

Overall, magic links trade some security for convenience. They are reasonably safe for low-risk applications, but additional controls should be layered on for sensitive data.

Following authentication best practices is still important with magic link logins. You have to design with defense in depth, not just rely on the magic link alone.

A magic link is a convenient way to log users into an application without needing a password. Here's how it works in Supabase:

When a user wants to log in, instead of entering credentials on your site, they enter their email address. Supabase then sends them a login link via email.

When the user clicks the login link, it logs them into your application automatically, without needing to enter a password. Some key benefits of magic links:

  • Increased convenience - no need to remember passwords
  • Enhanced security - no passwords that could be leaked or cracked
  • Frictionless onboarding - users can easily get started with just their email

To implement magic links with Supabase and NextJS, there are a few simple steps:

First, set up user authentication in Supabase. Make sure email/password authentication is enabled.

Then in your NextJS app, import the useUser hook from @supabase/auth-helpers-nextjs to track login state.

When the user enters their email to log in, call supabase.auth.signInWithOtp() to kick off the magic link flow.

Supabase sends the login link email behind the scenes. Use onAuthStateChange to update state when the user logs in via link.

Finally, use the session object from useUser to check if the user is logged in, and show protected content.

That's the gist of it! Magic links remove friction during onboarding by eliminating passwords. Combined with Supabase's email templates andNextJS auth helpers, you can build passwordless flows easily.

sbb-itb-5683811

What is slack magic link?

Supabase Magic Link allows users to sign in to an application without needing a password. Instead, users enter their email address and a login link is sent to their inbox. Clicking this link signs them into the app securely.

Here is a quick overview of how Supabase Magic Link works:

  • User visits login page and enters their email address
  • supabase.auth.signInWithOtp() is called to request a magic link
  • An email is sent to the user's inbox with a unique login link
  • User clicks the login link in their email
  • They are automatically signed into the app without needing to enter a password

This creates a smooth passwordless login experience. Users don't need to remember credentials or go through a cumbersome sign-up flow.

Implementation Example

Integrating Supabase Magic Link into a NextJS app is straightforward. Here is an example using React hooks:

import { useState } from 'react'
import { supabase } from '../utils/supabaseClient'

export default function Auth() {

  const [email, setEmail] = useState('')

  const handleLogin = async (email) => {
    try {
      const { error } = await supabase.auth.signInWithOtp({ email })
      if (error) throw error
      alert('Check your email for the login link!')
    } catch (error) {
      alert(error.error_description || error.message)
    }
  }

  return (
    <div>
      <input 
        type="email"
        placeholder="Your email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />
      <button onClick={() => handleLogin(email)}>Send magic link</button>
    </div>
  )
}

This allows the user to enter their email and request a login link. Supabase handles sending the email and managing the magic link URL.

When the user clicks the link, they will be automatically signed in using supabase.auth.onAuthStateChanged() to update authentication state.

Best Practices

Here are some tips for optimizing a Supabase Magic Link flow:

  • Use supabase.auth.getSession() to check if a user is already logged in before showing the Magic Link form. This avoids an extra step for returning users.

  • Consider adding SMS magic link support with supabase.auth.signInWithOtp({ email, phoneNumber }) to provide both email and text message login options.

  • Customize the magic link email template in Supabase Dashboard > Authentication > Templates.

  • Show a progress indicator after requesting a login link while the email is in transit.

By following these best practices, you can create a smooth, passwordless authentication flow using Supabase Magic Links in your NextJS application.

Supabase's Magic Link authentication provides a smooth login experience for users by sending them a login link instead of passwords. It's easy to enable in new or existing Supabase projects.

Creating a New Supabase Project

When first creating your Supabase project, you'll have the option to enable Magic Link authentication on the "Authentication" page during project setup.

  1. Check the box for "Email Magic Link" on the Authentication page
  2. Customize the magic link options like link lifespan, redirect URLs, etc.
  3. Click "Save" to enable Magic Link and finish project creation

And that's it! Your new Supabase project will now have Magic Link enabled by default for a simplified auth flow.

If you already have a Supabase project, head to the "Authentication" tab in your Supabase Dashboard.

  1. Scroll down and check the box to "Enable email magic links"
  2. Customize the link options like lifespan, redirect URL, etc.
  3. Click "Save" to update the authentication settings

Once saved, your project will now support Magic Link! You can start sending login links from the Supabase client library.

With just a few clicks, Magic Link provides a passwordless login experience that delights users. Whether starting a new project or adding it later, enabling Magic Link is a breeze with Supabase.

Supabase Magic Link provides a seamless passwordless login experience for NextJS applications. By integrating just a few Supabase client methods, you can enable one-click email logins for your users.

Setting Up the Supabase Client

To get started, you need to initialize the Supabase client by passing your project's URL and anon public API key. These credentials can be stored as environment variables on the server to keep them secure.

import { createClient } from '@supabase/supabase-js'

const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL, 
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
)

Now the Supabase client is ready for use in our app!

When a user clicks your app's login button, you can trigger the Magic Link flow by calling supabase.auth.signInWithOtp().

This will send an email to the user with a login link. When clicked, it will redirect back to your app and automatically log them in.

async function login() {
  const { error } = await supabase.auth.signInWithOtp({
    email: enteredEmail,
  })
}

To handle the redirect callback, use NextJS getInitialProps in your pages. Check if a session exists to show the correct UI.

MyPage.getInitialProps = async ({ req }) => {

  const {
    data: { session }
  } = await supabase.auth.getSession()

  return {
    props: {
      userLoggedIn: !!session
    }
  }
}

Validating User Session with Supabase getUser

After the login redirect, double check the user is logged in with supabase.auth.getUser().

If a user exists, you can display profile information or route to your app's protected areas.

useEffect(() => {
  checkUser()  
}, [])

async function checkUser() {
  const user = await supabase.auth.getUser()
  
  if (user) {
    // logged in
  } else {  
    // not logged in
  }
} 

By chaining these Supabase methods, you can add Magic Link authentication to a NextJS app with just a few lines of code!

Advanced Usage Tips and Best Practices

Additional recommendations for improving the Magic Link flow in your app, like managing user sessions.

Handling Authentication State with Supabase onAuthStateChanged

Listening for auth changes using Supabase's onAuthStateChanged event for a more dynamic user experience.

Supabase provides an onAuthStateChange listener that fires whenever a user logs in or out. This is useful for updating your UI based on the authentication state.

For example, you can conditionally show profile or login buttons:

import { createClient } from '@supabase/supabase-js'

const supabase = createClient()

function AuthButtons() {
  const [session, setSession] = useState(null)

  useEffect(() => {
    setSession(supabase.auth.session())

    supabase.auth.onAuthStateChange((_event, session) => {
      setSession(session)
    })
  }, [])

  return (
    <div>
      {session ? (
        <Button onClick={() => supabase.auth.signOut()}>
          Sign out
        </Button>
      ) : (
        <Button onClick={() => supabase.auth.signInWithOAuth()}>
          Sign in
        </Button>
      )}
    </div>
  )
}

This listens for changes and updates the session state accordingly.

Some key advantages:

  • No need to manually check session, it updates automatically
  • Can persist user data on sign in
  • Clear logged out state on sign out

Overall, onAuthStateChange helps create a more seamless auth flow.

Options for customizing the Magic Link login prompt, email templates, etc.

Supabase's Magic Link emails use default templates that work well out of the box. But you can override this to match your app's branding.

In Supabase Dashboard > Authentication > Settings, you can set a custom email sender address, subject line, and HTML template.

For the template, you get access to handlebars helpers like:

  • {{app_name}} - Your site name
  • {{url}} - The Magic Link
  • {{expiry}} - Link expiry deadline

Example custom email template:

<h1>Log in to {{app_name}}</h1>

<p>Tap the link below to sign in instantly:</p>

<a href="{{url}}">{{url}}</a>

<p>Expires in {{expiry}} minutes!</p>

You can also customize the Magic Link prompt programmatically:

const { data, error } = await supabase.auth.signInWithOtp({
  email: userEmail,
  options: {
    magicLink: {
      // Customize prompt displayed to user    
      customPrompt: 'Check your email to sign in!' 
    }
  }  
})

This gives you flexibility to match the email and prompts to your branding.

User Session Management

Setting session expiry and refresh token usage for persisting logins.

By default, Supabase sessions expire after 30 days of inactivity. To change this, update the auth.cookie.refresh_expiry setting.

For example, to set sessions to expire after 7 days of inactivity:

// Set session expiration to 7 days
supabase.auth.setAuthCookieConfiguration({
  refreshExpiry: 60 * 60 * 24 * 7 
})

You can also enable refresh tokens to allow users to stay logged in even after a session expires:

supabase.auth.setAuthCookieConfiguration({
  refreshTokenEnabled: true
})  

Now Supabase will use the refresh token to get a new access token if the session expires, keeping the user logged in.

Some best practices:

  • Lower expiry the more sensitive the data
  • Increase expiry for user convenience
  • Enable refresh tokens for most apps
  • Call setAuthCookieConfiguration on initClient

Fine tuning these levers helps ensure your auth flow remains secure while keeping users logged in.

Supabase Magic Link provides a simple way to add passwordless authentication to Next.js applications. With just a few lines of code, developers can enable email-based login for their sites.

Here is a brief example to demonstrate how easy it is:

import { createClient } from '@supabase/auth-helpers-nextjs'

const supabase = createClient({
  supabaseKey: 'supabase-key',
  supabaseUrl: 'supabase-url',
  options: {
    magicLink: true 
  }
})

async function signInWithMagicLink() {
  const { error } = await supabase.auth.signInWithOtp({
    email: 'name@example.com',
  })
}

By setting magicLink: true in the client options, Supabase will automatically email users a login link instead of a one-time password.

Some key advantages of using Magic Link include:

  • No passwords to manage or forget
  • Frictionless login experience
  • Users access your site in one click from their email

Supabase also supports many other login options like OAuth via GitHub, Google, Facebook and more. But Magic Link stands out for its simplicity compared to traditional authentication flows.

So if you're looking for an easy way to add authentication without passwords in your Next.js project, enabling Supabase's Magic Link is a great place to start.

Related posts

Read more

Make your website with
Unicorn Platform Badge icon