NextAuth sendet beim Neuladen der Seite zwei Aktualisierungsanfragen gleichzeitig (Rotation des Aktualisierungstokens).JavaScript

Javascript-Forum
Anonymous
 NextAuth sendet beim Neuladen der Seite zwei Aktualisierungsanfragen gleichzeitig (Rotation des Aktualisierungstokens).

Post by Anonymous »

Ich verwende NextAuth mit einem benutzerdefinierten Backend in meiner Next.js-App.
Wenn ich die Seite aktualisiere, werden fast gleichzeitig zwei Aktualisierungsanfragen gesendet.
Die erste Anfrage ruft korrekt /auth/refresh auf und erhält ein neues AccessToken und RefreshToken.
Unmittelbar danach wird eine zweite Anfrage gesendet, die jedoch weiterhin die alte Aktualisierung verwendet Token.
Das Backend gibt dann 401 zurück, wodurch beide Token ungültig werden.
Danach sind keine weiteren API-Aufrufe erfolgreich, bis ich mich erneut anmelde.
Ich versuche zu verstehen:
Warum wird der NextAuth-JWT-Rückruf beim Neuladen der Seite zweimal aufgerufen?
Wie kann ich das verhindern? Können mehrere Aktualisierungsaufrufe gleichzeitig erfolgen?
Hier ist der relevante Teil meiner Konfiguration:

Code: Select all

// auth.config.ts
import type { NextAuthConfig } from "next-auth"
import Credentials from "next-auth/providers/credentials"
import validateCredential from "../server/actions/user/validateCredential"

async function refreshAccessToken(token: any) {
const BACKEND_URL = process.env.NEXT_PUBLIC_API_URL!

try {
const res = await fetch(`${BACKEND_URL}/auth/refresh`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ refresh_token: token.refreshToken }),
cache: "no-store",
})

if (!res.ok) throw new Error("Refresh failed")

const data = await res.json()
const newAccessToken = data.access_token || token.accessToken
const newRefreshToken = data.refresh_token || token.refreshToken

const payload = JSON.parse(
Buffer.from(newAccessToken.split(".")[1], "base64").toString()
)
const newExp = payload?.exp ? payload.exp * 1000 : undefined

return {
...token,
accessToken: newAccessToken,
refreshToken: newRefreshToken,
accessTokenExpires: newExp,
}
} catch (e) {
return { ...token, error: "RefreshAccessTokenError" }
}
}

const authConfig: NextAuthConfig = {
providers: [
Credentials({
async authorize(credentials) {
const user = await validateCredential(credentials as any)
return user ?? null
},
}),
],
callbacks: {
async jwt({ token, user }) {
if (user) {
return {
...token,
accessToken: user.accessToken,
refreshToken: user.refreshToken,
accessTokenExpires: user.accessTokenExpires,
}
}

const now = Date.now()
if (token.accessTokenExpires && now < token.accessTokenExpires - 10000) {
return token
}

if (token.refreshToken) {
return await refreshAccessToken(token)
}

return { ...token, error: "RefreshAccessTokenError" }
},
},
}

export default authConfig
Und meine Anmeldeinformationsvalidierung:

Code: Select all

// validateCredential.ts
export default async function validateCredential(values) {
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/login/verify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
cache: 'no-store',
body: JSON.stringify(values),
})

if (!res.ok) return null

const data = await res.json()
return {
id: String(data.user.id),
accessToken: data.access_token,
refreshToken: data.refresh_token,
accessTokenExpires: data.access_token_exp,
}
}

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post