Home Arrow Icon Knowledge base Arrow Icon Global Arrow Icon Can I use Next.js for authentication in a non-React SSR project


Can I use Next.js for authentication in a non-React SSR project


Handling user authentication in a React Server-Side Rendering (SSR) application involves several steps:

Step 1: Configure State Management

Create a `provider.js` file to manage state across the application. This file should wrap the `SessionProvider` from `next-auth/react` to make session data available to all components.

javascript
// provider.js
import { SessionProvider } from "next-auth/react";

export default function Providers({ children }) {
  return <SessionProvider>{children}</SessionProvider>;
}

Step 2: Implement Authentication Logic

Create a login function in your `apiServices` that handles authentication and returns user information if successful.

javascript
// apiServices.js
import axios from "axios";

const login = async (username, password) => {
  const response = await axios.post("/api/auth/login", { username, password });
  if (response.data) {
    return response.data;
  } else {
    return null;
  }
};

export { login };

Step 3: Access Session Data in Components

Use the `useSession` hook from `next-auth/react` to access the session data within components.

javascript
// components/Login.js
import { useSession } from "next-auth/react";

export default function Login() {
  const { data: session, status } = useSession();

  if (status === "authenticated") {
    return <h1>Welcome {session.user.name}!</h1>;
  } else {
    return <p>You are not logged in.</p>;
  }
}

Step 4: Handle Authentication on the Client Side

Use the `auth` function from your `apiServices` to handle authentication on the client side.

javascript
// components/Login.js
import { useState } from "react";
import { auth } from "@/services/apiServices";

export default function Login() {
  const [input, setInput] = useState({ username: "", password: "" });

  const handleSubmit = (e) => {
    e.preventDefault();
    if (input.username !== "" && input.password !== "") {
      auth.loginAuth(input);
      return;
    }
    alert("Please provide a valid input");
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>Username: </label>
      <br />
      <input type="text" onChange={(e) => setInput({ ...input, username: e.target.value })} />
      <br />
      <label>Password: </label>
      <br />
      <input type="password" onChange={(e) => setInput({ ...input, password: e.target.value })} />
      <br />
      <button type="submit">Login</button>
    </form>
  );
}

Step 5: Access Session Data in Server-Side Components

Use the `getServerSession` function from `next-auth/next` to fetch the user session on the server side.

javascript
// pages/api/public/page.js
import { getServerSession } from "next-auth/next";
import { GetServerSidePropsContext } from "next";
import { login } from "@/services/apiServices";

export default function Protected({ user }) {
  return (
    <div>
      <div>
        {user ? (
          <h1>Hi {user.name}!</h1>
        ) : (
          <a href="/api/auth/signin">Sign in</a>
        )}
      </div>
    </div>
  );
}

export async function getServerSideProps(context) {
  const session = await getServerSession(context);
  const user = session ? session.user : null;

  return {
    props: {
      user,
    },
  };
}

Step 6: Configure API Routes

Protect API routes using `getServerSession` to ensure that only authenticated users can access them.

javascript
// pages/api/secure-api.js
import { authOptions } from './auth/[...nextauth]';
import { getServerSession } from "next-auth/next";

export default async (req, res) => {
  const session = await getServerSession(req, res, authOptions);

  if (session) {
    res.status(200).json({
      name: "John Doe",
      message: "Welcome authenticated user",
    });
  } else {
    res.status(403).json({
      error: "You must sign-in to view the content on this page.",
    });
  };
};

Step 7: Integrate NextAuth

Integrate NextAuth into your application by creating an `auth` directory and adding the necessary files.

javascript
// auth/[...nextauth].js
import NextAuth from "next-auth";
import Google from "next-auth/providers/google";

export default NextAuth({
  // Configure one or more authentication providers
  providers: [
    Google({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
});

Step 8: Set Up API Routes

Set up API routes to handle authentication and authorization.

javascript
// pages/api/auth/[...nextauth].js
import NextAuth from "next-auth";
import Google from "next-auth/providers/google";

export default NextAuth({
  // Configure one or more authentication providers
  providers: [
    Google({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
});

Step 9: Use NextAuth in Components

Use the `useSession` hook to access the session data within components.

javascript
// components/Login.js
import { useSession } from "next-auth/react";

export default function Login() {
  const { data: session, status } = useSession();

  if (status === "authenticated") {
    return <h1>Welcome {session.user.name}!</h1>;
  } else {
    return <p>You are not logged in.</p>;
  }
}

Step 10: Handle Authentication on the Server Side

Handle authentication on the server side by using `getServerSession` to fetch the user session.

javascript
// pages/api/public/page.js
import { getServerSession } from "next-auth/next";
import { GetServerSidePropsContext } from "next";
import { login } from "@/services/apiServices";

export default function Protected({ user }) {
  return (
    <div>
      <div>
        {user ? (
          <h1>Hi {user.name}!</h1>
        ) : (
          <a href="/api/auth/signin">Sign in</a>
        )}
      </div>
    </div>
  );
}

export async function getServerSideProps(context) {
  const session = await getServerSession(context);
  const user = session ? session.user : null;

  return {
    props: {
      user,
    },
  };
}

By following these steps, you can effectively handle user authentication in a React SSR application using Next.js and `next-auth`. This setup ensures that authentication is handled both on the server and client sides, providing robust security and user management for your application[1][2][3][5].

Citations:
[1] https://stackoverflow.com/questions/60799741/next-js-authentication-strategies
[2] https://blog.openreplay.com/authentication-and-authorization-with-ssr-in-nextjs/
[3] https://buttercms.com/blog/nextjs-authentication-tutorial/
[4] https://www.reddit.com/r/nextjs/comments/v01uy1/why_should_i_use_next_other_than_ssr/
[5] https://github.com/nextauthjs/next-auth/discussions/3394