Implementing Credential Authentication with NextAuth v5, PostgreSQL, Prisma, and JWT

August 14, 2024

In this article, we will walk through the process of setting up credential-based authentication in a Next.js application using NextAuth v5, Prisma, and JSON Web Tokens (JWT). This setup will allow users to log in with PostgreSQL and manage authentication securely.

Prerequisites

  • NodeJS
  • NextJS (min: 14.0)
  • NextAuth v5.0 Beta
  • PostgreSQL
  • Prisma as an ORM (Optional, recommended.)
  • JWT for cookie strategy (Optional, recommmended.)

Project setup

  • Ensure you have Node.js installed on your machine. Download NodeJS

  • Create a NextJS app using the following command

npx create-next-app@latest my-nextjs-app

You will get series of questions about how to build your project in terms of structure of the project and script. You may choose the below options that I use.

Would you like to use TypeScript? » No / Yes

Would you like to use ESLint? » No / Yes

Would you like to use Tailwind CSS? » No / Yes

Would you like to use src/ directory? » No / Yes

Would you like to use App Router? (recommended) » No / Yes

Would you like to customize the default import alias (@/*)? » No / Yes

Your sample project is located at /my-nextjs-app, so access the file directoy by

cd my-nextjs-app

‎ In order to see everthing okey and run on your localhost server, just run the command below and then visit the homepage.

npm run dev

http://localhost:3000/

Database Setup

To set up PostgreSQL on your local machine, follow these steps:

  • Download PostgreSQL: Visit the official PostgreSQL website and download the installer for your operating system (Windows, macOS, Linux). Please follow the procedure of the installer and take not the database name and the password which you determine to access. Download PostgreSQL

  • In order to manage your PostgreSQL database easily and examine the relationship of object visually, I strongly recommend the install pgAdmin. Download pgAdmin

  • Run pgAdmin and connect you database. The default installation parameters deply PostgreSQL at 5432 port, so please do not adjust any parameters while connecting. Please log in by typing your username and password that you set during the installation phase in the 'Connection' section. In the 'General' section, set a name to better understand which server you will connect to.

Set up Prisma

Prisma is a synchronous ORM (Object–Relational Mapping) for PostgreSQL (Support: SQL or NonSQL databases) that simplifies database operations by providing a type-safe query builder. It allows developers to interact with their PostgreSQL databases using a unified API, ensuring type safety and ease of use.

  • In your root folder create a folder named as hello-prisma, enter inside the folder

mkdir hello-prisma
cd hello-prisma

  • Initialize a TypeScript project and add the Prisma CLI

npm init -y
npm install prisma typescript ts-node @types/node --save-dev
npx tsc --init

  • Invoke the Prisma CLI and create your initial schema file

npx prisma
npx prisma init

Connect The Database

In order to connect database and call the models from there, we have to specifiy connection info to .env file inside the hello-prisma folder.

DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"

  • johndoe: Change to your username

  • randompassword: Change to your password

  • mydb: Change to your database name

  • schema: Default parameter is schema.

function greet(name: string): string {
  return `Hello, ${name}!`
}

// This will throw an error at compile time, preventing potential runtime issues.
let message: string = greet(123)

Enhanced Readability and Maintainability

Static typing makes code more readable and maintainable. By explicitly declaring types, developers provide a clear contract of what the code does, making it easier for others (or themselves in the future) to understand and modify the codebase.

Facilitates Tooling and Refactoring

Modern IDEs leverage static typing to offer advanced features like code completion, refactoring, and static analysis. These tools can automatically detect issues, suggest fixes, and safely refactor code, enhancing developer productivity and reducing the likelihood of introducing bugs during refactoring.

// Refactoring example: Renaming a method in C#
public class Calculator {
    public int Add(int a, int b) {
        return a + b;
    }
}

// After refactoring `Add` to `Sum`, all references are automatically updated.
public class Calculator {
    public int Sum(int a, int b) {
        return a + b;
    }
}

Performance Optimizations

Static typing can lead to better performance. Since types are known at compile time, compilers can optimize the generated code more effectively. This can result in faster execution times and lower resource consumption.

Conclusion

Static typing offers numerous benefits that contribute to the development of robust, efficient, and maintainable software. By catching errors early, enhancing readability, facilitating tooling, and enabling optimizations, static typing is an invaluable asset for developers. As the software industry continues to mature, the importance of static typing in ensuring code quality and performance cannot be overstated. Whether you're working on a large-scale enterprise application or a small project, embracing static typing can lead to better software development outcomes.