Authentication with middlewares in NextJS
source link: https://dev.to/brainiacneit/authentication-with-middlewares-in-nextjs-279p
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Overview
Hey there! Today, we're going to talk about authentication in Next.js using middlewares. If you're not familiar, Next.js is a really cool framework for building server-rendered React applications.
So, what's authentication all about? Well, it's a way to make sure that only the right people can access certain parts of your web app. And that's where middlewares come in handy! They're like helpers that can do certain things before requests reach the actual route handlers.
This article will discuss the fundamentals of middlewares and demonstrate how they can be utilized in a Next.js application to establish a secure authentication system. Upon reading this article, you'll acquire a comprehensive understanding of how to utilize middlewares for authentication in Next.js and have the ability to enhance the security of your web apps. Let's begin and explore the world of authentication with Next.js.
Set up
Packages
First, we have to have a NextJS project, then install Axios for better HTTP Handling
yarn add axios
Services
Next we have to define a service, in this case AuthService
to handle authentication:
import axios, { AxiosInstance } from "axios";
export class AuthService {
protected readonly instance: AxiosInstance;
public constructor(url: string) {
this.instance = axios.create({
baseURL: url,
timeout: 30000,
timeoutErrorMessage: "Time out!",
});
}
login = (username: string, password: string) => {
return this.instance
.post("/login", {
username,
password,
})
.then((res) => {
return {
username: res.data.username,
avatar: res.data.avatar,
id: res.data.userId,
accessToken: res.data.access_token,
expiredAt: res.data.expiredAt,
};
});
};
}
This code defines a class named AuthService
that exports it as a module. The AuthService
class has a constructor that takes a URL as a parameter to create an Axios instance based on that URL. Axios is a popular JavaScript library used to make HTTP requests from a web browser or Node.js.
The login
method is defined within the AuthService
class, which takes two parameters, username
and password
. This method sends a POST request to the /login
endpoint of the API service using the Axios instance created in the constructor. The username
and password
are passed as an object in the POST request body.
If the POST request is successful, the method returns an object that contains the username
, avatar
, id
, accessToken
, and expiredAt
properties. These properties are extracted from the response data, which is received from the API service.
Overall, this code defines a reusable AuthService
class that encapsulates the logic for making an HTTP request to an API service to log in a user and retrieves the user's information.
Routes
export const protectedRoutes = ["/profile"];
export const authRoutes = ["/login"];
export const publicRoutes = ["/about", "/"];
We need 3 types of routes:
- Protected routes: only logged-in users can access these routes
- Auth routes: routes that serve authentication, authenticated users can't access these routes
- Public routes: routes that can be accessed by anyone
Login hook
We need a hook to handle login function:
import { authService } from "../../services";
import Cookies from "js-cookie";
import { User } from "../../types/user";
export const useLogin = () => {
const login = async (username: string, password: string) => {
const user = await authService.login(username, password);
if (user) {
Cookies.set("currentUser", JSON.stringify(user));
}
return user as User;
};
return { login };
};
This code exports a function named useLogin
that returns an object with the login
function. The login
function takes two parameters: username
and password
.
Within the login
function, an asynchronous call is made to authService.login(username, password)
, which is a method defined in another module, authService
. This method returns a promise that resolves to a User
object.
If the User
object is truthy, meaning it exists, the Cookies.set
method is called to set a cookie named "currentUser" with the stringified User
object as its value.
Finally, the login
function returns the User
object as a type assertion to inform TypeScript that the returned value is indeed a User
.
Middleware
This is the most important part of the article, using built-in middleware.ts
of NextJS:
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { authRoutes, protectedRoutes } from "./src/router/routes";
export function middleware(request: NextRequest) {
const currentUser = request.cookies.get("currentUser")?.value;
if (
protectedRoutes.includes(request.nextUrl.pathname) &&
(!currentUser || Date.now() > JSON.parse(currentUser).expiredAt)
) {
request.cookies.delete("currentUser");
const response = NextResponse.redirect(new URL("/login", request.url));
response.cookies.delete("currentUser");
return response;
}
if (authRoutes.includes(request.nextUrl.pathname) && currentUser) {
return NextResponse.redirect(new URL("/profile", request.url));
}
}
This code defines a middleware function that is used in a Next.js application. Middlewares are functions that can modify incoming requests and outgoing responses in a web application.
The middleware function takes a NextRequest
object as its parameter, which is provided by the Next.js server. The NextRequest
object represents an incoming request and contains information about the URL, headers, cookies, and other request-specific data.
The middleware function first retrieves the currentUser
cookie from the request using request.cookies.get("currentUser")?.value
.
If the requested URL is a protected route (defined in protectedRoutes
), and the currentUser
cookie is not present or has expired, the middleware will delete the currentUser
cookie and redirect the user to the login page using NextResponse.redirect(new URL("/login", request.url))
. The response.cookies.delete("currentUser")
statement removes the currentUser
cookie from the response object.
If the requested URL is an authentication route (defined in authRoutes
) and the currentUser
cookie is present, the middleware will redirect the user to the profile page using NextResponse.redirect(new URL("/profile", request.url))
.
Conclusion
In conclusion, this article has covered the fundamentals of authentication using middlewares in Next.js. We've discussed how middlewares can be used to manage authentication in web applications by intercepting incoming requests and performing necessary actions before they reach the actual route handlers. We've also explored how to implement a secure authentication system using middlewares in a Next.js application.
If you find this article is too confusing, you can check out the source code: https://github.com/superdev163/nextjs-auth
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK