개발자를 위한 Google OAuth 인증 흐름 및 보안 설계 원칙
클라이언트에서 id_token, access_token을 직접 받아 서버로 전달하는 방식
문제점:
Authorization Code + PKCE 방식으로, 클라이언트는 code만 받고, 토큰은 서버가 교환
장점:
**PKCE(픽시)**는
“클라이언트 시크릿을 사용할 수 없는 앱(예: 모바일, SPA 등)”
안전하게 OAuth 인증을 수행하기 위해 고안된 보안 메커니즘
원래 OAuth2의 Authorization Code Flow는 클라이언트 시크릿을 요구했지만, 모바일 앱은 이 시크릿을 안전하게 숨길 수 없어, 대신 PKCE로 code_verifier와 code_challenge를 사용해 인증 요청의 정당성을 검증함.
| 항목 | 설명 |
|---|---|
| code_verifier | 앱이 생성한 무작위 문자열 (비밀번호처럼 생각하면 됨) |
| code_challenge | code_verifier를 SHA-256으로 해싱한 후, base64-url 인코딩한 값 |
| code_challenge_method | 보통 S256 (SHA-256 기반) 사용 |
앱 → 구글 로그인 페이지 요청 시:
- code_challenge
- code_challenge_method=S256
구글 로그인 완료 → 앱은 code만 받음
앱 → 서버로 다음 전송:
- code
- code_verifier
- osType (ANDROID or IOS)
osType은 구글 소셜 로그인에서만 필요한 값으로, ANDRIOD용 ClientId와 IOS용 ClientId가 나뉘어있기 때문이다. 그러나 이는 어떤 SDK를 사용하느냐, 어떻게 통합하는지에 따라 다르므로, Web application을 쓸 때도 있다. Google에서 제공하는 통신 규격 확인 후 선택하기 바란다.

POST /token
- code
- code_verifier
🔐 Google은 자체적으로 code_verifier로 code_challenge를 재생성해,
초기 요청에서 전달받은 code_challenge와 비교하여 동일하면 access_token, id_token을 발급한다.
단순히 authorization code만 탈취해서는 토큰을 못 받기 때문
| 개념 | 역할 |
|---|---|
| code_verifier | 토큰 교환 시 증명자료 (비밀번호 같은 것) |
| code_challenge | 구글 서버가 사전에 받아놓는 검증용 해시 |
| PKCE | 이 둘을 통해 authorization code 탈취 공격을 방어하는 OAuth 확장 기법 |

이때 서비스 성격에 따라 완전 회원가입을 시키는 대신, 임시 유저로 넘겨서 소셜정보로 완벽히 채울 수 없는 부분을 다 채워야 할 수 있다.
| 단계 | 주체 | 요청/응답 | 설명 |
|---|---|---|---|
| (1) | 앱 클라이언트 → Google | OAuth 요청 (client_id, code_challenge, redirect_uri, scope, response_type=code) | PKCE 사용하여 보안 강화 |
| (2) | Google → 사용자 | 로그인 UI | 사용자 계정 및 권한 동의 |
| (3) | Google → 앱 클라이언트 | Authorization Code | 일회용 코드 |
| (4) | 앱 클라이언트 → 앱 서버 | code, code_verifier, osType 포함 POST 요청 | 클라이언트가 받은 code를 서버에 위임 |
| (5) | 앱 서버 → Google | client_id, client_secret(optional), code, code_verifier, grant_type=authorization_code | Google OAuth 서버에 토큰 요청 |
| (6) | Google → 앱 서버 | access_token, id_token, expires_in, token_type 등 | access_token은 Google API용, id_token은 사용자 인증용 |
| (7) | 앱 서버 내부 | id_token의 aud, iss, exp 검증 | 신뢰성 검증 |
| (8) | 앱 서버 내부 | 유저 회원가입 or 로그인 처리 | 유저 정보 업데이트 등 |
| (9) | 앱 서버 → 앱 클라이언트 | 우리 시스템의 JWT 토큰 발급 | 앱에서는 이 토큰으로 로그인 완료 처리 |
| 항목 | 목적 | 용도 | 노출 여부 |
|---|---|---|---|
| id_token | 사용자의 신원 확인 | Google이 발급한 JWT (sub, email 포함) | 서버에서 검증 필요 |
| access_token | Google API 호출 | Google People API 등 접근 가능 | 노출되면 위험 |