Miliki kontrol lebih besar atas logika autentikasi aplikasi Next.js Anda melalui implementasi autentikasi berbasis JWT khusus.

Otentikasi token adalah strategi populer yang digunakan untuk melindungi aplikasi web dan seluler dari akses tidak sah. Di Next.js, Anda dapat memanfaatkan fitur otentikasi yang disediakan oleh Next-auth.

Alternatifnya, Anda dapat memilih untuk mengembangkan sistem autentikasi berbasis token khusus menggunakan JSON Web Tokens (JWTs). Dengan melakukan hal ini, Anda memastikan bahwa Anda memiliki kontrol lebih besar atas logika autentikasi; pada dasarnya, menyesuaikan sistem agar sesuai dengan kebutuhan proyek Anda.

Siapkan Proyek Next.js

Untuk memulai, instal Next.js dengan menjalankan perintah di bawah ini pada terminal Anda.

npx create-next-app@latest next-auth-jwt --experimental-app

Panduan ini akan memanfaatkan Next.js 13 yang menyertakan direktori aplikasi.

Selanjutnya, instal dependensi ini di proyek Anda menggunakan npm, Manajer Paket Node.

npm install jose universal-cookie
instagram viewer

Jose adalah modul JavaScript yang menyediakan seperangkat utilitas untuk bekerja dengan JSON Web Tokens sementara cookie universal ketergantungan menyediakan cara sederhana untuk bekerja dengan cookie browser di lingkungan sisi klien dan sisi server.

Anda dapat menemukan kode proyek ini di sini Repositori GitHub.

Buat Antarmuka Pengguna Formulir Login

Buka src/aplikasi direktori, buat folder baru, dan beri nama Gabung. Di dalam folder ini, tambahkan yang baru halaman.js file dan sertakan kode di bawah ini.

"use client";
import { useRouter } from"next/navigation";

