Logo
guidesMarch 15, 2026·5 min read

Next.js Supabase Auth Tutorial: Secure Your Web App Easily

Learn how to implement authentication in your Next.js app with our Next.js Supabase Auth tutorial. Build secure applications effortlessly.

Introduction

Next.js is a powerful React framework that enables developers to build scalable web applications with ease, while Supabase provides a robust backend-as-a-service solution that simplifies database and authentication management. In this Next.js Supabase Auth Tutorial, we will explore how to set up authentication in a Next.js application using Supabase. Authentication is a crucial component of modern web applications, and mastering it will empower you to build secure applications quickly.

This tutorial will guide you through the entire process, from setting up your Next.js project to implementing user authentication, managing sessions, and handling user profiles. By the end of this guide, you will have a functional authentication system integrated with Supabase.

Setting Up Your Next.js Project

Creating a New Next.js App

To get started, you'll need to create a new Next.js application. You can do this easily using the Create Next App command.

npx create-next-app@latest my-supabase-app
cd my-supabase-app

This command creates a new directory called my-supabase-app and sets up a Next.js project with the default directory structure.

Installing Supabase Client

Next, you'll need to add the Supabase client to your project. Run the following command to install the Supabase library:

npm install @supabase/supabase-js

Once installed, you need to configure the Supabase client. Create a new file named supabaseClient.ts in the root of your project and add the following code:

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

const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL as string;
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY as string;

export const supabase = createClient(supabaseUrl, supabaseAnonKey);

Make sure to set your Supabase URL and anon key in a .env.local file:

NEXT_PUBLIC_SUPABASE_URL=https://your-supabase-url.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

Configuring Supabase

Creating a Supabase Project

  1. Go to the Supabase website and sign up for an account.
  2. After logging in, click on "New Project."
  3. Fill in the project details like the name and database password, then click "Create new project."

Setting Up Authentication

Once your project is created, navigate to the "Authentication" section in the Supabase dashboard:

  1. Click on the "Settings" tab.
  2. Enable the authentication providers you want to use (e.g., email/password).
  3. Under "Email Auth," make sure to enable "Enable Email Auth."

Implementing Authentication in Next.js

Creating Auth Context

To manage authentication state throughout your application, you can create a React context. Create a new folder named context and add a file called AuthContext.tsx:

import React, { createContext, useReducer, useContext } from 'react';
import { supabase } from '../supabaseClient';

interface AuthState {
  user: any | null;
  loading: boolean;
}

const initialState: AuthState = {
  user: null,
  loading: true,
};

const AuthContext = createContext<{
  state: AuthState;
  dispatch: React.Dispatch<any>;
}>({ state: initialState, dispatch: () => null });

const authReducer = (state: AuthState, action: any) => {
  switch (action.type) {
    case 'SET_USER':
      return { ...state, user: action.payload, loading: false };
    case 'LOGOUT':
      return { ...state, user: null, loading: false };
    default:
      return state;
  }
};

export const AuthProvider: React.FC = ({ children }) => {
  const [state, dispatch] = useReducer(authReducer, initialState);

  return (
    <AuthContext.Provider value={{ state, dispatch }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => useContext(AuthContext);

Building Login and Signup Pages

Now, let's create the login and signup pages. In the pages directory, create two new files: login.tsx and signup.tsx.

Login Page (login.tsx):

import React, { useState } from 'react';
import { supabase } from '../supabaseClient';
import { useAuth } from '../context/AuthContext';
import { useRouter } from 'next/router';

const Login = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const { dispatch } = useAuth();
  const router = useRouter();

  const handleLogin = async (e: React.FormEvent) => {
    e.preventDefault();
    const { user, error } = await supabase.auth.signIn({ email, password });
    if (error) {
      console.error(error);
    } else {
      dispatch({ type: 'SET_USER', payload: user });
      router.push('/profile');
    }
  };

  return (
    <form onSubmit={handleLogin}>
      <input
        type="email"
        placeholder="Email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        required
      />
      <input
        type="password"
        placeholder="Password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        required
      />
      <button type="submit">Login</button>
    </form>
  );
};

export default Login;

Signup Page (signup.tsx):

import React, { useState } from 'react';
import { supabase } from '../supabaseClient';
import { useAuth } from '../context/AuthContext';
import { useRouter } from 'next/router';

const Signup = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const { dispatch } = useAuth();
  const router = useRouter();

  const handleSignup = async (e: React.FormEvent) => {
    e.preventDefault();
    const { user, error } = await supabase.auth.signUp({ email, password });
    if (error) {
      console.error(error);
    } else {
      dispatch({ type: 'SET_USER', payload: user });
      router.push('/profile');
    }
  };

  return (
    <form onSubmit={handleSignup}>
      <input
        type="email"
        placeholder="Email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        required
      />
      <input
        type="password"
        placeholder="Password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        required
      />
      <button type="submit">Sign Up</button>
    </form>
  );
};

export default Signup;

Managing User Sessions

Using Supabase Session Management

Supabase provides session management out of the box. You can retrieve the user session as follows:

import { supabase } from '../supabaseClient';

const session = supabase.auth.session();

To handle session expiration, you can set up a listener:

supabase.auth.onAuthStateChange((event, session) => {
  console.log(event, session);
});

Protecting Routes

To protect certain routes, you can create a higher-order component (HOC) called withAuth. Create a new file in the utils folder named withAuth.tsx:

import { useAuth } from '../context/AuthContext';
import { useRouter } from 'next/router';
import React, { useEffect } from 'react';

const withAuth = (WrappedComponent: React.FC) => {
  const AuthenticatedComponent = (props: any) => {
    const { state } = useAuth();
    const router = useRouter();

    useEffect(() => {
      if (!state.user) {
        router.push('/login');
      }
    }, [state.user]);

    return state.user ? <WrappedComponent {...props} /> : null;
  };

  return AuthenticatedComponent;
};

export default withAuth;

You can then wrap your protected pages with this HOC:

import withAuth from '../utils/withAuth';

const Profile = () => {
  // Profile component code
};

export default withAuth(Profile);

Adding User Profile Management

Creating User Profile Page

Create a new file named profile.tsx in the pages directory. This page will display the user’s profile information.

import React from 'react';
import { supabase } from '../supabaseClient';
import { useAuth } from '../context/AuthContext';

const Profile = () => {
  const { state } = useAuth();

  return (
    <div>
      <h1>User Profile</h1>
      {state.user && (
        <div>
          <p>Email: {state.user.email}</p>
          {/* Add more user details if necessary */}
        </div>
      )}
    </div>
  );
};

export default Profile;

Updating User Information

To allow users to update their profile details, you can create a form in the Profile component.

const updateProfile = async (e: React.FormEvent) => {
  e.preventDefault();
  const { error } = await supabase.auth.update({
    data: { /* user data */ },
  });
  if (error) {
    console.error(error);
  }
};

// In the JSX
<form onSubmit={updateProfile}>
  {/* Input fields for updating user info */}
  <button type="submit">Update Profile</button>
</form>

Testing and Debugging

Common Issues and Solutions

  1. Authentication Errors: Ensure your Supabase URL and anon key are set correctly in the .env.local file.
  2. Session Issues: Use Supabase's built-in session management to handle session expiration and state changes.

Best Practices for Secure Authentication

  1. Use environment variables for sensitive information.
  2. Secure your API routes by validating user sessions before processing requests.

Conclusion

In this Next.js Supabase Auth Tutorial, we've covered the essential steps to implement authentication in your Next.js application using Supabase. From setting up your project and configuring Supabase to managing user sessions and profiles, you now have the foundation to build a secure SaaS product.

Feel free to explore more features of Supabase and Next.js. Check out our guides for in-depth tutorials and features to see what more you can achieve with BuilderHack.

FAQ

What is Supabase?

Supabase is an open-source backend-as-a-service platform that provides a database, authentication, and storage solutions, allowing developers to build applications quickly.

How does Supabase authentication work?

Supabase authentication allows you to manage user sign-up, sign-in, and session management using various providers, including email/password, OAuth, and more.

Can I use other authentication providers with Supabase?

Yes, Supabase supports multiple authentication providers, including third-party services like Google, GitHub, and Facebook.

Is it secure to use Supabase for authentication?

Yes, Supabase follows security best practices, providing secure authentication methods and managing sensitive user data.

Where can I find more resources on Next.js and Supabase?

You can find additional resources in our guides section, and explore our comparisons to see how Supabase stacks up against other services.

Explore More

Related Articles