OAuth2 로그인(또는 회원가입) 프로세스

TMT

SSO(OAuth) 로그인을 통한 회원가입 프로세스 단계별 설명


1. 클라이언트: OAuth 로그인 시작

  • 사용자 동작: 클라이언트 앱/웹에서 "Google로 로그인" 버튼 클릭.
  • 클라이언트 처리:
    • 서버에 OAuth 인증 요청을 위한 엔드포인트로 리다이렉트 (예: /oauth2/authorization/google).
    • 중요: state 파라미터를 생성하여 CSRF 공격 방지 (랜덤 문자열).

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): 사용자 인증 및 동의

  • 사용자 동작:
    1. Google 계정으로 로그인.
    2. 앱이 요청한 권한 (이메일, 프로필 등)에 동의.
  • 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. 서버: 회원가입 또는 로그인 처리

  • 서버 로직:
    1. 응답받은 email 또는 id로 DB 조회.
    2. 회원가입 (최초 로그인):
      • OAuth 제공자에서 받은 정보로 사용자 생성.
      • 필수 정보 누락 시 추가 폼 요청 (선택적).
    3. 로그인 (기존 사용자):
      • 기존 계정에 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": "홍길동"
        }
      }
  • 클라이언트 처리:
    • 토큰을 로컬 스토리지/쿠키에 저장하고 인증 상태 유지.

🔐 보안 고려 사항

  1. CSRF 방지: state 파라미터 필수 사용.
  2. PKCE (Proof Key for Code Exchange): 모바일/SPA에서는 PKCE 적용.
  3. 토큰 저장: 클라이언트에서 access_token 직접 저장하지 않음.
  4. 정보 동의: 사용자에게 명시적인 권한 동의 요청.

🌐 예시 아키텍처 다이어그램

[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 동의를 취소한 경우 대응.
Edit this page