From d3f44cee2bab4696dbdf54292d81c45092dc917d Mon Sep 17 00:00:00 2001 From: happybell80 Date: Wed, 17 Sep 2025 20:22:27 +0900 Subject: [PATCH] Update NAVER WORKS OAuth implementation documentation - Add NAVER WORKS OAuth to authentication system architecture - Update API integration guide with confirmed endpoints and decisions - Create troubleshooting guide for implementation --- 300_architecture/380_authentication_system.md | 18 +- ...²„μ›μŠ€_μΊ˜λ¦°λ”_API_연동_κ°€μ΄λ“œ.md | 81 ++++- .../250917_naverworks_oauth_implementation.md | 332 ++++++++++++++++++ 3 files changed, 425 insertions(+), 6 deletions(-) create mode 100644 troubleshooting/250917_naverworks_oauth_implementation.md diff --git a/300_architecture/380_authentication_system.md b/300_architecture/380_authentication_system.md index 3b898cc..6a120d6 100644 --- a/300_architecture/380_authentication_system.md +++ b/300_architecture/380_authentication_system.md @@ -32,6 +32,15 @@ - GET/POST 콜백 λͺ¨λ‘ 지원 - ν•˜μ΄λΈŒλ¦¬λ“œ μ‚¬μš©μž λ§€ν•‘ +#### NAVER WORKS OAuth +- **μ—”λ“œν¬μΈνŠΈ**: `/auth/naverworks/login` +- **콜백**: `/auth/naverworks/callback` +- **νŠΉμ§•**: + - OAuth 2.0 + OpenID Connect + - Service Account (JWT) 지원 + - Access Token 1μ‹œκ°„, Refresh Token Rotation + - **κ²°μ •ν•„μš”**: Redirect URL 도메인 (auth.ro-being.com vs auth.robeing.com) + ### 3. λ°μ΄ν„°λ² μ΄μŠ€ ꡬ쑰 #### users ν…Œμ΄λΈ” @@ -154,11 +163,18 @@ SLACK_CLIENT_ID= SLACK_CLIENT_SECRET= SLACK_REDIRECT_URI= -# Gmail OAuth +# Gmail OAuth GMAIL_CLIENT_ID= GMAIL_CLIENT_SECRET= GMAIL_REDIRECT_URI= +# NAVER WORKS OAuth +NAVERWORKS_CLIENT_ID= +NAVERWORKS_CLIENT_SECRET= +NAVERWORKS_REDIRECT_URI= +NAVERWORKS_SERVICE_ACCOUNT= +NAVERWORKS_PRIVATE_KEY_PATH= + # Redis REDIS_URL=redis://localhost:6379/0 diff --git a/ideas/250916_λ„€μ΄λ²„μ›μŠ€_μΊ˜λ¦°λ”_API_연동_κ°€μ΄λ“œ.md b/ideas/250916_λ„€μ΄λ²„μ›μŠ€_μΊ˜λ¦°λ”_API_연동_κ°€μ΄λ“œ.md index 80a5702..134b099 100644 --- a/ideas/250916_λ„€μ΄λ²„μ›μŠ€_μΊ˜λ¦°λ”_API_연동_κ°€μ΄λ“œ.md +++ b/ideas/250916_λ„€μ΄λ²„μ›μŠ€_μΊ˜λ¦°λ”_API_연동_κ°€μ΄λ“œ.md @@ -2,6 +2,19 @@ **[ν˜„μž¬ ν”„λ‘œμ νŠΈ μƒνƒœ]** λ„€μ΄λ²„μ›μŠ€ API 연동 λ―Έκ΅¬ν˜„ (OAuth2 토큰 관리 둜직 μ—†μŒ, κ΄€λ ¨ skill μ„œλΉ„μŠ€ 미쑴재, auth-server에 Works API 인증 λ―Ένƒ‘μž¬). +## κ΅¬ν˜„ ν˜„ν™© 및 ν•„μš” μž‘μ—… + +### ν˜„μž¬ μƒνƒœ +- **auth-server**: NAVER WORKS OAuth λ―Έκ΅¬ν˜„ (Gmail, Slack만 쑴재) +- **skill μ„œλΉ„μŠ€**: NAVER WORKS μ „μš© μŠ€ν‚¬ μ—†μŒ +- **nginx**: NAVER WORKS λΌμš°νŒ… μ„€μ • μ—†μŒ + +### ν™•μΈλœ NAVER WORKS OAuth 2.0 μ—”λ“œν¬μΈνŠΈ +- **Authorization**: `https://auth.worksmobile.com/oauth2/v2.0/authorize` +- **Token**: `https://auth.worksmobile.com/oauth2/v2.0/token` +- **Userinfo (OIDC)**: `https://www.worksapis.com/v1.0/oidc/userinfo` +- **API Base**: `https://www.worksapis.com/v1.0/` + --- ## 1. λ‘œλΉ™(RO-BEING) μ•± μ„€μ • ν˜„ν™© @@ -11,10 +24,10 @@ ### 1.1. 인증 정보 -- **Client ID**: `kFJu_ajl6tb8pBiPEEnS` -- **Client Secret**: `xIz5G0v4wn` +- **Client ID**: `[ν™˜κ²½λ³€μˆ˜ NAVERWORKS_CLIENT_ID μ°Έμ‘°]` +- **Client Secret**: `[ν™˜κ²½λ³€μˆ˜ NAVERWORKS_CLIENT_SECRET μ°Έμ‘°]` - > **⚠️ κ²½κ³ : 이 값은 외뢀에 λ…ΈμΆœλ˜μ–΄μ„œλŠ” μ•ˆ 되며, Git λ“± 버전 관리 μ‹œμŠ€ν…œμ— ν¬ν•¨ν•˜μ§€ λ§ˆμ‹­μ‹œμ˜€. Vault λ˜λŠ” μ•”ν˜Έν™”λœ ν™˜κ²½ λ³€μˆ˜λ₯Ό 톡해 μ•ˆμ „ν•˜κ²Œ 관리해야 ν•©λ‹ˆλ‹€.** -- **Service Account**: `86rye.serviceaccount@company-x.partners` +- **Service Account**: `[ν™˜κ²½λ³€μˆ˜ NAVERWORKS_SERVICE_ACCOUNT μ°Έμ‘°]` ### 1.2. 토큰 μ„€μ • @@ -102,11 +115,69 @@ - **JWT ν‚€ 관리 (JWKS)**: κ²Œμ΄νŠΈμ›¨μ΄λŠ” JWT μ„œλͺ…에 μ‚¬μš©ν•˜λŠ” κ³΅κ°œν‚€ λͺ©λ‘μ„ `/.well-known/jwks.json` μ—”λ“œν¬μΈνŠΈλ₯Ό 톡해 λ…ΈμΆœν•˜μ—¬, λ‹€λ₯Έ μ„œλΉ„μŠ€λ“€μ΄ 토큰을 μ•ˆμ „ν•˜κ²Œ κ²€μ¦ν•˜κ³  ν‚€ ꡐ체에 λŒ€μ‘ν•  수 μžˆλ„λ‘ ν•©λ‹ˆλ‹€. - **토큰 흐름**: λ‘œλΉ™/μŠ€ν‚¬ μ„œλ²„λŠ” μ™ΈλΆ€ APIλ₯Ό 직접 ν˜ΈμΆœν•˜λŠ” λŒ€μ‹ , κ²Œμ΄νŠΈμ›¨μ΄μ— API ν˜ΈμΆœμ„ μœ„μž„ν•˜κ³  ν•„μš”ν•œ 단기 토큰을 λ°›μ•„ μ‚¬μš©ν•©λ‹ˆλ‹€. -## 5. μ°Έκ³  자료 +## 5. κ΅¬ν˜„ ν•„μš” 사항 + +### 5.1 파일 생성/μˆ˜μ • λͺ©λ‘ + +#### 생성 ν•„μš” +- **`auth-server/app/providers/naverworks.py`**: OAuth 2.0 인증 ν”Œλ‘œμš° κ΅¬ν˜„ +- **`skill-naverworks/`**: NAVER WORKS API μ „μš© μŠ€ν‚¬ μ„œλΉ„μŠ€ (포트 8511) + +#### μˆ˜μ • ν•„μš” +- **`auth-server/app/main.py`**: naverworks λΌμš°ν„° 등둝 (`prefix="/auth/naverworks"`) +- **`auth-server/.env`**: NAVERWORKS_CLIENT_ID, SECRET, REDIRECT_URI μΆ”κ°€ +- **`nginx-deploy`**: `/auth/naverworks`, `/api/naverworks` λΌμš°νŒ… μ„€μ • + +### 5.2 κ΅¬ν˜„ ν”Œλ‘œμš° (Slack νŒ¨ν„΄ μ°Έμ‘°) + +#### OAuth 둜그인 ν”Œλ‘œμš° +```python +# auth-server/app/providers/naverworks.py κ΅¬ν˜„ ν•„μš” + +@router.get("/login/") +async def naverworks_login(): + # 1. State 생성 β†’ Redis μ €μž₯ (TTL 300s) + # 2. Redirect to https://auth.worksmobile.com/oauth2/v2.0/authorize + +@router.get("/callback") +@router.post("/callback") # form_post 지원 +async def naverworks_login_callback(): + # 1. State 검증 + # 2. Code β†’ Token κ΅ν™˜ (POST https://auth.worksmobile.com/oauth2/v2.0/token) + # 3. Userinfo 쑰회 (GET https://www.worksapis.com/v1.0/oidc/userinfo) + # 4. User DB λ§€ν•‘ (oauth_provider="naverworks") + # 5. JWT 생성 β†’ Redis temp code β†’ Frontend redirect +``` + +#### Service Account JWT 인증 +```python +async def get_service_account_token(): + # 1. Private Key λ‘œλ“œ (파일 μ‹œμŠ€ν…œ) + # 2. JWT Assertion 생성 + # 3. Token μš”μ²­ (grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer) + # 4. Access Token 캐싱 (Redis TTL 3600s) +``` + +### 5.3 κ²°μ •/확인 ν•„μš” 사항 + +#### 결정사항 (ν™•μ •) +- **Redirect URL 도메인**: `auth.ro-being.com` μ‚¬μš© +- **Private Key μ €μž₯ 경둜**: `auth-server/private_20250917185550.key` +- **NAVER WORKS 토큰 ν…Œμ΄λΈ”**: `naverworks_token` (team μŠ€ν‚€λ§ˆ μ•„λž˜, λ‹¨μˆ˜ν˜•) + +#### ν™•μΈν•„μš” +- **OIDC userinfo 응닡 ν˜•μ‹**: sub, userId λ“± μ •ν™•ν•œ ν•„λ“œλͺ… +- **Service Account JWT μ„œλͺ…**: μ•Œκ³ λ¦¬μ¦˜ (RS256 λ“±) +- **Rate Limit**: API 호좜 μ œν•œ 및 μΏΌν„° +- **Private Key ꡐ체 μ‹œ**: κΈ°μ‘΄ 토큰 μœ νš¨μ„± μœ μ§€ μ—¬λΆ€ + +## 6. μ°Έκ³  자료 - **λ„€μ΄λ²„μ›μŠ€ 개발자 μ„Όν„° (곡식 λ¬Έμ„œ):** [developers.worksmobile.com](https://developers.worksmobile.com) - [인증 κ°€μ΄λ“œ](https://developers.worksmobile.com/kr/docs/auth) - [μΊ˜λ¦°λ” API](https://developers.worksmobile.com/kr/document/10070?lang=ko) - [μ£Όμ†Œλ‘ API](https://developers.worksmobile.com/kr/docs/contact) - [메일 API](https://developers.worksmobile.com/kr/docs/mail) -- **넀이버 개발자 포럼:** API κ΄€λ ¨ μ‹€μ œ μ§ˆμ˜μ‘λ‹΅μ„ μ°Έκ³ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. +- **λ‚΄λΆ€ μ°Έμ‘° μ½”λ“œ:** + - Slack OAuth: `auth-server/app/providers/slack.py` + - Gmail OAuth: `auth-server/app/providers/gmail_passport.py` diff --git a/troubleshooting/250917_naverworks_oauth_implementation.md b/troubleshooting/250917_naverworks_oauth_implementation.md new file mode 100644 index 0000000..cda546f --- /dev/null +++ b/troubleshooting/250917_naverworks_oauth_implementation.md @@ -0,0 +1,332 @@ +# NAVER WORKS OAuth 2.0 κ΅¬ν˜„ κ°€μ΄λ“œ + +**μž‘μ„±μΌ**: 2025-09-17 +**μž‘μ„±μž**: happybell80 +**μƒνƒœ**: κ΅¬ν˜„ λŒ€κΈ° + +## 1. ν˜„μž¬ μƒνƒœ 뢄석 + +### 1.1 κΈ°μ‘΄ Slack OAuth κ΅¬ν˜„ 확인 +**파일 μœ„μΉ˜**: `auth-server/app/providers/slack.py` + +#### Slack OAuth μ—”λ“œν¬μΈνŠΈ ꡬ쑰 +```python +# OIDC μ‚¬μš©μž 둜그인 +GET /auth/slack/login/ β†’ slack_login() +GET|POST /auth/slack/login/callback β†’ slack_login_callback() + +# Bot μ„€μΉ˜ (Passport) +GET /auth/slack/passport/install β†’ slack_install() +GET /auth/slack/passport/callback β†’ slack_callback() +GET /auth/slack/passport/status/{workspace_id} β†’ slack_status() +DELETE /auth/slack/passport/uninstall/{workspace_id} β†’ slack_uninstall() +``` + +#### Slack OAuth URL +- **OIDC Authorize**: `https://slack.com/openid/connect/authorize` +- **OIDC Token**: `https://slack.com/api/openid.connect.token` +- **OIDC Userinfo**: `https://slack.com/api/openid.connect.userInfo` +- **Bot Authorize**: `https://slack.com/oauth/v2/authorize` +- **Bot Token**: `https://slack.com/api/oauth.v2.access` + +#### Slack κ΅¬ν˜„ νŒ¨ν„΄ +1. State 생성 β†’ Redis μ €μž₯ (TTL 300s) +2. OAuth λ¦¬λ‹€μ΄λ ‰νŠΈ +3. Callbackμ—μ„œ state 검증 +4. Code β†’ Token κ΅ν™˜ +5. Userinfo 쑰회 +6. DB User λ§€ν•‘ (oauth_provider="slack", oauth_id=sub) +7. JWT 생성 β†’ Redis temp code μ €μž₯ +8. Frontend둜 λ¦¬λ‹€μ΄λ ‰νŠΈ + +### 1.2 NAVER WORKS ν˜„μž¬ μ„€μ • +**λ¬Έμ„œ**: `DOCS/ideas/250916_λ„€μ΄λ²„μ›μŠ€_μΊ˜λ¦°λ”_API_연동_κ°€μ΄λ“œ.md` + +- **μ•± 이름**: Ro-being +- **μ†Œμ†**: company-x.partners (155032) +- **Redirect URL (μ½˜μ†” μ„€μ •)**: `https://auth.robeing.com/oauth/naverworks/callback` +- **ν™œμ„± Scopes**: openid, profile, email, calendar, contact, file, mail, task, user +- **Token μ„€μ •**: Access Token 1μ‹œκ°„, Refresh Token Rotation On + +## 2. NAVER WORKS OAuth 2.0 κ΅¬ν˜„ λͺ…μ„Έ + +### 2.1 곡식 OAuth μ—”λ“œν¬μΈνŠΈ +**ν™•μΈλœ LINE WORKS API 2.0 μ—”λ“œν¬μΈνŠΈ**: +- **Authorization**: `https://auth.worksmobile.com/oauth2/v2.0/authorize` +- **Token**: `https://auth.worksmobile.com/oauth2/v2.0/token` +- **Userinfo**: `https://www.worksapis.com/v1.0/oidc/userinfo` +- **API Base**: `https://www.worksapis.com/v1.0/` + +### 2.2 κ΅¬ν˜„ ν•„μš” 파일 + +#### μ‹ κ·œ 생성 +1. **`auth-server/app/providers/naverworks.py`** +```python +from fastapi import APIRouter, Request, HTTPException, Depends +from fastapi.responses import RedirectResponse +import httpx +import jwt +import json +import uuid +from datetime import datetime, timedelta +from app.core.auth import create_access_token +from app.models.user import User +from app.core.config import settings +from app.db.redis_client import redis_client + +router = APIRouter() + +NAVERWORKS_AUTH_URL = "https://auth.worksmobile.com/oauth2/v2.0/authorize" +NAVERWORKS_TOKEN_URL = "https://auth.worksmobile.com/oauth2/v2.0/token" +NAVERWORKS_USERINFO_URL = "https://www.worksapis.com/v1.0/oidc/userinfo" +NAVERWORKS_API_BASE = "https://www.worksapis.com/v1.0" + +@router.get("/login/") +async def naverworks_login(request: Request, redirect_uri: str = None): + """NAVER WORKS OAuth 둜그인 μ‹œμž‘""" + # κ΅¬ν˜„ λ‚΄μš©... + +@router.get("/callback") +@router.post("/callback") # form_post 지원 +async def naverworks_login_callback(request: Request): + """NAVER WORKS OAuth 콜백 처리""" + # κ΅¬ν˜„ λ‚΄μš©... + +# Service Account JWT 인증 헬퍼 +async def get_service_account_token(): + """μ„œλΉ„μŠ€ κ³„μ •μœΌλ‘œ Access Token λ°œκΈ‰""" + # JWT assertion 생성 + # Token endpoint 호좜 + # κ΅¬ν˜„ λ‚΄μš©... +``` + +#### κΈ°μ‘΄ 파일 μˆ˜μ • +2. **`auth-server/app/main.py`** +```python +# μΆ”κ°€ +from app.providers import naverworks + +# λΌμš°ν„° 등둝 +app.include_router( + naverworks.router, + prefix="/auth/naverworks", + tags=["auth-naverworks"] +) +``` + +3. **`auth-server/.env`** +```bash +# NAVER WORKS OAuth +NAVERWORKS_CLIENT_ID=[Client ID from console] +NAVERWORKS_CLIENT_SECRET=[Client Secret from console] +NAVERWORKS_REDIRECT_URI=https://auth.ro-being.com/auth/naverworks/callback +NAVERWORKS_SERVICE_ACCOUNT=[Service Account from console] +NAVERWORKS_PRIVATE_KEY_PATH=/secure/naverworks/private_key.json +``` + +### 2.3 λ°μ΄ν„°λ² μ΄μŠ€ μŠ€ν‚€λ§ˆ + +#### μ‹ κ·œ ν…Œμ΄λΈ” (선택적) +```sql +-- NAVER WORKS μ „μš© λ§€ν•‘ ν…Œμ΄λΈ” (ν•„μš”μ‹œ) +CREATE TABLE naverworks_user_mapping ( + naverworks_user_id VARCHAR(100) NOT NULL, + naverworks_org_id VARCHAR(100) NOT NULL, + user_id UUID NOT NULL REFERENCES users(id), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (naverworks_user_id, naverworks_org_id) +); + +-- NAVER WORKS 토큰 μ €μž₯ (Service Account용) +CREATE TABLE naverworks_tokens ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + org_id VARCHAR(100) NOT NULL, + access_token TEXT NOT NULL, + refresh_token TEXT, + expires_at TIMESTAMP NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +``` + +#### κΈ°μ‘΄ users ν…Œμ΄λΈ” ν™œμš© +- `oauth_provider`: "naverworks" +- `oauth_id`: NAVER WORKS userId λ˜λŠ” sub claim +- `email`: μ‚¬μš©μž 이메일 +- `name`: μ‚¬μš©μž 이름 + +### 2.4 κ΅¬ν˜„ ν”Œλ‘œμš° + +#### μ‚¬μš©μž 둜그인 (OAuth 2.0 + OIDC) +``` +1. GET /auth/naverworks/login/?redirect_uri={frontend_url} + - State 생성 (UUID) + - Redis μ €μž₯: oauth:state:{state} = {"redirect_uri", "created_at"} + - Redirect to: https://auth.worksmobile.com/oauth2/v2.0/authorize + ?client_id={NAVERWORKS_CLIENT_ID} + &redirect_uri={NAVERWORKS_REDIRECT_URI} + &scope=openid+profile+email + &response_type=code + &state={state} + +2. GET|POST /auth/naverworks/callback?code={code}&state={state} + - State 검증 (Redis 쑰회 및 μ‚­μ œ) + - Token κ΅ν™˜: + POST https://auth.worksmobile.com/oauth2/v2.0/token + { + "code": code, + "client_id": NAVERWORKS_CLIENT_ID, + "client_secret": NAVERWORKS_CLIENT_SECRET, + "redirect_uri": NAVERWORKS_REDIRECT_URI, + "grant_type": "authorization_code" + } + - Userinfo 쑰회: + GET https://www.worksapis.com/v1.0/oidc/userinfo + Headers: Authorization: Bearer {access_token} + - User 쑰회/생성: + - oauth_provider="naverworks" + - oauth_id={sub λ˜λŠ” userId} + - JWT 생성 + - μž„μ‹œ μ½”λ“œ 생성 β†’ Redis: auth:temp:{temp_code} + - Redirect: {redirect_uri}?code={temp_code} + +3. Frontend: POST /auth/verify + - μž„μ‹œ μ½”λ“œλ‘œ JWT 토큰 수령 +``` + +#### Service Account 인증 (JWT) +``` +1. Private Key λ‘œλ“œ (파일 μ‹œμŠ€ν…œ) +2. JWT Assertion 생성: + - iss: NAVERWORKS_CLIENT_ID + - sub: NAVERWORKS_SERVICE_ACCOUNT + - iat: ν˜„μž¬ μ‹œκ°„ + - exp: ν˜„μž¬ μ‹œκ°„ + 1μ‹œκ°„ +3. Token μš”μ²­: + POST https://auth.worksmobile.com/oauth2/v2.0/token + { + "assertion": jwt_assertion, + "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", + "client_id": NAVERWORKS_CLIENT_ID, + "client_secret": NAVERWORKS_CLIENT_SECRET, + "scope": "calendar contact mail user" + } +4. Access Token 캐싱 (Redis, TTL 3600s) +``` + +### 2.5 API μ‚¬μš© μ˜ˆμ‹œ + +#### μΊ˜λ¦°λ” 일정 생성 +```python +async def create_calendar_event(user_id: str, event_data: dict): + token = await get_service_account_token() + + async with httpx.AsyncClient() as client: + response = await client.post( + f"{NAVERWORKS_API_BASE}/users/{user_id}/calendar/events", + headers={"Authorization": f"Bearer {token}"}, + json=event_data + ) + return response.json() +``` + +## 3. κ΅¬ν˜„ 체크리슀트 + +### ν•„μˆ˜ μž‘μ—… +- [ ] `auth-server/app/providers/naverworks.py` 생성 +- [ ] `auth-server/app/main.py`에 λΌμš°ν„° 등둝 +- [ ] `.env` νŒŒμΌμ— ν™˜κ²½λ³€μˆ˜ μΆ”κ°€ +- [ ] Redis key νŒ¨ν„΄ κ΅¬ν˜„ (oauth:state:*, auth:temp:*) +- [ ] User λͺ¨λΈ λ§€ν•‘ 둜직 +- [ ] JWT 토큰 생성 및 검증 + +### 선택 μž‘μ—… +- [ ] NAVER WORKS μ „μš© ν…Œμ΄λΈ” 생성 (ν•„μš”μ‹œ) +- [ ] Service Account JWT 인증 κ΅¬ν˜„ +- [ ] Refresh Token 처리 둜직 +- [ ] μ—λŸ¬ 핸듀링 및 μž¬μ‹œλ„ 둜직 + +### Frontend 연동 +- [ ] 둜그인 λ²„νŠΌ μΆ”κ°€ +- [ ] `/auth/naverworks/login` λ¦¬λ‹€μ΄λ ‰νŠΈ +- [ ] 콜백 처리 및 토큰 μ €μž₯ + +## 4. λ³΄μ•ˆ 고렀사항 + +### λΉ„λ°€ ν‚€ 관리 +- **κ²°μ •ν•„μš”**: Private Key μ €μž₯ μœ„μΉ˜ (파일 μ‹œμŠ€ν…œ vs Vault) +- Client Secret은 ν™˜κ²½λ³€μˆ˜λ‘œλ§Œ 관리 +- Private Key 파일 κΆŒν•œ 600 μ„€μ • ν•„μˆ˜ +- **ν™•μΈν•„μš”**: ν•œ λ²ˆμ— ν•˜λ‚˜μ˜ Private Key만 ν™œμ„±ν™” (μ½˜μ†” μ œμ•½) + +### 도메인 일치 +- **κ²°μ •ν•„μš”**: Redirect URL 도메인 톡일 + - μ½˜μ†” μ„€μ •: `auth.robeing.com` + - ν˜„μž¬ Slack: `auth.ro-being.com` + - ν•˜λ‚˜λ‘œ 톡일 ν•„μš” + +### 토큰 λ³΄μ•ˆ +- Access Token은 Redis에 μž„μ‹œ μ €μž₯ (TTL μ„€μ •) +- Refresh Token은 μ•”ν˜Έν™”ν•˜μ—¬ DB μ €μž₯ +- Service Account 토큰은 κ²Œμ΄νŠΈμ›¨μ΄ μ„œλ²„μ—μ„œλ§Œ μ‚¬μš© + +## 5. ν…ŒμŠ€νŠΈ μ‹œλ‚˜λ¦¬μ˜€ + +### 둜그인 ν”Œλ‘œμš° ν…ŒμŠ€νŠΈ +1. `/auth/naverworks/login` 접속 +2. NAVER WORKS 둜그인 νŽ˜μ΄μ§€ 확인 +3. 인증 ν›„ 콜백 처리 확인 +4. JWT 토큰 λ°œκΈ‰ 확인 +5. Frontend λ¦¬λ‹€μ΄λ ‰νŠΈ 확인 + +### API 호좜 ν…ŒμŠ€νŠΈ +1. Service Account 토큰 λ°œκΈ‰ +2. μΊ˜λ¦°λ” API 호좜 ν…ŒμŠ€νŠΈ +3. μ‚¬μš©μž 정보 쑰회 ν…ŒμŠ€νŠΈ +4. μ—λŸ¬ 처리 확인 + +## 6. μ°Έκ³  자료 + +### λ‚΄λΆ€ λ¬Έμ„œ +- Slack OAuth κ΅¬ν˜„: `auth-server/app/providers/slack.py` +- Gmail OAuth κ΅¬ν˜„: `auth-server/app/providers/gmail_passport.py` +- NAVER WORKS μ„€μ •: `DOCS/ideas/250916_λ„€μ΄λ²„μ›μŠ€_μΊ˜λ¦°λ”_API_연동_κ°€μ΄λ“œ.md` + +### μ™ΈλΆ€ λ¬Έμ„œ +- [LINE WORKS Developers](https://developers.worksmobile.com) +- [OAuth 2.0 인증 κ°€μ΄λ“œ](https://developers.worksmobile.com/kr/docs/auth-oauth) +- [API Reference](https://developers.worksmobile.com/kr/reference/introduction) + +## 7. κ΅¬ν˜„ μš°μ„ μˆœμœ„ + +1. **Phase 1** (μ¦‰μ‹œ) + - ν™˜κ²½λ³€μˆ˜ μ„€μ • + - κΈ°λ³Έ OAuth 둜그인 ν”Œλ‘œμš° + - User λ§€ν•‘ 둜직 + +2. **Phase 2** (1μ£Ό λ‚΄) + - Service Account 인증 + - μΊ˜λ¦°λ” API 연동 + - μ—λŸ¬ 핸듀링 + +3. **Phase 3** (2μ£Ό λ‚΄) + - Refresh Token μžλ™ κ°±μ‹  + - 전체 API 톡합 + - λͺ¨λ‹ˆν„°λ§ 및 λ‘œκΉ… + +## 8. λ―Έκ²° 사항 + +### κ²°μ • ν•„μš” +- [ ] Redirect URL 도메인 (auth.ro-being.com vs auth.robeing.com) +- [ ] Private Key μ €μž₯ 방식 (파일 vs Vault) +- [ ] NAVER WORKS μ „μš© ν…Œμ΄λΈ” 생성 μ—¬λΆ€ + +### 확인 ν•„μš” +- [ ] NAVER WORKS OIDC userinfo endpoint μ •ν™•ν•œ 응닡 ν˜•μ‹ +- [ ] Service Account JWT μ„œλͺ… μ•Œκ³ λ¦¬μ¦˜ +- [ ] Rate Limit 및 μΏΌν„° μ œν•œ +- [ ] Private Key ꡐ체 μ‹œ κΈ°μ‘΄ 토큰 μœ νš¨μ„± + +--- +*μž‘μ„±: 2025-09-17 / happybell80* +*λ‹€μŒ μ—…λ°μ΄νŠΈ: κ΅¬ν˜„ μ™„λ£Œ ν›„* \ No newline at end of file