DOCS/ideas/auth_system_analysis.md
happybell80 1699e852b4 docs: OAuth 권한 분리 전략 추가
- Google OAuth 권한 과다 요청 문제점 추가
- 단계별 권한 요청 전략 제안 (기본 로그인 vs 스킬별 권한)
- 구현 방안 및 Phase 4 로드맵 추가
2025-08-16 11:09:04 +09:00

7.0 KiB

로빙 프로젝트 인증 시스템 전체 분석 및 통합 방안

현재 구조 분석

1. 데이터베이스 (PostgreSQL - auth_db)

Users 테이블 구조

- id: UUID (Primary Key)
- username: VARCHAR(50) UNIQUE  # happybell80 
- email: VARCHAR(255) UNIQUE NOT NULL
- name: VARCHAR(255)
- picture: VARCHAR(500)  # OAuth profile picture URL
- oauth_provider: VARCHAR(50)  # google, github 
- oauth_id: VARCHAR(255)  # Provider의 user ID
- is_active: BOOLEAN
- created_at, updated_at, last_login_at: TIMESTAMP

WorkspaceMembers 테이블

- user_id: UUID (FK to users.id)
- workspace_id: UUID
- robing_id: VARCHAR(100)  # rb8001, rb10508 
- role: ENUM (owner, member, guest)

2. Auth Server (51123 서버, 포트 9000)

JWT 토큰 구조

# 토큰 생성 시 페이로드 (gmail.py:183-188)
{
    "sub": username,        # "happybell80" - 주요 식별자
    "email": user_email,    # "goeun2dc@gmail.com"
    "name": user_name,      # "김고은"
    "username": username,   # "happybell80" (중복)
    "exp": expires_at
}

환경 변수

  • JWT_SECRET_KEY: ro-being-auth-jwt-secret-key-2024
  • JWT_ALGORITHM: HS256
  • JWT_ACCESS_TOKEN_EXPIRE_MINUTES: 30일

이메일-유저명 매핑 (하드코딩)

# gmail.py:150-154
email_to_username = {
    'goeun2dc@gmail.com': 'happybell80',
    'eagle0914@gmail.com': 'eagle0914',
}

3. Frontend (frontend-customer)

토큰 저장/조회

  • 저장 키: auth_token (auth-context.tsx:61)
  • 조회: localStorage.getItem('auth_token') (auth-context.tsx:29)
  • 서버 URL: https://auth.ro-being.com (하드코딩)

현재 문제점

// robing-api.ts - 토큰 전송 안함!
export async function sendMessage(text: string, userId: string = 'test_user') {
    // Authorization 헤더 없음
    // 모든 사용자가 'test_user'로 처리됨
}

4. Robing Gateway (포트 10100)

현재 처리 방식

# main.py:92-95
x_user_id: Optional[str] = Header(None)  # X-User-Id 헤더만 확인
# JWT 토큰 검증 없음!

5. Robing Services (51124 서버)

ChromaDB 컬렉션명 생성

# storage.py:84 (추정)
collection_name = f"{robing_id}_{user_id}_episodic"
# 현재: rb10508_test_default_episodic (모든 사용자 공유!)

주요 문제점

1. 인증 토큰 미전송 ⚠️

  • Frontend가 API 호출 시 JWT 토큰을 전송하지 않음
  • robing-api.ts에 Authorization 헤더 없음
  • 모든 사용자가 'test_user'로 처리

2. 백엔드 토큰 미검증 ⚠️

  • Robing Gateway가 JWT 토큰을 검증하지 않음
  • X-User-Id 헤더만 확인 (누구나 위조 가능)

3. 사용자 식별 실패 ⚠️

  • username이 제대로 전달되지 않아 'default'로 폴백
  • ChromaDB 컬렉션을 모든 사용자가 공유

4. 이메일-유저명 매핑 하드코딩 📝

  • 새 사용자 추가 시 코드 수정 필요
  • 확장성 없음

5. OAuth 권한 과다 요청 🔐

  • 회원가입/로그인 시 Gmail 읽기/쓰기 권한(gmail.modify)까지 요청
  • 복잡한 동의 과정으로 사용자 이탈 가능성 높음
  • 이메일 기능 미사용자에게도 과도한 권한 요청

6. 변수명 불일치 혼란 🔄

  • user_id vs username vs email 혼용
  • JWT의 'sub'가 username인지 user_id인지 불명확

