DOCS/troubleshooting/250821_gmail_token_auto_refresh.md
happybell80 8c02b80359 Fix incorrect table names in documentation
- gmail_tokens → gmail_token (33 files)
- companies → company (17 files)
- conversation_logs → conversation_log (27 files)
- workspace_members → workspace_member (28 files)

All table names now match the actual PostgreSQL schema
2025-09-26 00:49:47 +09:00

227 lines
5.8 KiB
Markdown

# Gmail 토큰 자동 갱신 기능 구현
## 작성일: 2025-08-21
## 작성자: Claude (with heejae)
---
## 1. 개요
Gmail OAuth 토큰의 자동 갱신 기능을 auth-server에 구현하여, 만료된 access_token을 refresh_token을 사용해 자동으로 갱신할 수 있도록 함.
### 1.1 배경
- Gmail access_token은 1시간 후 만료
- refresh_token을 사용하여 새 access_token 발급 필요
- skill-email 서비스가 토큰 만료로 이메일 발송 실패하는 문제 해결 필요
---
## 2. 데이터베이스 구조
### 2.1 현재 DB 정보
```
Database: main_db (auth_db 아님 주의!)
Table: gmail_token
```
### 2.2 gmail_token 테이블 구조
```sql
CREATE TABLE gmail_token (
id SERIAL PRIMARY KEY,
user_id UUID UNIQUE NOT NULL,
robeing_id VARCHAR(50),
token_data JSONB NOT NULL, -- access_token, refresh_token, token_type
oauth_config JSONB, -- client_id, client_secret, token_uri
scopes JSONB, -- Gmail API 권한 목록
metadata JSONB, -- email, source_file 등
expiry TIMESTAMP, -- 토큰 만료 시간
is_equipped BOOLEAN DEFAULT false,
equipped_to VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
### 2.3 현재 저장된 토큰
| User ID | Email | 상태 |
|---------|-------|------|
| b6ea2ee0-a15a-5cf4-93a9-a9ca20d4c4a0 | 0914eagle@gmail.com | ❌ refresh_token 무효 |
| dddddddd-dddd-dddd-dddd-dddddddddddd | test@gmail.com | ✅ 정상 작동 |
---
## 3. auth-server 자동 갱신 API
### 3.1 구현 파일
- `/home/heejae/auth-server/app/api/gmail_refresh.py`
### 3.2 엔드포인트
#### 3.2.1 토큰 상태 확인
```
GET /api/gmail/check/{user_id}
```
**응답 예시:**
```json
{
"status": "found",
"user_id": "dddddddd-dddd-dddd-dddd-dddddddddddd",
"email": "test@gmail.com",
"has_token": true,
"has_access_token": true,
"has_refresh_token": true,
"has_oauth_config": true,
"is_expired": false,
"remaining_seconds": 34620,
"needs_refresh": false
}
```
#### 3.2.2 토큰 자동 갱신
```
POST /api/gmail/refresh/{user_id}
```
**응답 예시 (유효한 토큰):**
```json
{
"status": "valid",
"user_id": "dddddddd-dddd-dddd-dddd-dddddddddddd",
"email": "test@gmail.com",
"expires_in": 34550,
"access_token": "ya29.a0AS3H6Nxc8Z61FzHnEYmJ9TckEa0Yj8zd9Y6..."
}
```
**응답 예시 (갱신된 토큰):**
```json
{
"status": "refreshed",
"user_id": "dddddddd-dddd-dddd-dddd-dddddddddddd",
"email": "test@gmail.com",
"expires_in": 3600,
"access_token": "ya29.a0AS3H6NxNEW_TOKEN_HERE..."
}
```
### 3.3 갱신 로직
1. 토큰 만료 확인 (5분 이상 남았으면 갱신 안함)
2. refresh_token으로 Google OAuth API 호출
3. 새 access_token 받아서 DB 업데이트
4. 만료 시간(expiry) 업데이트
---
## 4. 문제 해결 과정
### 4.1 데이터베이스 문제
- **문제**: auth_db가 존재하지 않음
- **해결**: main_db 사용으로 변경
### 4.2 Docker 네트워크 문제
- **문제**: Docker 컨테이너에서 localhost 접근 불가
- **해결**: host.docker.internal 사용
### 4.3 refresh_token 무효 문제
- **원인**:
- Google OAuth 앱이 테스트 모드
- 6개월 이상 미사용 시 자동 만료
- 사용자가 권한 취소
- **해결**: 재인증 필요
---
## 5. 테스트 방법
### 5.1 토큰 상태 확인
```bash
curl -X GET "http://localhost:9000/api/gmail/check/{user_id}"
```
### 5.2 토큰 갱신
```bash
curl -X POST "http://localhost:9000/api/gmail/refresh/{user_id}"
```
### 5.3 로컬 테스트 스크립트
```bash
python3 /home/heejae/test_refresh.py
```
---
## 6. Gmail 재인증 방법
### 6.1 OAuth 재인증 URL
```
http://localhost:9000/auth/gmail/passport?user_id={user_id}
```
### 6.2 "액세스 차단됨" 에러 해결
1. Google Cloud Console 접속
2. APIs & Services → OAuth consent screen
3. Test users에 이메일 추가
4. 또는 기존 권한 삭제 후 재시도
- https://myaccount.google.com/permissions
### 6.3 주의사항
- gmail/login (로그인용) vs gmail/passport (API 권한용) 구분
- passport 엔드포인트 사용해야 gmail.send 권한 획득
---
## 7. 환경 설정
### 7.1 auth-server 환경변수 (.env)
```
DATABASE_URL=postgresql://robeings:robeings@host.docker.internal:5432/main_db
GOOGLE_CLIENT_ID=1044056803209-0h8n5kcl22rvl740mdgpejp58v27mlro.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=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
```
### 7.2 Docker 실행
```bash
cd /home/heejae/auth-server
docker compose down && docker compose up -d --build
```
---
## 8. 다음 단계
### 8.1 완료된 작업
- [x] auth-server에 자동 갱신 API 구현
- [x] test@gmail.com 계정 테스트 완료
- [x] DB 연결 및 구조 확인
### 8.2 TODO
- [x] 0914eagle@gmail.com 토큰 갱신 완료 (2025-08-27 10:34 - 리프레시 토큰으로 자동 갱신)
- [x] skill-email 자체 갱신 구현 완료 (2025-08-27 - Google 라이브러리 직접 사용)
- [ ] gmail_passport.py를 현재 DB 구조(JSONB)에 맞게 수정
- [ ] 토큰 만료 알림 기능 추가 고려
---
## 9. 참고사항
### 9.1 refresh_token 수명
- **프로덕션 앱**: 6개월 미사용 시 만료
- **테스트 앱**: 7일 후 만료
- **해결**: 정기적 갱신 또는 프로덕션 모드 전환
### 9.2 민감한 스코프
- gmail.send, gmail.modify는 제한된 스코프
- Google 검증 필요할 수 있음
### 9.3 UUID 변경 이력
- 원래: heejae, test, unknown (VARCHAR)
- 현재: UUID 형식으로 변경
- heejae → b6ea2ee0-a15a-5cf4-93a9-a9ca20d4c4a0
---
## 10. 관련 문서
- `/home/heejae/DOCS/250818_gmail_token_database_setup.md`
- `/home/heejae/DOCS/robeing-monitor-integration.md`
- `/home/heejae/DOCS/250817_slack_user_mapping_troubleshooting.md`