# 인증 및 로그인 시스템 시퀀스 다이어그램 ## 작성일: 2025-08-20 ## 작성자: Claude (51123 서버 관리자) ## 상태: 초안 --- ## 목차 1. [Google OAuth 로그인](#1-google-oauth-로그인) 2. [Slack OAuth 로그인](#2-slack-oauth-로그인) 3. [JWT 토큰 검증](#3-jwt-토큰-검증) 4. [사용자 생성 및 UUID 관리](#4-사용자-생성-및-uuid-관리) --- ## 1. Google OAuth 로그인 ### 1.1 신규 사용자 로그인 플로우 ```mermaid sequenceDiagram participant User as 사용자 participant Front as 프론트엔드 participant Auth as auth-server(9000) participant Redis as Redis participant Google as Google OAuth participant DB as PostgreSQL User->>Front: 로그인 버튼 클릭 Front->>Front: window.location.href 변경 Front->>Auth: GET /auth/gmail/login Auth->>Auth: state 생성 (랜덤) Auth->>Auth: OAuth URL 생성 Note over Auth: scopes: openid, email, profile Auth-->>Front: 302 Redirect to Google Front->>Google: 브라우저 리다이렉트 User->>Google: Google 계정 로그인 User->>Google: 권한 승인 Google->>Auth: GET /auth/gmail/callback Note over Auth: code, state 파라미터 Auth->>Google: POST /oauth2/token Note over Auth: 인증 코드 → 액세스 토큰 Google-->>Auth: access_token, refresh_token Auth->>Google: GET /oauth2/v2/userinfo Google-->>Auth: email, name, picture Auth->>DB: SELECT * FROM users WHERE email=? DB-->>Auth: 사용자 없음 Auth->>Auth: UUID 생성 (uuid.uuid4()) Auth->>DB: INSERT INTO users Note over DB: id(UUID), email, name, picture Auth->>Auth: JWT 토큰 생성 Note over Auth: username, email, exp
(실제 user_id 포함 안함) Auth->>Redis: 임시 코드 저장 (60초 TTL) Note over Redis: code → JWT token Auth-->>Front: 302 Redirect Note over Auth: /#auth={code} Front->>Front: Fragment URL 파싱 Front->>Auth: POST /auth/verify Note over Front: {code: "임시코드"} Auth->>Redis: GET 및 DEL (atomic) Redis-->>Auth: JWT token Auth-->>Front: {token: "JWT", user: {...}} Front->>Front: localStorage 저장 Front->>Front: 상태 업데이트 & 새로고침 ``` ### 1.2 기존 사용자 로그인 플로우 ```mermaid sequenceDiagram participant User as 사용자 participant Front as 프론트엔드 participant Auth as auth-server(9000) participant Redis as Redis participant Google as Google OAuth participant DB as PostgreSQL User->>Front: 로그인 버튼 클릭 Front->>Auth: GET /auth/gmail/login Note over Auth,Google: OAuth 플로우 (1.1과 동일) Auth->>DB: SELECT * FROM users WHERE email=? DB-->>Auth: 사용자 정보 (기존 UUID) Auth->>DB: UPDATE users SET last_login=NOW() Auth->>DB: username 조회 Note over DB: SELECT username FROM users
WHERE id = ? DB-->>Auth: username Auth->>Auth: JWT 토큰 생성 Note over Auth: username, email, exp
(실제 user_id 포함 안함) Note over Auth,Front: 토큰 전달 (1.1과 동일) ``` --- ## 2. Slack OAuth 로그인 ### 2.1 Slack 워크스페이스 연동 ```mermaid sequenceDiagram participant User as 사용자 participant Slack as Slack App participant Auth as auth-server(9000) participant DB as PostgreSQL participant SlackAPI as Slack API User->>Slack: /robeing-login 명령 Slack->>Auth: POST /auth/slack/command Note over Auth: user_id, team_id, response_url Auth->>Auth: OAuth URL 생성 Auth-->>Slack: 로그인 링크 메시지 User->>Slack: 링크 클릭 Slack->>Auth: GET /auth/slack/login Auth->>Auth: state 생성 (user_id 포함) Auth-->>Slack: 302 Redirect to Slack OAuth User->>SlackAPI: Slack 권한 승인 SlackAPI->>Auth: GET /auth/slack/callback Auth->>SlackAPI: POST /oauth.v2.access SlackAPI-->>Auth: access_token, user info Note over Auth: Slack User ID: U0925SXQFDK Auth->>DB: SELECT user_id FROM slack_user_mapping WHERE slack_user_id=? Note over DB: Slack ID로 매핑 테이블 조회 alt 매핑 존재 DB-->>Auth: user_id (UUID) Auth->>DB: SELECT * FROM users WHERE id=? Note over DB: UUID로 사용자 정보 조회 DB-->>Auth: 사용자 정보 Auth->>DB: UPDATE users SET last_login=NOW() else 매핑 없음 (신규) Auth->>Auth: UUID 생성 (uuid.uuid4()) Auth->>Auth: username 생성 Note over Auth: slack_{slack_id[:8]} Auth->>DB: INSERT INTO users Note over DB: id: UUID
username: slack_U0925SXQ
email: slack.email Auth->>DB: INSERT INTO slack_user_mapping Note over DB: slack_user_id, user_id(UUID), workspace_id end Auth-->>Slack: 로그인 성공 메시지 ``` --- ## 3. JWT 토큰 검증 ### 3.1 API 요청 시 토큰 검증 ```mermaid sequenceDiagram participant Front as 프론트엔드 participant Gateway as Gateway(8100) participant Auth as auth-server(9000) participant Service as 로빙 서비스 Front->>Gateway: API 요청 Note over Gateway: Authorization: Bearer {JWT} Gateway->>Gateway: JWT 서명 검증 Gateway->>Gateway: 만료 시간 확인 alt 토큰 유효 Gateway->>Gateway: username 추출 Note over Gateway: JWT payload에서 username Gateway->>DB: username → UUID 변환 Note over DB: SELECT id FROM users
WHERE username = ? DB-->>Gateway: user_id (UUID) Gateway->>Service: 요청 전달 Note over Service: X-User-Id: {UUID}
X-Username: {username} Service-->>Gateway: 응답 Gateway-->>Front: 응답 else 토큰 만료/무효 Gateway-->>Front: 401 Unauthorized Front->>Front: 로그인 페이지로 end ``` --- ## 4. 사용자 생성 및 UUID 관리 ### 4.1 UUID 생성 규칙 ```mermaid flowchart TD A[사용자 로그인/가입] --> B{사용자 타입} B -->|Google OAuth| C[이메일로 DB 조회] C --> D{기존 사용자?} D -->|Yes| E[기존 UUID 사용] D -->|No| F["uuid.uuid4() 생성"] B -->|Slack OAuth| G[Slack ID 받음] G --> H[slack_user_mapping 테이블 조회] H --> I{매핑 존재?} I -->|Yes| E I -->|No| J["uuid.uuid4() 생성
매핑 테이블에 저장"] B -->|테스트 사용자| K[수동 UUID 할당] K --> L["하드코딩 UUID
aaaaaaaa-aaaa..."] F --> M[DB 저장] J --> M L --> M E --> N[username으로 JWT 생성] M --> N ``` ### 4.2 사용자 테이블 구조 ```sql -- users 테이블 CREATE TABLE users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email VARCHAR(255) UNIQUE NOT NULL, name VARCHAR(255), username VARCHAR(50) UNIQUE, -- happybell80, test_user 등 picture TEXT, oauth_provider VARCHAR(50), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, last_login TIMESTAMP ); -- 예시 데이터 -- 테스트 사용자 (하드코딩 UUID) INSERT INTO users VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'goeun2dc@gmail.com', '김종태', 'happybell80'), ('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '0914eagle@gmail.com', '전희재', 'eagle0914'), ('dddddddd-dddd-dddd-dddd-dddddddddddd', 'test@example.com', 'Test User', 'test_user'); -- 실제 사용자 (자동 생성 UUID) -- OAuth 로그인 시 uuid.uuid4()로 생성 ``` --- ## 5. 로그인 상태 관리 ### 5.1 프론트엔드 상태 관리 ```mermaid stateDiagram-v2 [*] --> 비로그인 비로그인 --> 로그인중: 로그인 버튼 클릭 로그인중 --> OAuth인증: OAuth 리다이렉트 OAuth인증 --> 코드교환: 콜백 수신 코드교환 --> 토큰저장: JWT 수신 토큰저장 --> 로그인완료: localStorage 저장 로그인완료 --> 비로그인: 로그아웃 로그인완료 --> 토큰갱신: 토큰 만료 토큰갱신 --> 로그인완료: 갱신 성공 토큰갱신 --> 비로그인: 갱신 실패 ``` --- ## 6. 보안 고려사항 ### 6.1 토큰 보안 1. **JWT 토큰** - HttpOnly 쿠키 사용 권장 (현재는 localStorage) - 짧은 만료 시간 (현재 24시간) - 서명 검증 필수 - username 기반 payload (user_id 포함 안함) 2. **임시 코드** - Redis 60초 TTL - 1회용 (atomic getdel) - Fragment URL로 서버 로그 방지 3. **OAuth state** - CSRF 방지 - 랜덤 생성 - 세션별 유니크 ### 6.2 사용자 식별 ```yaml 식별 체계: Primary Key: UUID (36자) - Google 사용자: uuid4() 랜덤 생성 - Slack 사용자: uuid4() 랜덤 생성 후 매핑 테이블 저장 Unique Keys: - email (OAuth provider에서 제공) - username (사용자 정의 또는 자동 생성) 관계: - users.id (UUID) ← gmail_tokens.user_id - users.id (UUID) ← slack_user_mapping.user_id - users.id (UUID) ← robeing_stats.user_id 매핑 방식: slack_user_mapping 테이블을 통한 Slack ID → UUID 직접 조회 ``` --- ## 문서 끝