결정 필요 사항

1. 주요 식별자 선택

  • username (추천): 'happybell80' - 인간 친화적, URL 안전
  • user_id (UUID): 'a1b2c3d4-...' - DB 표준, 중복 없음
  • email: 'goeun2dc@gmail.com' - OAuth 표준, 변경 가능성

2. JWT 페이로드 표준화

옵션 A (username 중심):
{
    "sub": "happybell80",      // 주 식별자
    "user_id": "uuid-here",     // DB ID
    "email": "goeun2dc@gmail.com",
    "name": "김고은"
}

옵션 B (UUID 중심):
{
    "sub": "uuid-here",         // 주 식별자
    "username": "happybell80",
    "email": "goeun2dc@gmail.com",
    "name": "김고은"
}

3. API 헤더 표준화

옵션 A (Bearer 토큰만):
Authorization: Bearer <jwt_token>

옵션 B (Bearer + X-User-Id):
Authorization: Bearer <jwt_token>
X-User-Id: happybell80  // 빠른 조회용

옵션 C (Bearer + X-Username):
Authorization: Bearer <jwt_token>
X-Username: happybell80  // 명확한 이름

4. ChromaDB 컬렉션 네이밍

옵션 A: {robing_id}_{username}_episodic
예: rb10508_happybell80_episodic

옵션 B: {robing_id}_{user_uuid}_episodic
예: rb10508_a1b2c3d4_episodic

옵션 C: {workspace_id}_{robing_id}_{username}_episodic
예: workspace1_rb10508_happybell80_episodic

5. 토큰 저장 키 통일

현재: 'auth_token'
대안: 'jwt_token', 'access_token', 'robing_token'

6. OAuth 권한 분리 전략

# 옵션 A: 단계별 권한 요청 (추천) ✅
기본 로그인: openid, userinfo.email, userinfo.profile
이메일 스킬: gmail.modify (별도 연결)
캘린더 스킬: calendar.events (별도 연결)

# 옵션 B: 일괄 권한 요청 (현재)
모든 권한을  번에 요청 (사용자 이탈 높음)

구현 방안:

  • /auth/gmail/login - 기본 프로필 권한만 (간단한 로그인)
  • /auth/gmail/connect-email - Gmail 권한 추가 (이메일 아이템 사용 시)
  • DB에 권한 레벨 저장: oauth_scopes 필드 추가
  • Frontend에서 권한 상태 표시 및 추가 연결 버튼 제공

즉시 수정 필요 (Critical)

1. Frontend (robing-api.ts)

// 토큰 전송 추가
const token = localStorage.getItem('auth_token');
headers['Authorization'] = `Bearer ${token}`;

2. Gateway (main.py)

# JWT 검증 추가
from app.core.auth import decode_access_token

authorization = Header(None)
if authorization:
    token = authorization.replace("Bearer ", "")
    payload = decode_access_token(token)
    username = payload.get("sub")  # 또는 username

3. Robing Service (storage.py)

# username 기반 컬렉션 생성
collection_name = f"{robing_id}_{username}_episodic"

단계별 구현 계획

Phase 1: 긴급 패치 (1일)

  1. Frontend에서 토큰 전송
  2. Gateway에서 토큰 검증
  3. username 기반 ChromaDB 분리

Phase 2: 표준화 (3일)

  1. 변수명 통일 (username vs user_id)
  2. JWT 페이로드 표준화
  3. API 문서 작성

Phase 3: 개선 (1주)

  1. 이메일-유저명 매핑 DB화
  2. 토큰 갱신 로직 구현
  3. 권한 체계 구현

Phase 4: OAuth 권한 분리 (1주)

  1. 기본 로그인용 엔드포인트 구현 (최소 권한)
  2. 스킬별 추가 권한 연결 엔드포인트 구현
  3. DB에 사용자별 권한 상태 저장
  4. Frontend에 권한 관리 UI 추가

참고 사항

  • JWT Secret: 모든 서비스가 같은 키 공유 필요
  • CORS 설정: frontend URL 추가 필요
  • Redis: 토큰 캐싱 및 세션 관리 활용
  • 로그: 모든 인증 실패 상세 로깅

문서 작성자

  • 작성일: 2025-08-16
  • 작성자: 51123 서버 관리 Claude
  • 목적: 인증 시스템 통합을 위한 현황 분석