OAuth2 로그인(또는 회원가입) 프로세스
TMTSSO(OAuth) 로그인을 통한 회원가입 프로세스 단계별 설명
1. 클라이언트: OAuth 로그인 시작
- 사용자 동작: 클라이언트 앱/웹에서 "Google로 로그인" 버튼 클릭.
- 클라이언트 처리:
- 서버에 OAuth 인증 요청을 위한 엔드포인트로 리다이렉트 (예:
/oauth2/authorization/google
). - 중요:
state
파라미터를 생성하여 CSRF 공격 방지 (랜덤 문자열).
- 서버에 OAuth 인증 요청을 위한 엔드포인트로 리다이렉트 (예:
2. 서버: OAuth 제공자(Google)로 리다이렉트
- 서버 처리:
- 클라이언트 요청을 Google OAuth 2.0 인증 페이지로 리다이렉트.
- 전달 파라미터:
client_id
: Google에 등록된 앱의 ID.redirect_uri
: 인증 후 리다이렉트될 서버의 콜백 URL (예:/login/oauth2/code/google
).response_type=code
: 인증 코드를 받겠다는 의미.scope
: 요청 권한 (예:email profile
).state
: 클라이언트에서 생성한 랜덤 문자열.
3. OAuth 제공자(Google): 사용자 인증 및 동의
- 사용자 동작:
- Google 계정으로 로그인.
- 앱이 요청한 권한 (이메일, 프로필 등)에 동의.
- Google 처리:
- 인증 성공 시, 서버의
redirect_uri
로 **인증 코드(code)**와 state를 전달.
- 인증 성공 시, 서버의
4. 서버: 인증 코드를 액세스 토큰으로 교환
- 서버 처리:
- 인증 코드(code) + client_secret을 사용해 Google의 토큰 엔드포인트에 POST 요청.
- 요청 예시:
POST https://oauth2.googleapis.com/token Body: code={인증_코드} &client_id={클라이언트_ID} &client_secret={클라이언트_시크릿} &redirect_uri={리다이렉트_URI} &grant_type=authorization_code
- 응답:
{ "access_token": "ya29.a0AfB...", "expires_in": 3599, "refresh_token": "1//0gABC..." }
5. 서버: 액세스 토큰으로 사용자 정보 조회
- 서버 처리:
- 액세스 토큰을 사용해 Google의 사용자 정보 API 호출.
- 요청 예시:
GET https://www.googleapis.com/oauth2/v2/userinfo Header: Authorization: Bearer {액세스_토큰}
- 응답:
{ "id": "1234567890", "email": "user@example.com", "name": "홍길동", "picture": "https://..." }
6. 서버: 회원가입 또는 로그인 처리
- 서버 로직:
- 응답받은
email
또는id
로 DB 조회. - 회원가입 (최초 로그인):
- OAuth 제공자에서 받은 정보로 사용자 생성.
- 필수 정보 누락 시 추가 폼 요청 (선택적).
- 로그인 (기존 사용자):
- 기존 계정에 OAuth 정보 연결 (소셜 로그인 정보 저장).
- 생성 예시:
User user = User.builder() .email(oauthUserInfo.getEmail()) .name(oauthUserInfo.getName()) .provider("google") .providerId(oauthUserInfo.getId()) .build(); userRepository.save(user);
- 응답받은
7. 클라이언트: 로그인 완료 및 세션/JWT 발급
- 서버 처리:
- 로그인 성공 시, 세션 ID 또는 JWT 토큰을 클라이언트에 전달.
- 응답 예시 (JWT):
{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "user": { "email": "user@example.com", "name": "홍길동" } }
- 클라이언트 처리:
- 토큰을 로컬 스토리지/쿠키에 저장하고 인증 상태 유지.
🔐 보안 고려 사항
- CSRF 방지:
state
파라미터 필수 사용. - PKCE (Proof Key for Code Exchange): 모바일/SPA에서는 PKCE 적용.
- 토큰 저장: 클라이언트에서
access_token
직접 저장하지 않음. - 정보 동의: 사용자에게 명시적인 권한 동의 요청.
🌐 예시 아키텍처 다이어그램
[Client] → (1) 로그인 버튼 클릭 → [Server]
[Server] → (2) Google OAuth로 리다이렉트 → [Google]
[Google] → (3) 사용자 인증 후 코드 전달 → [Server]
[Server] ↔ (4) 액세스 토큰 교환 ↔ [Google]
[Server] ↔ (5) 사용자 정보 조회 ↔ [Google]
[Server] → (6) 회원가입/로그인 처리 → [DB]
[Server] → (7) JWT 발급 → [Client]
[React]
→ (1) Google OAuth 리디렉션
→ [Google]
→ (2) React가 code 수신
→ (3) Spring Boot로 code 전송
→ (4) Spring Boot가 Google과 통신
→ (5) DB 처리 & JWT 생성
→ (6) React에 JWT 반환
🚨 주의사항
- 이메일 중복: 다른 OAuth 제공자에서 동일 이메일 사용 시 충돌 처리 필요.
- 토큰 만료:
refresh_token
으로 액세스 토큰 갱신 로직 추가. - 에러 핸들링: 사용자가 OAuth 동의를 취소한 경우 대응.