작업계획서대로 진행
This commit is contained in:
557
claude_temp/05_Synology_SSO_연동_작업계획서.md
Normal file
557
claude_temp/05_Synology_SSO_연동_작업계획서.md
Normal file
@@ -0,0 +1,557 @@
|
||||
# Synology SSO 연동 작업계획서
|
||||
|
||||
> 작성일: 2026-01-10
|
||||
> 예상 기간: 2~3일
|
||||
> 우선순위: 5
|
||||
> 선행 작업: 4번 (Gmail OAuth 로그인)
|
||||
|
||||
---
|
||||
|
||||
## 1. 기능 개요
|
||||
|
||||
### 1.1 핵심 컨셉
|
||||
- 사내 Synology NAS의 SSO Server를 통한 로그인
|
||||
- **4번(Gmail OAuth)과 동일한 구조**로 구현
|
||||
- Google OAuth와 병행 사용 가능 (사용자 선택)
|
||||
- Synology 계정 이메일로 기존 사용자 매칭
|
||||
|
||||
### 1.2 로그인 페이지
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ 📊 주간보고 시스템 │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────┐ │
|
||||
│ │ [G] Google로 로그인 │ │
|
||||
│ └─────────────────────────────────────┘ │
|
||||
│ ┌─────────────────────────────────────┐ │
|
||||
│ │ [S] Synology로 로그인 │ │ ← 이번 작업
|
||||
│ └─────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ─────────────── 또는 ─────────────── │
|
||||
│ │
|
||||
│ 이메일: [_________________________] │
|
||||
│ 비밀번호: [_________________________] │
|
||||
│ │
|
||||
│ [로그인] [비밀번호 찾기] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.3 Synology SSO 로그인 플로우
|
||||
|
||||
```
|
||||
[Synology로 로그인] 클릭
|
||||
↓
|
||||
Synology SSO Server OAuth 인증
|
||||
↓
|
||||
Synology 계정 이메일 획득
|
||||
↓
|
||||
wr_employee_info.email 매칭?
|
||||
├─ NO → "등록되지 않은 사용자입니다. 관리자에게 문의하세요."
|
||||
└─ YES ↓
|
||||
비밀번호 설정됨?
|
||||
├─ YES → 메인 페이지로 이동
|
||||
└─ NO → 비밀번호 설정 페이지
|
||||
"비상시 로그인을 위해 비밀번호를 설정해주세요"
|
||||
```
|
||||
|
||||
### 1.4 결정 사항
|
||||
|
||||
| # | 항목 | 결정 |
|
||||
|:-:|------|:----:|
|
||||
| 1 | 매칭 기준 | Synology 계정 이메일 ↔ wr_employee_info.email |
|
||||
| 2 | 매칭 안됨 | 로그인 거부, 관리자 문의 안내 |
|
||||
| 3 | 비밀번호 미설정 | 4번과 동일하게 설정 유도 |
|
||||
| 4 | Google/Synology 동시 연결 | 허용 (1인 1계정씩) |
|
||||
|
||||
---
|
||||
|
||||
## 2. Synology SSO Server 개요
|
||||
|
||||
### 2.1 SSO Server란?
|
||||
- Synology NAS에서 제공하는 OAuth 2.0 기반 인증 서버
|
||||
- DSM (DiskStation Manager) 패키지로 설치
|
||||
- 사내 NAS 계정으로 외부 애플리케이션 로그인 가능
|
||||
|
||||
### 2.2 OAuth 2.0 흐름 (Google과 동일)
|
||||
|
||||
```
|
||||
1. 사용자 → [Synology로 로그인] 클릭
|
||||
2. 서버 → Synology SSO 인증 페이지로 리다이렉트
|
||||
3. 사용자 → Synology 계정 로그인, 권한 승인
|
||||
4. Synology → 콜백 URL로 리다이렉트 (code 포함)
|
||||
5. 서버 → code로 access_token 요청
|
||||
6. 서버 → access_token으로 사용자 정보 요청
|
||||
7. 서버 → email로 wr_employee_info 조회
|
||||
- 있으면: 세션 생성, 로그인 완료
|
||||
- 없으면: 에러 페이지 표시
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 데이터 모델
|
||||
|
||||
### 3.1 사용자 테이블 수정 (wr_employee_info)
|
||||
|
||||
```sql
|
||||
-- 4번 작업에서 추가한 컬럼에 Synology 관련 컬럼 추가
|
||||
ALTER TABLE wr_employee_info
|
||||
ADD COLUMN synology_id VARCHAR(100), -- Synology 고유 ID
|
||||
ADD COLUMN synology_username VARCHAR(100), -- Synology 사용자명
|
||||
ADD COLUMN synology_linked_at TIMESTAMP; -- Synology 연결 일시
|
||||
|
||||
-- 인덱스
|
||||
CREATE UNIQUE INDEX idx_employee_synology_id ON wr_employee_info(synology_id) WHERE synology_id IS NOT NULL;
|
||||
```
|
||||
|
||||
### 3.2 최종 사용자 테이블 구조 (4번 + 5번)
|
||||
|
||||
```sql
|
||||
-- wr_employee_info 인증 관련 컬럼 요약
|
||||
employee_id SERIAL PRIMARY KEY,
|
||||
...
|
||||
-- 비밀번호 (4번)
|
||||
password_hash VARCHAR(200),
|
||||
|
||||
-- Google OAuth (4번)
|
||||
google_id VARCHAR(100),
|
||||
google_email VARCHAR(100),
|
||||
google_linked_at TIMESTAMP,
|
||||
|
||||
-- Synology SSO (5번)
|
||||
synology_id VARCHAR(100),
|
||||
synology_username VARCHAR(100),
|
||||
synology_linked_at TIMESTAMP,
|
||||
|
||||
-- 공통
|
||||
last_login_at TIMESTAMP,
|
||||
last_login_ip VARCHAR(50),
|
||||
last_login_type VARCHAR(20), -- PASSWORD, GOOGLE, SYNOLOGY
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. API 설계
|
||||
|
||||
### 4.1 Synology SSO API
|
||||
|
||||
| Method | Endpoint | 설명 |
|
||||
|--------|----------|------|
|
||||
| GET | /api/auth/synology | Synology OAuth 시작 (리다이렉트) |
|
||||
| GET | /api/auth/synology/callback | Synology 콜백 처리 |
|
||||
|
||||
### 4.2 기존 API와 통합
|
||||
|
||||
| Method | Endpoint | 설명 | 비고 |
|
||||
|--------|----------|------|------|
|
||||
| GET | /api/auth/me | 현재 사용자 정보 | login_type 포함 |
|
||||
| POST | /api/auth/logout | 로그아웃 | 공통 |
|
||||
|
||||
---
|
||||
|
||||
## 5. Synology SSO Server 설정 가이드
|
||||
|
||||
### 5.1 SSO Server 패키지 설치
|
||||
|
||||
1. **DSM 접속**: `https://nas.company.com:5001` 관리자 계정으로 로그인
|
||||
2. **패키지 센터** 열기
|
||||
3. **"SSO Server"** 검색 → **설치**
|
||||
4. 설치 완료 후 **열기**
|
||||
|
||||
```
|
||||
패키지 센터 > 검색: "SSO Server" > [설치]
|
||||
```
|
||||
|
||||
### 5.2 SSO Server 기본 설정
|
||||
|
||||
1. **SSO Server** 앱 열기
|
||||
2. **설정** 탭 진입
|
||||
3. 기본 설정 확인:
|
||||
|
||||
| 설정 항목 | 권장 값 |
|
||||
|----------|---------|
|
||||
| SSO 서비스 활성화 | ✅ 체크 |
|
||||
| HTTPS 사용 | ✅ 체크 (필수) |
|
||||
| 포트 | 5001 (기본값) |
|
||||
|
||||
### 5.3 애플리케이션 등록
|
||||
|
||||
1. **SSO Server** > **애플리케이션** 탭
|
||||
2. **[추가]** 버튼 클릭
|
||||
3. 아래 정보 입력:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 애플리케이션 추가 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 애플리케이션 이름: [주간보고시스템________________] │
|
||||
│ │
|
||||
│ 리디렉션 URI: │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ https://weeklyreport.company.com/api/auth/synology/callback │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ※ 개발용 추가 (선택): │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ http://localhost:3000/api/auth/synology/callback │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ [저장] │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
4. **저장** 후 **Client ID / Client Secret** 확인 및 복사
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 애플리케이션 정보 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 애플리케이션 이름: 주간보고시스템 │
|
||||
│ │
|
||||
│ Client ID: abc123def456... [복사] │
|
||||
│ Client Secret: xyz789ghi012... [복사] │
|
||||
│ │
|
||||
│ ※ Client Secret은 다시 볼 수 없으니 반드시 복사해두세요! │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 5.4 사용자 권한 설정
|
||||
|
||||
1. **SSO Server** > **권한** 탭
|
||||
2. 로그인 허용할 사용자/그룹 선택
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 권한 설정 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 애플리케이션: 주간보고시스템 │
|
||||
│ │
|
||||
│ 허용된 사용자/그룹: │
|
||||
│ ☑ administrators │
|
||||
│ ☑ developers │
|
||||
│ ☑ users │
|
||||
│ ☐ guests │
|
||||
│ │
|
||||
│ ※ 또는 [모든 사용자 허용] 선택 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 5.5 HTTPS/SSL 인증서 확인
|
||||
|
||||
**제어판 > 보안 > 인증서**에서 유효한 SSL 인증서 확인
|
||||
|
||||
| 확인 항목 | 필수 여부 |
|
||||
|----------|:--------:|
|
||||
| 유효한 SSL 인증서 | ✅ 필수 |
|
||||
| 인증서 만료일 확인 | ✅ 확인 |
|
||||
| Let's Encrypt 또는 정식 인증서 | 권장 |
|
||||
|
||||
```
|
||||
※ 자체 서명 인증서(Self-signed)는 브라우저 경고 발생할 수 있음
|
||||
※ Let's Encrypt 무료 인증서 권장
|
||||
```
|
||||
|
||||
### 5.6 방화벽/포트 설정
|
||||
|
||||
외부에서 NAS 접근이 필요한 경우:
|
||||
|
||||
| 포트 | 용도 | 필요 여부 |
|
||||
|:----:|------|:--------:|
|
||||
| 5001 | DSM HTTPS | ✅ 필수 |
|
||||
| 443 | 역방향 프록시 사용 시 | 선택 |
|
||||
|
||||
```
|
||||
※ 공유기/방화벽에서 5001 포트 개방 필요
|
||||
※ 또는 역방향 프록시로 443 → 5001 연결
|
||||
```
|
||||
|
||||
### 5.7 설정 완료 체크리스트
|
||||
|
||||
| # | 항목 | 확인 |
|
||||
|:-:|------|:----:|
|
||||
| 1 | SSO Server 패키지 설치 | ☐ |
|
||||
| 2 | SSO 서비스 활성화 | ☐ |
|
||||
| 3 | 애플리케이션 등록 (주간보고시스템) | ☐ |
|
||||
| 4 | Client ID 복사 | ☐ |
|
||||
| 5 | Client Secret 복사 | ☐ |
|
||||
| 6 | 리디렉션 URI 설정 (운영) | ☐ |
|
||||
| 7 | 리디렉션 URI 설정 (개발) - 선택 | ☐ |
|
||||
| 8 | 사용자/그룹 권한 설정 | ☐ |
|
||||
| 9 | SSL 인증서 유효 확인 | ☐ |
|
||||
| 10 | 외부 접근 테스트 | ☐ |
|
||||
|
||||
### 5.8 설정 후 .env 파일 업데이트
|
||||
|
||||
```env
|
||||
# Synology SSO (5.3에서 복사한 값 입력)
|
||||
SYNOLOGY_SSO_URL=https://nas.company.com:5001
|
||||
SYNOLOGY_CLIENT_ID=여기에_Client_ID_붙여넣기
|
||||
SYNOLOGY_CLIENT_SECRET=여기에_Client_Secret_붙여넣기
|
||||
SYNOLOGY_REDIRECT_URI=https://weeklyreport.company.com/api/auth/synology/callback
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 구현 상세
|
||||
|
||||
### 6.1 Synology OAuth 엔드포인트
|
||||
|
||||
```
|
||||
# 인증 요청 (Authorization)
|
||||
GET https://{SYNOLOGY_SSO_URL}/webman/sso/SSOOauth.cgi
|
||||
?response_type=code
|
||||
&client_id={CLIENT_ID}
|
||||
&redirect_uri={REDIRECT_URI}
|
||||
&scope=user_id
|
||||
|
||||
# 토큰 요청 (Token)
|
||||
POST https://{SYNOLOGY_SSO_URL}/webman/sso/SSOAccessToken.cgi
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
grant_type=authorization_code
|
||||
&code={CODE}
|
||||
&client_id={CLIENT_ID}
|
||||
&client_secret={CLIENT_SECRET}
|
||||
&redirect_uri={REDIRECT_URI}
|
||||
|
||||
# 사용자 정보 요청 (UserInfo)
|
||||
GET https://{SYNOLOGY_SSO_URL}/webman/sso/SSOUserInfo.cgi
|
||||
?access_token={ACCESS_TOKEN}
|
||||
```
|
||||
|
||||
### 6.2 사용자 정보 응답 예시
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"email": "hyosung@company.com",
|
||||
"user_id": 1001,
|
||||
"user_name": "hyosung"
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
### 6.3 API 구현 코드 (예시)
|
||||
|
||||
```typescript
|
||||
// backend/api/auth/synology.get.ts
|
||||
export default defineEventHandler((event) => {
|
||||
const config = useRuntimeConfig();
|
||||
|
||||
const authUrl = new URL(`${config.synologySsoUrl}/webman/sso/SSOOauth.cgi`);
|
||||
authUrl.searchParams.set('response_type', 'code');
|
||||
authUrl.searchParams.set('client_id', config.synologyClientId);
|
||||
authUrl.searchParams.set('redirect_uri', config.synologyRedirectUri);
|
||||
authUrl.searchParams.set('scope', 'user_id');
|
||||
|
||||
return sendRedirect(event, authUrl.toString());
|
||||
});
|
||||
|
||||
// backend/api/auth/synology/callback.get.ts
|
||||
export default defineEventHandler(async (event) => {
|
||||
const query = getQuery(event);
|
||||
const code = query.code as string;
|
||||
|
||||
if (!code) {
|
||||
return sendRedirect(event, '/login?error=no_code');
|
||||
}
|
||||
|
||||
// 1. Access Token 요청
|
||||
const tokenResponse = await $fetch(`${config.synologySsoUrl}/webman/sso/SSOAccessToken.cgi`, {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams({
|
||||
grant_type: 'authorization_code',
|
||||
code,
|
||||
client_id: config.synologyClientId,
|
||||
client_secret: config.synologyClientSecret,
|
||||
redirect_uri: config.synologyRedirectUri,
|
||||
}),
|
||||
});
|
||||
|
||||
// 2. 사용자 정보 요청
|
||||
const userInfo = await $fetch(`${config.synologySsoUrl}/webman/sso/SSOUserInfo.cgi`, {
|
||||
params: { access_token: tokenResponse.access_token },
|
||||
});
|
||||
|
||||
// 3. 이메일로 사용자 매칭
|
||||
const employee = await findEmployeeByEmail(userInfo.data.email);
|
||||
|
||||
if (!employee) {
|
||||
return sendRedirect(event, '/login?error=not_registered');
|
||||
}
|
||||
|
||||
// 4. Synology 정보 업데이트
|
||||
await updateEmployeeSynologyInfo(employee.employee_id, {
|
||||
synology_id: userInfo.data.user_id,
|
||||
synology_username: userInfo.data.user_name,
|
||||
});
|
||||
|
||||
// 5. 세션 생성
|
||||
await createSession(event, employee, 'SYNOLOGY');
|
||||
|
||||
// 6. 비밀번호 설정 여부 확인
|
||||
if (!employee.password_hash) {
|
||||
return sendRedirect(event, '/auth/set-password');
|
||||
}
|
||||
|
||||
return sendRedirect(event, '/');
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 화면 설계
|
||||
|
||||
### 7.1 로그인 페이지 수정 (/login)
|
||||
|
||||
4번 작업에서 만든 로그인 페이지에 Synology 버튼 추가
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="login-buttons">
|
||||
<!-- Google 로그인 -->
|
||||
<a href="/api/auth/google" class="btn btn-outline-danger btn-lg w-100 mb-2">
|
||||
<i class="bi bi-google me-2"></i> Google로 로그인
|
||||
</a>
|
||||
|
||||
<!-- Synology 로그인 -->
|
||||
<a href="/api/auth/synology" class="btn btn-outline-primary btn-lg w-100 mb-3">
|
||||
<i class="bi bi-hdd-network me-2"></i> Synology로 로그인
|
||||
</a>
|
||||
|
||||
<hr class="my-3">
|
||||
|
||||
<!-- 이메일/비밀번호 로그인 -->
|
||||
...
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
### 7.2 마이페이지 수정 (/mypage)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 마이페이지 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 👤 기본 정보 │
|
||||
│ ─────────────────────────────────────────────────────────────── │
|
||||
│ 이름: 조효성 │
|
||||
│ 이메일: hyosung@company.com │
|
||||
│ ... │
|
||||
│ │
|
||||
│ 🔗 외부 계정 연결 │
|
||||
│ ─────────────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ Google: ✅ 연결됨 (hyosung@gmail.com) [연결 해제] │
|
||||
│ 연결일: 2026-01-10 │
|
||||
│ │
|
||||
│ Synology: ✅ 연결됨 (hyosung) [연결 해제] │
|
||||
│ 연결일: 2026-01-10 │
|
||||
│ │
|
||||
│ 🔒 비밀번호 │
|
||||
│ ─────────────────────────────────────────────────────────────── │
|
||||
│ ... │
|
||||
│ │
|
||||
│ 마지막 로그인: 2026-01-10 09:30 (Synology) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 작업 일정
|
||||
|
||||
### Phase 1: Synology SSO 설정 + API (1.5일)
|
||||
- [ ] 시작:
|
||||
- [ ] 완료:
|
||||
- [ ] 소요시간:
|
||||
|
||||
**작업 내용:**
|
||||
- [ ] Synology SSO Server 애플리케이션 등록
|
||||
- [ ] wr_employee_info 컬럼 추가 (synology_id 등)
|
||||
- [ ] 환경 변수 설정
|
||||
- [ ] Synology OAuth 시작/콜백 API
|
||||
- [ ] 사용자 매칭 로직
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: UI + 테스트 (1일)
|
||||
- [ ] 시작:
|
||||
- [ ] 완료:
|
||||
- [ ] 소요시간:
|
||||
|
||||
**작업 내용:**
|
||||
- [ ] 로그인 페이지에 Synology 버튼 추가
|
||||
- [ ] 마이페이지 외부 계정 연결 표시
|
||||
- [ ] 로그인 이력에 login_type 기록
|
||||
- [ ] 전체 플로우 테스트
|
||||
|
||||
---
|
||||
|
||||
## 작업 완료 결과
|
||||
|
||||
### Phase별 작업 시간
|
||||
|
||||
| Phase | 작업 내용 | 시작 | 완료 | 소요시간 |
|
||||
|:-----:|----------|:----:|:----:|:--------:|
|
||||
| 1 | Synology SSO 설정 + API | - | - | - |
|
||||
| 2 | UI + 테스트 | - | - | - |
|
||||
| | | | **총 소요시간** | **-** |
|
||||
|
||||
---
|
||||
|
||||
### 생성/수정된 파일
|
||||
|
||||
| 구분 | 파일 | 작업 |
|
||||
|------|------|:----:|
|
||||
| **DB** | wr_employee_info | 수정 (synology 컬럼 추가) |
|
||||
| **API** | backend/api/auth/synology.get.ts | 신규 |
|
||||
| **API** | backend/api/auth/synology/callback.get.ts | 신규 |
|
||||
| **Frontend** | frontend/pages/login.vue | 수정 |
|
||||
| **Frontend** | frontend/pages/mypage.vue | 수정 |
|
||||
| **Config** | .env | 수정 (Synology 설정 추가) |
|
||||
|
||||
---
|
||||
|
||||
## 9. 기술 스택
|
||||
|
||||
- **Backend**: Nitro (H3) + PostgreSQL
|
||||
- **Frontend**: Nuxt3 + Vue3 + Bootstrap 5
|
||||
- **OAuth**: Synology SSO Server (OAuth 2.0)
|
||||
- **세션**: 기존 방식 유지 (4번과 공유)
|
||||
|
||||
---
|
||||
|
||||
## 10. 주의사항
|
||||
|
||||
### 10.1 Synology SSO Server 요구사항
|
||||
- DSM 7.0 이상 권장
|
||||
- SSO Server 패키지 설치 필요
|
||||
- HTTPS 필수 (유효한 SSL 인증서)
|
||||
|
||||
### 10.2 네트워크 설정
|
||||
- 외부에서 Synology NAS 접근 가능해야 함
|
||||
- 방화벽에서 5001 포트 (HTTPS) 허용 필요
|
||||
- 또는 역방향 프록시 설정
|
||||
|
||||
### 10.3 개발 환경 제약
|
||||
- localhost 콜백이 안 될 수 있음
|
||||
- ngrok 또는 개발용 도메인 필요할 수 있음
|
||||
|
||||
---
|
||||
|
||||
## 11. 향후 확장 고려
|
||||
|
||||
1. **LDAP 연동**: Synology LDAP Server와 통합
|
||||
2. **그룹 기반 권한**: Synology 그룹 → 시스템 권한 매핑
|
||||
3. **자동 사용자 생성**: Synology 계정 → 자동 사용자 등록 (관리자 승인)
|
||||
Reference in New Issue
Block a user