본문 바로가기

자바스크립트

NextJS, 미해결) InvalidCheck: pkceCodeVerifier value could not be parsed. Read more at https://errors.authjs.dev#invalidcheck

처음 보는 에러가 나왔습니다.

이슈로 등록된 것도 확인해봤지만 최근에 발생한 에러인지 해결법은 없었습니다. (링크)

보통 코드를 수정하거나 생성하면 에러가 나오기 마련이지만 기존 oauth코드 부분에서는 최근 수정한 적이 없습니다. 한마디로 잘 되던 코드가 갑자기 동작을 안하게 된거죠..

불과 하루 전 DB를 옮기느라 DB관련 로직을 수정한 것 외에는 전부 UI를 수정했으니 정말 황당합니다.

 

우선 에러에서 알려준 링크로 들어갔습니다.

https://errors.authjs.dev#invalidcheck

 

Auth.js | Errors

Authentication for the Web

authjs.dev

링크에 나와있는 설명은

"PKCE, 상태 또는 nonce OAuth 검사를 수행할 수 없을 때 발생합니다. 이는 OAuth 제공자가 잘못 구성되었거나 브라우저에서 쿠키를 차단할 경우 발생할 수 있습니다."라고 나왔습니다. 

 

에러를 해결하기에 앞서 PKCE에 대해 알아봐야겠습니다.

 

PKCE(Proof Key for Code Exchange)

요약하자면 다음과 같다. "OAuth 2.0은 널리 사용되는 인증 프로토콜이지만, 인증 코드 가로채기와 같은 보안 취약점이 있습니다. 이를 해결하기 위해 PKCE를 사용하며, 클라이언트가 코드 교환 과정에서 무작위 문자열을 생성하여 보안을 강화합니다. PKCE는 모든 클라이언트에서 적용 가능하며, OAtuh2.1에서는 필수로 권고되는 보안 확장입니다."

 

일반적으로 널리 사용되는 OAuth 2.0 인증 흐름입니다.

  1. 사용자 로그인: 사용자가 애플리케이션에서 로그인 버튼을 클릭합니다.
  2. 인증요청: 애플리케이션이 인증 서버(Google 등)에 로그인합니다.
  3. 사용자 승인: 사용자가 인증 서버에서 자신의 자원에 접근할 수 있는 구너한을 애플리케이션에 부여합니다.
  4. 인증 코드 반환: 인증 서버가 애플리케이션에 인증 코드를 반환합니다.
  5. 액세스 토큰 교환: 애플리케이션이 인증 코드를 서버에 다시 보내고 엑세스 토큰을 받습니다. 이 토큰을 사용하여 자원에 접근할 수 있습니다.

공격자(해커)는 이런 흐름 속에서 다음 조건이 충족될 경우 인증 코드를 가로챌 수 있는 보안 위험이 있습니다.

  • 공격자가 배포한 악성 애플리케이션이 사용자의 기기에 설치된 상태에서 OAuth 2.0인증을 진행합니다.
  • 공격자는 이미 App Scheme을 변조해두었으며, Client Secret값을 알아낸 상태입니다.

 

 

만약 위 조건이 충족될 경우 공격자는 다음 과정으로 코드를 가로챌 수 있습니다.

  1. 스마트폰 등의 기기에서 네이티브 애플리케이션이 브라우저/운영 체제를 통해 OAuth 2.0 인증 요청을 보냅니다.
    • 이 때  리디렉션 엔드포인트 URI는 Custom URI Scheme 을 사용합니다. ( myapp://callback )
  2. 인증 서버로 인증을 요청합니다.
  3. 인증 서버가 인증 코드를 반환합니다.
  4. 제공된 리디렉션 엔드포인트 URI를 통해 인증 코드가 요청자에게 반환됩니다.
    • 리디렉션
      • 인증 서버가 인증 코드를 myapp://callback URI로 반환할 때, OS 는 이 URI를 처리할 수 있는 애플리케이션을 찾습니다.
    • 악성 앱이 실행
      • 만약 악성 애플리케이션이 이 URI를 먼저 핸들링하도록 설정되어 있다면, 인증 코드는 악성 애플리케이션으로 전달됩니다.
      • 만일 사용자가 실수로 'FakeBankApp'을 선택하면, 인증 코드는 'FakeBankApp'으로 전달됩니다.
    • 코드 가로채기
      • 악성 애플리케이션은 이 인증 코드를 사용하여 OAuth 2.0 인증 서버에 접근하고, 정당한 애플리케이션 대신 액세스 토큰을 요청할 수 있습니다.
  5. 액세스 토큰 요청
    • 악성 애플리케이션이 액세스 토큰을 획득하면, client secret 값을 포함하여 OAuth 2.0 서버에 엑세스 토큰을 요청합니다.
  6. 사용자의 액세스 토큰이 응답됩니다. 이제 공격자는 발급된 토큰을 통해 사용자의 자원에 접근할 수 있습니다.

 

이런 공격을 방지하기 위해 등장한 것이 PKCE입니다. PKCE는 "코드 교환을 위한 증명 키"라는 의미입니다.

PKCE는 가로채기 공격을 완화하기 위해 "code verifier"라는 암호화적으로 안전한 무작위 문자열을 사용합니다.

매 인증마다 고유한 "code verifier"가 생성되며 이를 변환한 "code challenge"값이 인증 서버로 전송되어 인증 코드를 얻습니다.

그런 다음, 인증 코드를 "code verifier"와 함께 토큰 엔드포인트로 전송합니다.

서버는 이전에 받은 "code challenge"와 함께 비교하며 클라이언트의 코드 검증자 소유 증명을 수행합니다.

이 과정은 TLS를 통해 전송되어 가로챌 수 없기 때문에, 공격자가 이 일회용 키를 알 수 없으므로 효과적인 방어책으로 작동합니다.

 

PKCE 를 통한 인증 Flow 는 아래와 같습니다.

  1. 클라이언트:
    • "code_verifier" 를 생성합니다.
    • 이를 변환 (t, transformation) 하여 "code_challenge"를 만듭니다. 변환 방법은 "plain" 또는 "S256"입니다.
    • 변환 방법 (t_m, transformation method) 과 함께 OAuth 2.0 인증 요청에 "code_challenge"를 포함시켜 전송합니다.
  2. 인증 엔드포인트
    1. 요청을 받고 응답을 보내면서 "code_challenge"와 변환 방법을 세션에 기록합니다.
  3. 클라이언트:
  4. 인증서버
    1. 인증 코드를 받은 후, 액세스 토큰 요청에 "code_verifier"를 포함하여 보냅니다
    2. "code_verifier"를 수신하고, 이를 변환하여 기록된 "code_challenge"와 비교합니다.
    3. 값이 일치하지 않으면 접근을 거부합니다.

 

 

 

구글은 기본적으로 PKCE를 사용합니다. 하지만 이를 자동으로 생성 및 사용하므로 Next-auth를 평소와 같이 사용하는 저에게는 이 문제는 아닌 것으로 생각됩니다.

 

여러가지를 시도해보았고, 잠재적인 해결 방법은 구글 시크릿모드로 진행하는 것이었습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

참고(PKCE) https://devocean.sk.com/blog/techBoardDetail.do?ID=166255&boardType=techBlog