22 KiB
22 KiB
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)
-- 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번)
-- 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 패키지 설치
- DSM 접속:
https://nas.company.com:5001관리자 계정으로 로그인 - 패키지 센터 열기
- "SSO Server" 검색 → 설치
- 설치 완료 후 열기
패키지 센터 > 검색: "SSO Server" > [설치]
5.2 SSO Server 기본 설정
- SSO Server 앱 열기
- 설정 탭 진입
- 기본 설정 확인:
| 설정 항목 | 권장 값 |
|---|---|
| SSO 서비스 활성화 | ✅ 체크 |
| HTTPS 사용 | ✅ 체크 (필수) |
| 포트 | 5001 (기본값) |
5.3 애플리케이션 등록
- SSO Server > 애플리케이션 탭
- [추가] 버튼 클릭
- 아래 정보 입력:
┌─────────────────────────────────────────────────────────────────┐
│ 애플리케이션 추가 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 애플리케이션 이름: [주간보고시스템________________] │
│ │
│ 리디렉션 URI: │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ https://weeklyreport.company.com/api/auth/synology/callback │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ※ 개발용 추가 (선택): │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ http://localhost:3000/api/auth/synology/callback │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ [저장] │
└─────────────────────────────────────────────────────────────────┘
- 저장 후 Client ID / Client Secret 확인 및 복사
┌─────────────────────────────────────────────────────────────────┐
│ 애플리케이션 정보 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 애플리케이션 이름: 주간보고시스템 │
│ │
│ Client ID: abc123def456... [복사] │
│ Client Secret: xyz789ghi012... [복사] │
│ │
│ ※ Client Secret은 다시 볼 수 없으니 반드시 복사해두세요! │
│ │
└─────────────────────────────────────────────────────────────────┘
5.4 사용자 권한 설정
- SSO Server > 권한 탭
- 로그인 허용할 사용자/그룹 선택
┌─────────────────────────────────────────────────────────────────┐
│ 권한 설정 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 애플리케이션: 주간보고시스템 │
│ │
│ 허용된 사용자/그룹: │
│ ☑ 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 파일 업데이트
# 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 사용자 정보 응답 예시
{
"data": {
"email": "hyosung@company.com",
"user_id": 1001,
"user_name": "hyosung"
},
"success": true
}
6.3 API 구현 코드 (예시)
// 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 버튼 추가
<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. 향후 확장 고려
- LDAP 연동: Synology LDAP Server와 통합
- 그룹 기반 권한: Synology 그룹 → 시스템 권한 매핑
- 자동 사용자 생성: Synology 계정 → 자동 사용자 등록 (관리자 승인)