website-logomedcode

Server-Side Authentication with Next Auth: use MongoDb

Discover how to implement server-side authentication in your Next.js application using NextAuth and MongoDB. This comprehensive guide walks you through the process of setting up secure user authentication,
alejandro coutinho| August 22, 2024
next.js
Server-Side Authentication with Next Auth: use MongoDb

#Next.js #Next-Auth #MongoDb #Srver-Side #Providers

Introduction

In today's digital landscape, securing user data is paramount. With cyber threats on the rise, it's crucial to implement robust authentication mechanisms in your web applications. One such mechanism is server-side authentication, which ensures that all authentication processes are handled securely on the server, reducing the risk of client-side attacks.

This article delves into server-side authentication using Next Auth, a popular authentication library for Next.js, and MongoDB, a leading NoSQL database. We'll explore how these tools work together to provide a secure and scalable authentication solution for modern web applications.

What is Server-Side Authentication?

Server-side authentication refers to the process of handling user authentication on the server rather than on the client. This approach offers several advantages, including enhanced security, as sensitive operations like password verification and token generation occur on a secure server.

Differences Between Client-Side and Server-Side Authentication

While client-side authentication involves handling credentials and tokens directly on the user's device, server-side authentication processes these elements on the server. This distinction is crucial because server-side authentication minimizes exposure to potential vulnerabilities such as cross-site scripting (XSS) and token theft.

Benefits of Server-Side Authentication
  • Increased Security: Sensitive data is processed on a secure server, reducing the risk of client-side attacks.
  • Centralized Control: The server can enforce strict authentication policies and monitor all authentication attempts.
  • Scalability: Server-side authentication can handle large volumes of requests, making it ideal for applications with a growing user base.

Understanding Next Auth

Next Auth is a flexible and easy-to-implement authentication solution designed specifically for Next.js applications. It provides a range of authentication methods, including email/password, OAuth, and social logins, making it a versatile choice for developers.

Key Features of Next Auth
  • Seamless Integration: Next Auth integrates smoothly with Next.js, leveraging its server-side capabilities.
  • Customizable Authentication: Developers can tailor authentication flows to meet specific needs.
  • Support for Multiple Providers: Next Auth supports various authentication providers, including Google, GitHub, and Twitter.
Why Choose Next Auth for Authentication?

Next Auth is a preferred choice for many developers due to its simplicity, flexibility, and strong community support. It allows for quick setup while offering extensive customization options for more complex authentication scenarios.

Why Use MongoDB for Authentication?

MongoDB is a powerful NoSQL database that stores data in a flexible, JSON-like format. Its scalability and performance make it an excellent choice for managing user data in authentication systems.

Advantages of MongoDB for Authentication
  • Scalability: MongoDB can handle large volumes of data, making it suitable for applications with a growing user base.
  • Flexibility: MongoDB's schema-less design allows for easy updates and changes to the database structure.
  • High Availability: MongoDB's replication and sharding features ensure that your authentication data is always available and secure.
MongoDB vs. Other Databases for Storing User Data

While relational databases like MySQL are traditionally used for storing user data, MongoDB offers greater flexibility and scalability, making it a better fit for modern, dynamic applications that require rapid development and scaling.

Setting Up Next Auth in a Next.js Project

Before diving into the integration of MongoDB, it's essential to set up Next Auth in your Next.js project. The following steps will guide you through the initial setup.

Prerequisites for Integrating Next Auth
  • A Next.js project up and running
  • Basic knowledge of Node.js and React
  • MongoDB instance or cluster ready to be connected
Step-by-Step Guide to Installing Next app
  1. Install Next.js app: Begin by installing Next.js via npx.
npx create-next-app@latest
  1. Install Next-auth v5
npm install next-auth@beta
  1. Install mongoDb and mongoose
    npm i mongodb // and mongoose//  npm i mongoose

Create a Next Auth : In your Next.js project, create a new API route for Next Auth under the app/utils/auth.js directory.

