admin管理员组文章数量:1356815
What I want
I am developing an app in Next.js 15, and for authorization, I want to use JWT and Refresh Token, following this process:
- When a user visits a restricted page, the system checks whether they have an
access_token
cookie (a JWT with a validity of 7 minutes), which contains theiruserId
, and verifies if it is valid.- If valid, it recreates this JWT, renewing its validity for another 7 minutes, sends it back to the client as a cookie, retrieves the user session (for subsequent validation) e continue.
- If invalid, it checks whether they have a
refresh_token
cookie (just a token with a validity of 7 days) and:- If not, redirects them to the login page.
- If they do, it validates in the database (in my case, KV or Redis) whether this token exists, retrieves the
userId
, recreates both theaccess_token
(JWT) and therefresh_token
, updates the cookies, retrieves the user session, and continue.
The problem
The issue I'm facing is with this Refresh Token Rotation:
When accessing the page (e.g., app/dashboard/page.js
), I can read the cookies for verification, but I cannot update the cookies because they can only be "written" via Server Actions or Route Handlers.
- I’ve tried creating a Server Component (
UpdateAccessCookies
) to place on the page that would solely be responsible for sending the cookies, but doing this causes the system to enter a loop. - I’ve also tried using an API, but when making a POST request, the system didn’t receive the cookies—and I’m not sure if this would be the best option. I’d prefer to find a way to use Server Actions.
Here are some example codes
// Register Page
import { getCurrentSession } from '@/services/session';
import { RegisterForm } from './Form';
export default async function Register() {
const { session, data } = await getCurrentSession();
return (
<>
<h1>Register</h1>
<RegisterForm/>
</>
);
}
//session.js
'use server'
//...imports...
export async function getCurrentSession() {
const accessToken = await getCookie('access_token');
let data = {};
if (accessToken) {
const jwtValidation = await validarJWT(accessToken);
if (jwtValidation) {
data.userId = jwtValidation.userId;
data.jwt = {
token: await createJWT({ userId: jwtValidation.userId }),
expiraEm: JWT_EXPIRES_IN,
};
}
}
if (!data.userId) {
const refreshToken = await getCookie('refresh_token');
if (!refreshToken) {
return { session: null, data: null };
}
data.userId = await getStorageAdapterData('refresh_token', refreshToken);
if (!data.userId) {
return { session: null, data: null };
}
data.jwt = {
token: await createJWT({ userId: data.userId }),
expiraEm: JWT_EXPIRES_IN,
};
data.refreshToken = {
token: await createRefreshToken(data.userId, refreshToken),
expiraEm: SESSION_EXPIRES_IN,
};
}
const session = await getStorageAdapterData('session', data.userId);
if (!session) {
return { session: null, data: null };
}
return { session, data };
}
As I mentioned, I have already tried updating the cookies:
- On the page, right after
getCurrentSession
(would be ideal) - In session.js, right after renewing the tokens
- In a Refresh-cookies component (like the code below)
// Register Page 2
import { getCurrentSession } from '@/services/session';
import { RegisterForm } from './Form';
import RefreshCookies from '@/components/refresh-cookies';
export default async function Register() {
const { session, data } = await getCurrentSession();
return (
<>
<h1>Register</h1>
<RegisterForm/>
<RefreshCookies
jwt={data?.jwt}
refreshToken={data?.refreshToken}
/>
</>
);
}
//Refresh-cookies.js
'use client';
import { useEffect, useState } from 'react';
import { createCookie } from '@/services/cookies';
async function updateCookies(jwt, refreshToken) {
if (jwt) {
await createCookie('access_token', jwt.token, jwt.expires);
}
if (refreshToken) {
await createCookie(
'refresh_token',
refreshToken.token,
refreshToken.expires
);
}
}
export default function RefreshCookies({ jwt, refreshToken }) {
const [Updatedcookies, setUpdatedCookies] = useState(false);
useEffect(() => {
async function update() {
if (!Updatedcookies && (jwt || refreshToken)) {
await updateCookies(jwt, refreshToken);
}
}
update();
}, [jwt, refreshToken, Updatedcookies]);
}
What would you suggest?
Note: I don’t want to use an external library. I also don’t want to perform verification using middleware because it would check on every request to restricted pages, which would significantly increase request time.
UPDATE
I've manage to make it work changing a little bit, the logic on the Refresh-cookies.js (above), now it looks like this:
//Refresh-cookies.js
'use client';
import { useEffect, useState } from 'react';
import { createCookie } from '@/services/cookies';
async function updateCookies(jwt, refreshToken) {
if (jwt) {
await createCookie('access_token', jwt.token, jwt.expires);
}
if (refreshToken) {
await createCookie(
'refresh_token',
refreshToken.token,
refreshToken.expires
);
}
}
export default function RefreshCookies({ jwt, refreshToken }) {
const [Updatedcookies, setUpdatedCookies] = useState(false);
useEffect(() => {
async function update() {
if (refreshToken || !Updatedcookies && jwt)) { // *CHANGED HERE!
await updateCookies(jwt, refreshToken);
}
}
update();
}, [jwt, refreshToken, Updatedcookies]);
}
Now it updates the cookies: 1. if it received a refreshToken (in which case the 'access_token' was invalidated or expired) OR 2. if it received a JWT and the cookies aren't yet updated. This way it doesn't get on a loop. What do you guys think?
本文标签: javascriptRefresh Token Rotation on Nextjs 15Stack Overflow
版权声明:本文标题:javascript - Refresh Token Rotation on Next.js 15 - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744071028a2585884.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论