Få mere kontrol over din Next.js-apps godkendelseslogik gennem tilpasset JWT-baseret godkendelsesimplementering.

Token-godkendelse er en populær strategi, der bruges til at beskytte web- og mobilapplikationer mod uautoriseret adgang. I Next.js kan du bruge godkendelsesfunktionerne fra Next-auth.

Alternativt kan du vælge at udvikle et brugerdefineret token-baseret autentificeringssystem ved hjælp af JSON Web Tokens (JWT'er). Ved at gøre det sikrer du, at du har mere kontrol over autentificeringslogikken; i det væsentlige, at tilpasse systemet til præcist at matche kravene i dit projekt.

Konfigurer et Next.js-projekt

For at komme i gang skal du installere Next.js ved at køre kommandoen nedenfor på din terminal.

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

Denne guide vil bruge Next.js 13, som inkluderer app-biblioteket.

Dernæst skal du installere disse afhængigheder i dit projekt ved hjælp af npm, Node Package Manager.

npm install jose universal-cookie

Jose er et JavaScript-modul, der giver et sæt hjælpeprogrammer til at arbejde med JSON Web Tokens, mens

universal-cookie afhængighed giver en enkel måde at arbejde med browsercookies i både klient- og server-miljøer.

Du kan finde dette projekts kode i denne GitHub-depot.

Opret brugergrænsefladen til loginformularen

Åbn src/app mappe, opret en ny mappe og navngiv den Log på. Tilføj en ny i denne mappe side.js fil og medtag koden nedenfor.

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

exportdefaultfunctionLoginPage() {
return (


Koden ovenfor opretter en login-side funktionel komponent, der vil gengive en simpel login-formular på browseren, så brugere kan indtaste et brugernavn og en adgangskode.

Det bruge klient sætning i koden sikrer, at der er erklæret en grænse mellem server-kun og klient-kun kode i app vejviser.

I dette tilfælde bruges det til at erklære, at koden på login-siden, især handleSendfunktion udføres kun på klienten; ellers vil Next.js give en fejl.

Lad os nu definere koden for handleSend fungere. Tilføj følgende kode inde i den funktionelle komponent.

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

For at administrere login-godkendelseslogikken henter denne funktion brugerlegitimationsoplysningerne fra loginformularen. Den sender derefter en POST-anmodning til et API-slutpunkt, der videregiver brugeroplysningerne til verifikation.

Hvis legitimationsoplysningerne er gyldige, hvilket indikerer, at login-processen var vellykket - API'en returnerer en successtatus i svaret. Behandlerfunktionen vil derefter bruge Next.js' router til at navigere brugeren til en specificeret URL, i dette tilfælde beskyttet rute.

Definer login API-slutpunktet

Inde i src/app mappe, opret en ny mappe og navngiv den api. Tilføj en ny i denne mappe login/route.js fil og medtag koden nedenfor.

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

Den primære opgave for denne API er at verificere login-legitimationsoplysningerne, der sendes i POST-anmodningerne ved hjælp af falske data.

Efter vellykket verifikation genererer den et krypteret JWT-token, der er knyttet til de godkendte brugeroplysninger. Endelig sender den et vellykket svar til klienten, inklusive tokenet i svar-cookies; ellers returnerer den et fejlstatussvar.

Implementer Token Verification Logic

Det første trin i token-godkendelse er at generere tokenet efter en vellykket login-proces. Det næste trin er at implementere logikken for token-verifikation.

I det væsentlige vil du bruge jwtBekræft funktion leveret af Jose modul til at verificere de JWT-tokens, der er bestået med efterfølgende HTTP-anmodninger.

I den src mappe, skal du oprette en ny libs/auth.js fil og medtag koden nedenfor.

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

Den hemmelige nøgle bruges til at signere og bekræfte tokens. Ved at sammenligne den afkodede token-signatur med den forventede signatur, kan serveren effektivt verificere, at det leverede token er gyldigt, og i sidste ende autorisere brugernes anmodninger.

skab .env fil i rodmappen og tilføj en unik hemmelig nøgle som følger:

NEXT_PUBLIC_JWT_SECRET_KEY=your_secret_key

Opret en beskyttet rute

Nu skal du oprette en rute, som kun godkendte brugere kan få adgang til. For at gøre det skal du oprette en ny protected/page.js fil i src/app vejviser. Tilføj følgende kode i denne fil.

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

Opret en krog for at administrere godkendelsestilstanden

Opret en ny mappe i src mappe og navngiv den kroge. Tilføj en ny i denne mappe useAuth/index.js fil og medtag koden nedenfor.

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

Denne krog styrer godkendelsestilstanden på klientsiden. Den henter og verificerer gyldigheden af ​​det JWT-token, der findes i cookies ved hjælp af verifyJwtToken funktion, og indstiller derefter de godkendte brugeroplysninger til auth stat.

Ved at gøre det giver det andre komponenter adgang til og udnytter den godkendte brugers information. Dette er vigtigt for scenarier som at lave UI-opdateringer baseret på godkendelsesstatus, fremsætte efterfølgende API-anmodninger eller gengivelse af forskelligt indhold baseret på brugerroller.

I dette tilfælde skal du bruge krogen til at gengive forskelligt indhold på hjem rute baseret på en brugers godkendelsestilstand.

En alternativ tilgang, du måske overvejer, er håndtering statsstyring ved hjælp af Redux Toolkit eller ansætte en statsstyringsværktøj som Jotai. Denne tilgang garanterer, at komponenter kan få global adgang til godkendelsestilstanden eller enhver anden defineret tilstand.

Gå videre og åbn app/page.js fil, slet boilerplate Next.js-koden og tilføj følgende kode.

"use client" ;

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

Public Home Page</h1>

Ovenstående kode bruger brugAuth krog for at administrere godkendelsestilstanden. Derved gengiver den betinget en offentlig hjemmeside med et link til Log på siderute, når brugeren ikke er godkendt, og viser et afsnit for en godkendt bruger.

Tilføj et middleware for at håndhæve autoriseret adgang til beskyttede ruter

I den src mappe, skal du oprette en ny middleware.js fil, og tilføj koden nedenfor.

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*"] };

Denne middleware-kode fungerer som en vagt. Den kontrollerer, at når brugere ønsker at få adgang til beskyttede sider, er de autentificeret og godkendt til at få adgang til ruterne, ud over at omdirigere uautoriserede brugere til login-siden.

Sikring af Next.js-applikationer

Token-godkendelse er en effektiv sikkerhedsmekanisme. Det er dog ikke den eneste tilgængelige strategi til at beskytte dine applikationer mod uautoriseret adgang.

For at styrke applikationer mod det dynamiske cybersikkerhedslandskab er det vigtigt at indføre en omfattende sikkerhed tilgang, der holistisk adresserer potentielle sikkerhedshuller og sårbarheder for at garantere grundig beskyttelse.