인가 코드 플로

인가 코드 플로 (Authorization Code Grant)

OAuth 2.0에서 가장 널리 쓰이고, 또 가장 안전하다고 알려진 흐름이 바로 인가 코드 플로예요. 사용자를 로그인 페이지로 보내서 승인을 받은 뒤, 돌아온 **인가 코드(authorization code)**를 다시 액세스 토큰으로 바꾸는 2단계 방식을 취하죠. 웹 서버 앱뿐 아니라 모바일 앱 같은 public 클라이언트에서도 이 흐름을 쓰며, 특히 최근엔 PKCE라는 확장을 함께 적용해 보안을 더 끌어올리는 게 권장돼요. 이 문서에서는 이 흐름이 어떤 단계로 진행되는지, 그 안에 어떤 엔드포인트와 파라미터가 관여하는지 공식 스펙 기준으로 정리해 볼게요.

출처: OAuth 2.0 Authorization Code Grant (oauth.net)

동작 흐름

인가 코드 플로는 사용자가 브라우저를 통해 리소스 서버(또는 인가 서버)와 직접 마주친다는 점이 특징이에요. 클라이언트는 사용자 자격 증명을 직접 보지 않고, 흐름 전반에 걸쳐 중간 결과물만 주고받아요.

  1. 인가 요청 — 클라이언트가 사용자를 인가 서버의 authorization endpoint로 보내요. 이때 response_type=code, client_id, redirect_uri, scope, state 같은 파라미터를 함께 전달해요.
  2. 사용자 승인 + 리다이렉트 — 사용자가 로그인하고 동의하면, 인가 서버는 redirect_uri로 사용자를 되돌려 보내면서 URL에 인가 코드(code)와 state를 실어 줘요.
  3. 코드 → 토큰 교환 — 클라이언트는 이 인가 코드를 받아서 다시 token endpointgrant_type=authorization_code와 함께 보내고, 그 대가로 액세스 토큰(그리고 보통 리프레시 토큰)을 받아요.
  4. 보호 리소스 접근 — 받은 액세스 토큰으로 리소스 서버에 요청해요.

여기서 핵심은 이거예요. 인가 코드는 토큰과 달리 query string이나 URL에 잠시 노출될 수 있지만, 그 자체로는 아무런 권한도 주지 않는 일회용 값이라는 점이죠. 그래서 코드를 바로 뒤의 토큰 교환 단계에서만 쓸 수 있도록 설계됐어요. state 파라미터는 CSRF 공격을 막는 용도로, 브라우저에 넘긴 값과 돌아온 값이 일치하는지 검사해요.

PKCE 확장

모바일 앱처럼 클라이언트 시크릿을 안전하게 숨기기 어려운 public 클라이언트에서는 redirect_uri를 직접 제어할 수 있더라도 코드가 가로채질 위험이 남아요. 그래서 flow 시작 전에 한 번만 쓰는 code_verifier를 만들어 그 해시값인 code_challenge를 인가 요청에 보내고, 토큰 교환 때는 실제 code_verifier를 함께 보내 서로 짝이 맞는지 검증해요. 이렇게 하면 중간에 코드를 가로챈 공격자도 code_verifier를 모르기 때문에 토큰으로 바꿀 수 없어요. oauth.net도 이 흐름을 쓸 때 PKCE를 함께 적용할 것을 권장하고 있어요.

더 알아보기 (Learn more)