Google 로그인 시도 시 아래 에러와 함께 "Server error" 화면이 뜬다.
InvalidCheck: pkceCodeVerifier value could not be parsed.
// 좀 더 정확한 에러 내용
[31m[auth][error][0m InvalidCheck: pkceCodeVerifier value could not be parsed. Read more at https://errors.authjs.dev#invalidcheckPKCE(Proof Key for Code Exchange)는 OAuth 2.0의 보안 확장이다.
흐름은 이렇다:
로그인 클릭 → NextAuth가 code_verifier(랜덤 문자열)를 생성
이걸 쿠키에 암호화해서 저장하고, 해시값(code_challenge)을 Google에 전달
Google 인증 완료 → 콜백으로 돌아옴
NextAuth가 쿠키에서 code_verifier를 꺼내서 Google에 보내 토큰 교환
4번에서 쿠키를 못 읽으면 pkceCodeVerifier value could not be parsed 에러가 터진다.
쉽게 말하면, PKCE는 client_secret을 대체하는 게 아니라, authorization code injection 공격을 막는 추가 방어선
이번에는 두 가지가 겹쳤다.
AUTH_URL 환경변수 미설정NextAuth는 AUTH_URL로 콜백 URL을 결정한다. 이 값이 없으면 요청의 Host 헤더에서 추론하는데, Vercel 서버리스 환경에서는 내부 호스트명과 외부 도메인이 다를 수 있다.
환경변수 | 역할 |
|---|---|
| 쿠키 암호화/복호화 키 |
| 콜백 URL 및 쿠키 도메인 결정 |
AUTH_SECRET만 있고 AUTH_URL이 없으면, 쿠키가 설정될 때와 읽힐 때의 도메인이 달라질 수 있다.
sameSite 기본값 문제NextAuth의 PKCE 쿠키 기본 설정은 sameSite: "lax"다.
lax는 같은 사이트 내 탐색에서만 쿠키를 전달한다. 그런데 OAuth 흐름은:
mory.blog → accounts.google.com → mory.blog/api/auth/callback/google
Google에서 돌아오는 리다이렉트가 크로스사이트 요청으로 간주될 수 있다. 이 경우 sameSite: "lax" 쿠키가 전달되지 않아서 NextAuth가 code_verifier를 찾지 못한다.
AUTH_URL=https://www.mory.blogsrc/lib/auth.ts 수정export const { handlers, signIn, signOut, auth } = NextAuth({
trustHost: true,
cookies: {
pkceCodeVerifier: {
name: "next-auth.pkce.code_verifier",
options: {
httpOnly: true,
sameSite: "none",
path: "/",
secure: true,
},
},
},
// ... 나머지 설정
});trustHost: true는 Vercel처럼 리버스 프록시 뒤에서 동작할 때 Host 헤더를 그대로 신뢰하라는 설정이다. 이게 없으면 NextAuth가 호스트를 잘못 판단해서 쿠키 설정이 꼬일 수 있다.
sameSite: "none"은 크로스사이트에서도 쿠키가 전달되도록 허용한다. secure: true와 반드시 함께 써야 한다 (HTTPS에서만 쿠키 전송).
Google({
checks: ["state"], // PKCE 대신 state 체크만 사용
})Google은 client_secret을 사용하는 Confidential Client이므로 PKCE 없이도 보안이 유지된다. PKCE는 client_secret을 가질 수 없는 Public Client(모바일, SPA)에서 더 중요하다.
NextAuth v5에서 Vercel 배포 시 필수 환경변수는 세 가지: AUTH_SECRET, AUTH_URL, Google/GitHub OAuth 키
AUTH_SECRET만 설정하고 AUTH_URL을 빼먹기 쉽다. 둘 다 있어야 쿠키가 제대로 동작한다
sameSite 쿠키 정책은 OAuth 리다이렉트 흐름에서 의외의 복병이 된다
next-auth v5 beta는 이 이슈가 여러 GitHub 이슈에서 미해결 상태로 남아있다. Auth.js 프로젝트 자체가 Better Auth 팀에 이관되었으므로, 장기적으로는 마이그레이션을 고려할 필요가 있다