exportdefaultfunctionLoginPage() {
return (


Kode di atas membuat komponen fungsional halaman login yang akan membuat form login sederhana di browser untuk memungkinkan pengguna memasukkan nama pengguna dan kata sandi.

Itu gunakan klien pernyataan dalam kode memastikan bahwa batas dideklarasikan antara kode khusus server dan kode khusus klien di aplikasi direktori.

Dalam hal ini, digunakan untuk menyatakan bahwa kode di halaman login, khususnya, adalah menanganiKirimfungsi hanya dijalankan pada klien; jika tidak, Next.js akan menimbulkan kesalahan.

Sekarang, mari kita tentukan kode untuk menanganiKirim fungsi. Di dalam komponen fungsional, tambahkan kode berikut.

const router = useRouter();

const handleSubmit = async (event) => {
event.preventDefault();
const formData = new FormData(event.target);
const username = formData.get("username");
const password = formData.get("password");
const res = await fetch("/api/login", {
method: "POST",
body: JSON.stringify({ username, password }),
});
const { success } = await res.json();
if (success) {
router.push("/protected");
router.refresh();
} else {
alert("Login failed");
}
 };

Untuk mengelola logika otentikasi login, fungsi ini menangkap kredensial pengguna dari formulir login. Kemudian mengirimkan permintaan POST ke titik akhir API yang meneruskan detail pengguna untuk verifikasi.

Jika kredensialnya valid, yang menunjukkan bahwa proses login berhasil—API mengembalikan status sukses dalam responsnya. Fungsi handler kemudian akan menggunakan router Next.js untuk menavigasi pengguna ke URL tertentu, dalam hal ini, URL terlindung rute.

Tentukan Titik Akhir API Masuk

Di dalam src/aplikasi direktori, buat folder baru dan beri nama api. Di dalam folder ini, tambahkan yang baru login/route.js file dan sertakan kode di bawah ini.

import { SignJWT } from"jose";
import { NextResponse } from"next/server";
import { getJwtSecretKey } from"@/libs/auth";

exportasyncfunctionPOST(request) {
const body = await request.json();
if (body.username "admin" && body.password "admin") {
const token = awaitnew SignJWT({
username: body.username,
})
.setProtectedHeader({ alg: "HS256" })
.setIssuedAt()
.setExpirationTime("30s")
.sign(getJwtSecretKey());
const response = NextResponse.json(
{ success: true },
{ status: 200, headers: { "content-type": "application/json" } }
);
response.cookies.set({
name: "token",
value: token,
path: "/",
});
return response;
}
return NextResponse.json({ success: false });
}

Tugas utama API ini adalah memverifikasi kredensial login yang diteruskan dalam permintaan POST menggunakan data tiruan.

Setelah verifikasi berhasil, ini menghasilkan token JWT terenkripsi yang terkait dengan detail pengguna yang diautentikasi. Terakhir, ia mengirimkan respons yang berhasil ke klien, termasuk token dalam cookie respons; jika tidak, ia akan mengembalikan respons status kegagalan.

Menerapkan Logika Verifikasi Token

Langkah awal dalam otentikasi token adalah menghasilkan token setelah proses login berhasil. Langkah selanjutnya adalah menerapkan logika untuk verifikasi token.

Pada dasarnya, Anda akan menggunakan jwtVerifikasi fungsi yang disediakan oleh Jose modul untuk memverifikasi token JWT yang diteruskan dengan permintaan HTTP berikutnya.

Dalam src direktori, buat yang baru libs/auth.js file dan sertakan kode di bawah ini.

import { jwtVerify } from"jose";

exportfunctiongetJwtSecretKey() {
const secret = process.env.NEXT_PUBLIC_JWT_SECRET_KEY;
if (!secret) {
thrownewError("JWT Secret key is not matched");
}
returnnew TextEncoder().encode(secret);
}

exportasyncfunctionverifyJwtToken(token) {
try {
const { payload } = await jwtVerify(token, getJwtSecretKey());
return payload;
} catch (error) {
returnnull;
}
}

Kunci rahasia digunakan untuk menandatangani dan memverifikasi token. Dengan membandingkan tanda tangan token yang didekodekan dengan tanda tangan yang diharapkan, server dapat secara efektif memverifikasi bahwa token yang diberikan valid, dan pada akhirnya, mengotorisasi permintaan pengguna.

Membuat .env file di direktori root dan tambahkan kunci rahasia unik sebagai berikut:

NEXT_PUBLIC_JWT_SECRET_KEY=your_secret_key

Buat Rute yang Dilindungi

Sekarang, Anda perlu membuat rute yang hanya dapat diakses oleh pengguna terautentikasi. Untuk melakukannya, buat yang baru dilindungi/halaman.js berkas di src/aplikasi direktori. Di dalam file ini, tambahkan kode berikut.

exportdefaultfunctionProtectedPage() {
return<h1>Very protected pageh1>;
}

Buat Hook untuk Mengelola Status Otentikasi

Buat folder baru di src direktori dan beri nama kait. Di dalam folder ini tambahkan yang baru gunakanAuth/index.js file dan sertakan kode di bawah ini.

"use client" ;
import React from"react";
import Cookies from"universal-cookie";
import { verifyJwtToken } from"@/libs/auth";

exportfunctionuseAuth() {
const [auth, setAuth] = React.useState(null);

const getVerifiedtoken = async () => {
const cookies = new Cookies();
const token = cookies.get("token")?? null;
const verifiedToken = await verifyJwtToken(token);
setAuth(verifiedToken);
};
React.useEffect(() => {
getVerifiedtoken();
}, []);
return auth;
}

Kait ini mengatur status autentikasi di sisi klien. Ini mengambil dan memverifikasi validitas token JWT yang ada di cookie menggunakan verifikasiJwtToken fungsi, lalu atur detail pengguna yang diautentikasi ke autentik negara.

Dengan demikian, komponen lain dapat mengakses dan memanfaatkan informasi pengguna yang diautentikasi. Hal ini penting untuk skenario seperti membuat pembaruan UI berdasarkan status autentikasi, membuat permintaan API berikutnya, atau merender konten berbeda berdasarkan peran pengguna.

Dalam hal ini, Anda akan menggunakan hook untuk merender konten berbeda di rumah rute berdasarkan status otentikasi pengguna.

Pendekatan alternatif yang mungkin Anda pertimbangkan adalah penanganan manajemen negara menggunakan Redux Toolkit atau mempekerjakan a alat manajemen negara seperti Jotai. Pendekatan ini menjamin komponen bisa mendapatkan akses global ke status autentikasi atau status lain yang ditentukan.

Silakan dan buka aplikasi/halaman.js file, hapus kode boilerplate Next.js, dan tambahkan kode berikut.

"use client" ;

import { useAuth } from"@/hooks/useAuth";
import Link from"next/link";
exportdefaultfunctionHome() {
const auth = useAuth();
return<>

Public Home Page</h1>

Kode di atas menggunakan gunakanAuth kait untuk mengelola status otentikasi. Dengan melakukan hal tersebut, ia secara kondisional merender laman beranda publik dengan tautan ke Gabung rute halaman ketika pengguna tidak diautentikasi, dan menampilkan paragraf untuk pengguna yang diautentikasi.

Tambahkan Middleware untuk Menerapkan Akses Resmi ke Rute yang Dilindungi

Dalam src direktori, buat yang baru middleware.js file, dan tambahkan kode di bawah ini.

import { NextResponse } from"next/server";
import { verifyJwtToken } from"@/libs/auth";

const AUTH_PAGES = ["/login"];

const isAuthPages = (url) => AUTH_PAGES.some((page) => page.startsWith(url));

exportasyncfunctionmiddleware(request) {

const { url, nextUrl, cookies } = request;
const { value: token } = cookies.get("token")?? { value: null };
const hasVerifiedToken = token && (await verifyJwtToken(token));
const isAuthPageRequested = isAuthPages(nextUrl.pathname);

if (isAuthPageRequested) {
if (!hasVerifiedToken) {
const response = NextResponse.next();
response.cookies.delete("token");
return response;
}
const response = NextResponse.redirect(new URL(`/`, url));
return response;
}

if (!hasVerifiedToken) {
const searchParams = new URLSearchParams(nextUrl.searchParams);
searchParams.set("next", nextUrl.pathname);
const response = NextResponse.redirect(
new URL(`/login?${searchParams}`, url)
);
response.cookies.delete("token");
return response;
}

return NextResponse.next();

}
exportconst config = { matcher: ["/login", "/protected/:path*"] };

Kode middleware ini bertindak sebagai penjaga. Ia memeriksa untuk memastikan bahwa ketika pengguna ingin mengakses halaman yang dilindungi, mereka diautentikasi dan diberi wewenang untuk mengakses rute, selain itu, mengarahkan pengguna yang tidak sah ke halaman login.

Mengamankan Aplikasi Next.js

Otentikasi token adalah mekanisme keamanan yang efektif. Namun, ini bukan satu-satunya strategi yang tersedia untuk melindungi aplikasi Anda dari akses tidak sah.

Untuk memperkuat aplikasi terhadap lanskap keamanan siber yang dinamis, penting untuk menerapkan keamanan yang komprehensif pendekatan yang secara holistik mengatasi potensi celah keamanan dan kerentanan untuk menjamin secara menyeluruh perlindungan.