✅ Git 기반의 프로젝트 보고서 생성 서비스, Git Check 개발 기록
이번에는 구글 OAuth2를 이용하기 위해 어떤 플로우로 구글 인증 서버와 통신이 이루어져야하는지를 확인해보았다.
구글 OAuth2 - Auth Server 플로우
OpenID Connect | Sign in with Google | Google for Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 OpenID Connect 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 인증 및 승인에 Google의 OAuth 2.0
developers.google.com

1-2. 로그인 요청 및 CSRF 토큰 생성 (Auth Server)


CSRF 공격이란, 사용자가 의도하지 않은 요청을 특정 웹사이트에 보내도록 유도하는 공격 기법이다.
OAuth 로그인 과정에서 CSRF 방지 검증이 없으면, 공격자가 이를 악용해 세션을 탈취하거나 경우에 따라 Access Token 탈취로 이어질 수도 있다.
따라서 CSRF 공격을 방지하기 위해 로그인 요청이 오면 서버는 예측 불가능한 랜덤 문자열인 CSRF 토큰을 생성하여 저장하고, 사용자를 구글 로그인 페이지로 리다이렉트시킨다.
3-5. 인증 요청 및 인증 (User <-> Google)

사용자가 로그인 페이지에서 Google로 인증을 요청할 때 다음과 같은 정보들을 포함해야 한다.
| 변수 | 설명 |
| client_id | API 콘솔에서 얻은 클라이언트 ID |
| response_type | 기본적인 요청 시 code로 지정 |
| scope | 기본적인 요청 시 openid, email로 지정 |
| redirect_uri | Google 응답 수신용 서버의 HTTP 엔드포인트. Credentials 페이지에 설정된 승인된 리디렉션 URI와 정확히 일치 필요 |
| state | 위조 방지 고유 세션 토큰 및 컨텍스트 복구용 기타 정보(예: 시작 URL) 포함 |
| nonce | 앱에서 생성한 임의의 값으로 재생 공격 방지 |
| login_hint | 사용자의 이메일 주소 또는 Google ID와 동일한 sub 문자열 |
로그인 정보가 유효할 경우, 아래와 같은 정보가 Response 된다.
사용자는 이 정보를 그대로 Auth Server로 리다이렉션 시킨다.
| 변수 | 설명 |
| state | 위조 방지 토큰 및 사용자 상태 정보로, 보안 토큰과 반환 URL을 포함 |
| code | 액세스 토큰 및 ID 토큰으로 교환 가능한 승인 코드 |
| scope | 앱이 요청하는 권한으로, OpenID 인증, 이메일 주소 및 사용자 정보 액세스 요청 |
6-7 토큰 교환 요청
토큰을 교환하기에 앞서, CSRF 토큰을 검증한다.
만약 토큰 교환 요청이 정상적인 사용자가 아닌 공격자로부터 온 것이라면 토큰이 일치하지 않으므로 요청을 거부한다.
CSRF 토큰이 일치한다면, 앞에서 받은 승인 코드를 이용하여 Google에 토큰 교환 요청을 보낸다.
| 변수 | 설명 |
| code | 초기 요청에서 반환된 승인 코드 |
| client_id | OAuth 2.0 사용자 인증 정보에서 가져온 클라이언트 ID |
| client_secret | OAuth 2.0 사용자 인증 정보에서 가져온 클라이언트 보안 비밀 |
| redirect_uri | client_id에 지정된 승인된 리디렉션 URI |
| grant_type | OAuth 2.0 사양에 따라 authorization_code 값으로 지정 필요 |
그러면 토큰을 응답받을 수 있다.
구글의 경우, refresh_token은 처음 실행할 때만 가져올 수 있으므로 반드시 저장해두어야 한다.
| 변수 | 설명 |
| access_token | Google API로 전송 가능한 토큰 |
| expires_in | 액세스 토큰의 남은 수명 (초 단위) |
| id_token | Google이 디지털 서명한 사용자 ID 정보가 포함된 JWT |
| scope | access_token에 부여된 액세스 범위 (공백으로 구분) |
| token_type | 반환된 토큰의 유형, 항상 Bearer 값을 가짐 |
| refresh_token | (선택사항) access_type이 offline일 경우에만 반환되는 토큰 - 처음 실행할 때만 가져올 수 있으므로 영구적으로 저장해야함 |
이때 응답 받은 id_token의 페이로드를 파싱하여 사용자 정보를 확인하고 인증을 마무리한다.
| key | 설명 | 제공 |
| aud | ID 토큰의 대상. 앱의 OAuth 2.0 클라이언트 ID 중 하나여야 함. | 항상 |
| exp | ID 토큰 만료 시간 (Unix 에포크). | 항상 |
| iat | ID 토큰 발급 시간 (Unix 에포크). | 항상 |
| iss | 발급기관 식별자 (https://accounts.google.com 또는 accounts.google.com). | 항상 |
| sub | 재사용되지 않는 사용자의 고유 식별자. 앱 내 사용자 식별 키로 사용 권장. | 항상 |
| at_hash | 액세스 토큰 해시. access_token과 함께 발급 시 포함. | |
| azp | 승인된 발표자의 client_id. 토큰 요청자와 대상이 다를 경우에만 필요. | |
| 사용자의 이메일 주소 (email 범위 요청 시 제공, 고유 식별자로 사용 금지). |
||
| email_verified | 이메일 주소의 확인 여부 (true / false). | |
| family_name | 사용자의 성. | |
| given_name | 사용자의 이름. | |
| hd | 사용자의 Google Workspace 또는 Cloud 조직 도메인. | |
| locale | 사용자의 언어 (BCP 47 언어 태그). | |
| name | 사용자의 전체 이름 (profile 범위 요청 시 제공 가능). | |
| nonce | 앱이 제공한 nonce 값. 재전송 공격 방지용. | |
| picture | 사용자 프로필 사진 URL (profile 범위 요청 시 제공 가능). | |
| profile | 사용자 프로필 페이지 URL (profile 범위 요청 시 제공 가능). |
'Backend > Git-Check' 카테고리의 다른 글
| [Auth] 구글 로그인 구현(4) - Spring Security 핵심 인터페이스 (1) | 2025.08.13 |
|---|---|
| [Auth] 구글 로그인 구현(2) - Spring Security 아키텍처 학습 (3) | 2025.08.07 |
| [Auth] 구글 로그인 구현(1) - 기획 과정 (6) | 2025.08.04 |