Home Arrow Icon Knowledge base Arrow Icon Global Arrow Icon How do I handle user authentication in a React SSR application


How do I handle user authentication in a React SSR application


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

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>;
   }
   

- Wrap the `provider` component in your `layout.js` file to make the session data accessible to all components.

javascript
   // layout.js
   import type, { Metadata } from "next";
   import { Inter } from "next/font/google";
   import "./globals.css";
   import Link from "next/link";
   import Providers from "./providers";

   const inter = Inter({ subsets: ["latin"] });

   export const metadata: Metadata = {
     title: "Create Next App",
     description: "Generated by create next app",
   };

   export default function RootLayout({ children }) {
     return (
       <html lang="en">
         <body className={inter.className}>
           <Providers>{children}</Providers>
         </body>
       </html>
     );
   }
   

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 };
   

- 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,
       },
     };
   }
   

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>;
     }
   }
   

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>
     );
   }
   

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].

Citations:
[1] https://blog.openreplay.com/authentication-and-authorization-with-ssr-in-nextjs/
[2] https://blog.logrocket.com/adding-login-authentication-secure-react-apps/
[3] https://www.turing.com/kb/master-react-user-authentication
[4] https://github.com/BigFatDog/auth-flow-ssr
[5] https://stackoverflow.com/questions/45679339/reactjs-handle-user-authentication-with-server-side-rendering