Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Authorization Code with PKCE(Proof Key for Code Exchange)

중간에 code 가로채고 먼저 accessToken 받아와서 해당 권한으로 리소스 서버에 접근하는 것을 막기 위한 프로토콜입니다. rfc 에 명시된 공격시나리오는 아래와 같아요.

PKCE

  • Summary : 2번 요청 보낼건데 첫 번째 요청에 hash(key) 전송하고 두 번째 요청에 key 전송해서, 두 번째 요청의 발신자가 첫 번째 발신자임을 증명하는 방식!

원리는 간단해요. 1번 과정에서 정상 앱은 secret_string(=code_verifier) 을 만들어서 hash(secret_string)(code_challenge) 를 만들고 이를 authorization server 로 보내면, 서버는 code_challenge 를 저장해놓고 code 를 앱으로 보내줍니다.

이 후, 정상 앱과 malicious 앱 둘 다 code 를 알게 되었습니다. 이제 legitimate 앱은 code 를 이용해서 access_token 을 받아오는데, 이 때 plain 한 code_verifier 를 함께 전달합니다. 또한 code_challenge 를 생성한 알고리즘(e.g. sha256)도 함께 전달하죠. malicious 앱은 전달할 code_verifier 를 모릅니다. 그래서 code 만을 보내죠. 하지만 authorization server 은 사전에 저장해둔 code 에 부여된 code challenge 가 있다는 것을 알고 있습니다. 그래서 아무런 code challenge 없이 code 만으로 access_token 을 받아오려는 시도를 거부합니다. 반면 legitimate 앱 은 code 와 code_verifier 를 함께 보냈죠? authorization server 는 code 에 부여된 code challenge 가 code_verifier 를 단방향 암호화한 값과 일치하는지 확인합니다. 일치하면 access_token 을 발급해줍니다.

이렇게 함으로써 authorization_code 가 하이재킹 되더라도 access_token 을 받아오는 것을 막을 수 있습니다 :) 이제 정상 앱이 accessToken 을 정상적으로 운용할 수 있게 되었습니다! 반면 웹 환경은 어떨까요?

뭐 웹 환경에서도 사용할 수 있습니다. 다만, 앱의 경우, iOS의 Keychain 및 Android의 Keystore 같은 안전한 저장소에 code_verifier 를 저장할 수 있지만, 웹은 저장할 공간이 마땅치 않습니다.

그래서 웹 환경에서는 클라이언트는 code_verifier 를 사용하지 않고, code 를 서버에 전달해 내부적으로 accessToken 받아서 처리하도록 합니다. 전통적이며 안전한 방법이죠.