refresh token rotation 질문
396
작성한 질문수 6
안녕하세요 강의를 듣고 next-auth를 활용하여 개발 중에 궁금한 점이 생겨 질문 드립니다.
프로젝트에서 일반 로그인과 소셜 로그인을 모두 사용하고 있어
next-auth의 signin callback에서 로그인일 경우 자체 서버에 요청하여 accessToken과 refreshToken을 발급 받고 jwt callback에서 엑세스 토큰의 만료 시간을 체크하여 만료 시에 재발급 요청이 되도록 구현하고 있습니다.
이렇게 구현했을 경우 간헐적으로 서버 시간과의 타이밍 이슈 때문인지 api 요청 시에 401 토큰 만료 에러가 발생하는 순간이 존재합니다.
따라서 401 상태코드일 경우에 refreshToken 토큰 재발급 요청을 하려고 하는데 refreshToken이 현재 next-auth에서 jwt 콜백에서 리턴되어 jwt토큰으로 생성되어 있습니다.
이 401일 경우 재발급 요청 처리를 클라이언트 단에서 할 경우 refreshToken이 노출되어 보안상 이슈가 있을 것으로 예상이 되는데 서버단에서 처리를 하려면 next에서 어디서 처리를 하면 좋을 지 문의드립니다.
async signIn({ account, user, credentials }) {
const cookieStore = cookies();
const authorizationParams = JSON.parse(
cookieStore.get("authorization-params")?.value ?? ""
);
const action = authorizationParams.action;
user.platform = authorizationParams.platform;
if (!account?.provider || !sns_type_map[account.provider]) {
throw new Error("Unsupported provider");
}
user.snsType = sns_type_map[account.provider];
if (action === auth_action_type.signin) {
return handleSignIn(user); // getAccessToken
}
if (action === auth_action_type.signup) {
return handleSignUp();
}
return false;
},
async jwt({ token, account, user }) {
// Initial sign in
if (account && user) {
return {
...token,
...user,
accessToken: user.refreshToken,
expiresAt: new Date(
Date.now() + (user?.expiresIn ?? 0)
).toISOString(),
refreshToken: "refreshtoken",
};
}
// Return previous token if the access token has not expired yet
if (new Date() < new Date(token.expiresAt as string)) {
console.log("@@@@@@valid");
return token;
} else {
// Access token has expired, try to update it
console.log("@@@@@@expired");
const cookieStore = cookies();
const authorizationParams = JSON.parse(
cookieStore.get("authorization-params")?.value ?? ""
);
const body = {
....
};
const tokenData = await authApi.reissueAccessToken(body);
// reissue token
return {
...token,
...user,
accessToken: tokenData.accessToken,
expiresAt: new Date(
Date.now() + (tokenData.expiresIn ?? 0)
).toISOString(),
refreshToken: tokenData.refreshToken,
};
}
},
미들웨어에서 401 상태 코드 처리하는 것도 알아보았으나 일반적인 방식인지 궁금합니다.
미들웨어에서 401일때 재발급 요청 시 새로운 엑세스 토큰으로 재요청이 정상적으로 되는 것은 확인했으나 다시 next-auth의 jwt토큰에 재발급된 값을 세팅해줘야 하는데 어떻게 해야할지도 궁금합니다.
import { NextResponse } from 'next/server';
import { getToken } from 'next-auth/jwt';
export async function middleware(request) {
const token = await getToken({ req: request, secret: process.env.AUTH_SECRET });
if (request.nextUrl.pathname.startsWith('/gateway')) {
const accessToken = token?.accessToken;
const headers = new Headers(request.headers);
if (response.status === 401) {
const refreshToken = token?.refreshToken;
const refreshResponse = await fetch("/reissueToken")
const refreshData = await refreshResponse.json();
if (refreshResponse.ok) {
const newAccessToken = refreshData.accessToken;
headers.set('Authorization', `Bearer ${newAccessToken}`);
const newResponse = NextResponse.next({
request: {
headers: request.headers,
},
});
}
// 토큰 재발급 실패 시 처리
return NextResponse.redirect('/login');
}
return NextResponse.next(response);
}
return NextResponse.next();
}
답변 1
0
현재 jwt 메서드에서 return에 엑세스토큰과 리프레시토큰을 다 넣고 계신데 이렇게 하면 프론트에 액세스토큰과 리프레시 토큰이 다 전송될 것 같고요(물론 JWE라서 암호화는 되어있겠지만)
리프레시 토큰은 그냥 DB에 저장하거나 Redis에 저장하시면 됩니다. 그리고 그걸 업데이트하거나 불러오는 건 api routes로 만들어두시면 되고요. middleware든 어디든 리프레시토큰을 수정/사용할 때 그 api routes를 호출하시면 됩니다. api routes 호출할 때는 fetch에 header로 cookie 넣어주셔야 하고요.
0
사용자가 세션에 접근할 때마다 암호화된 authjs.session-token 쿠키 값이 바뀌고 있어 쿠키값을 업데이트해줘도 원복되는 현상이 발생하고 있는데 세션에 접근할때마다 암호화된 값이 바뀌는 것이 스펙일까요?? 클라이언트, 서버단에서 접근할때마다 쿠키값이 바뀌는 현상을 확인했고 jwt 콜백에서 토큰을 출력해봤을때 값이 바뀌어있지는 않더라구요.
캡처링부분 질문있습니다.
0
76
2
깃에 소스코드를 찾을 수 없습니다.
0
113
2
useInfiniteQuery promise와 react use 사용시 페이지 무한 로딩
0
98
1
import 파일 경로를 찾지 못 해서 에러가 발생합니다.
0
111
2
css 라이브러리 추천 부탁드립니다
0
141
2
팔로우 추천 목록이 빈 배열로 들어옵니다.
0
133
1
게시물 업로드 시 userId가 undefined로 들어가는 오류
0
119
1
useSuspenseQuery 사용 시 SSR 401 이슈 관련
0
172
1
리액트 쿼리 useinfinitequery 무한스크롤 구현 시 페이지가 이동할 경우 데이터가 보존되게 할 수 있나요??
0
184
3
폴링이 필요없는 이유
0
93
2
next Request Memoization과 react cache
0
110
2
seo 최적화 기준은 데이터 fetching인가요 아님 데이터 렌더링인가요?
0
84
2
next.js 서버fetch 에러 fallback ui 구현 방법
0
173
2
프레임워크 여론 파악법
0
125
2
필터옵션이 많은 페이지에서 서버 fetch를 하는게 맞는걸까요??
0
103
2
서버 fetch suspense 로 감싸고 새로고침 시 잠시 빈 화면이 노출된 후 fallback ui가 노출됩니다.
0
102
2
template.tsx 내 서버fetch 응답값과 클라이언트 컴포넌트 상태값 싱크가 맞지 않는 이슈
0
66
2
Auth.js 사용 시 authorize 함수가 호출되지 않습니다
0
132
2
next.js 에서 로그인에 관하여
0
139
1
Next의 route handler에 대한 질문이 있습니다.
0
101
2
게시판 리스트 만들때 use client를 어디서부터 집어넣어야할지 모르겠습니다
0
98
2
프라이빗 폴더를 해야 하는 이유가 모호한 것 같아요.
0
85
2
vanilla-extract 못찾는 문제
0
230
2
fetch 캐싱과 revalidate 관련
0
85
2