import NextAuth from "next-auth";
import GitHub from "next-auth/providers/github";
import GoogleProvider from "next-auth/providers/google";
import { connect } from "./ConnectMongo";
import User from "@/app/module/User";
import { authConfig } from "./auth.config";
export const {
  handlers: { POST, GET },
  auth,
  signIn,
  signOut,
} = NextAuth({
  ...authConfig,
  providers: [
    GitHub({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
  callbacks: {
    async signIn({ user, account, profile }) {
      if (account.provider === "github") {
        connect();
        try {
          const user = await User.findOne({ email: profile.email });
          if (!user) {
            const newUser = new User({
              name: profile.name,
              email: profile.email,
              imageUrl: profile.avatar_url,
            });
            await newUser.save();
            console.log("user is created");
            Response.redirect(new URL("/dashboard"));
          }
        } catch (err) {
          console.log("this is the error auth new user", err.message);
          return true;
        }
      } else if (account.provider === "google") {
        connect();
        try {
          const user = await User.findOne({ email: profile.email });
          if (!user) {
            const newUser = new User({
              name: profile.name,
              email: profile.email,
              imageUrl: profile.picture,
            });
            await newUser.save();
            console.log("user is created");
          }
        } catch (err) {
          console.log("error when created user", err.message);
        }
      }
      return true;
    },
    ...authConfig.callbacks,
  },
});

3.create User.js Model in this directory /app/models/User.js

import mongoose from "mongoose";

const { Schema } = mongoose;

const userSchema = new Schema(
  {
    name: {
      type: String,
      unique: true,
      required: true,
    },
    email: {
      type: String,
      unique: true,
      required: true,
    },
    imageUrl: {
      type: String,
    },
    isAdmin: {
      type: Boolean,
      default: false,
    },
  },
  { timestamps: true }
);

//If the User collection does not exist create a new one.
module.exports = mongoose.models?.users || mongoose.model("users", userSchema);

4.Create mongoDb connection function in this directory /app/utils/mongoDb.js

import mongoose from "mongoose";
const connect = async () => {
  try {
    await mongoose.connect(process.env.MONGO);
  } catch (err) {
    throw new Error("connection failed !");
  }
};
export default connect;

5.create auth.config file in this directory /app/utils/auth.config.js

  export const authConfig = {
  page: {
    signIn: "/login",
  },
  providers: [],
  callbacks: {
    async jwt({ token, user }) {
      if (user) {
        token.id = user.id;
        token.isAdmin = user.isAdmin;
        token.userSlug = user.userSlug;
      }
      return token;
    },
    async session({ session, token }) {
      if (token) {
        session.user.id = token.id;
        session.user.isAdmin = token.isAdmin;
        session.user.userSlug = token.userSlug;
      }
      return session;
    },
    authorized({ auth, request }) {
      const user = auth?.user;
      const isOneBlog = request?.nextUrl?.pathname?.startsWith("/dashboard");
      const adminUserPage = request?.nextUrl?.pathname === "/dashboard/users";
      const adminDraftBlog =request?.nextUrl?.pathname == "dashboard/pending";
      const isOnLoginPage = request?.nextUrl?.pathname.startsWith("/login");

      if (adminUserPage && user?.email !== EMAIL) {
        return Response.redirect(new URL("/dashboard", request.nextUrl));
      }
      if (adminDraftBlog && user?.name != "MOHAMMED DAKIR") {
        return Response.redirect(new URL("/dashboard", request.nextUrl));
      }
      if (isOneBlog && !user) {
        return Response.redirect(new URL("/login", request.nextUrl));
      }
      if (isOnLoginPage && user) {
        return Response.redirect(new URL("/dashboard", request.nextUrl));
      }
      return true;
    },
  },
};

6.How to call auth function to get session in server side components

import React from "react";
import HomePage from "./components/HomePage";
import {auth} from "./utils/auth.js"


export default async function Home() {
   //this is for call session to get user authentificationconst session =await auth()
  return (
    <>
      <HomePage />
    </>
  );
}

7.How to call auth function to get session in client side components

to do that you be must pass auth.js as a props from server side to client side this example HomePage.js is a client component:

 import React from "react";
import HomePage from "./components/HomePage";
import {auth} from "./utils/auth.js"


export default async function Home() {
   //this is for call session to get user authentificationconst session =await auth()
  return (
    <>
      <HomePage session={session} />
    </>
  );
}

In HomePage.js

"use client";
import React, { useState, useEffect } from "react";
import "../globals.css";

const HomePage = ({ session}) => {
  useEffect(() => {
   if(session){
    router.push("/dashboard")
     }else{
      router.push("/login")
    }
  });

  return (
    <div className="p-10 xl:p-6 sm:p-2 xs:p-2 dark:bg-dark">
     <h1>HomePage</h1>
    </div>
  );
};

export default HomePage;

Explore the latest insights, articles,free components, and expert advice on programming and software development

© Copyright 2024 MED DAKIR. All rights reserved./privacy policyTerms & Conditions