diff --git a/.env b/.env index 44bfe31..e15064c 100644 --- a/.env +++ b/.env @@ -20,7 +20,7 @@ OPENAI_API_KEY=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 SYNOLOGY_SERVER_URL=https://sso.osolit.net SYNOLOGY_CLIENT_ID=dd477ab92304fa1cb1a2e1c6b96a6331 SYNOLOGY_CLIENT_SECRET= -SYNOLOGY_REDIRECT_URI=http://127.0.0.1/api/auth/synology/callback +SYNOLOGY_REDIRECT_URI=http://127.0.0.1/auth/synology/callback # EMAIL (SMTP) SMTP_HOST=smtp.gmail.com diff --git a/.env.prod b/.env.prod index 33aeca6..32f16d5 100644 --- a/.env.prod +++ b/.env.prod @@ -20,7 +20,7 @@ OPENAI_API_KEY=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 SYNOLOGY_SERVER_URL=https://sso.osolit.net SYNOLOGY_CLIENT_ID=afa90b7b4a9773af41f2c7b110f92d6e SYNOLOGY_CLIENT_SECRET= -SYNOLOGY_REDIRECT_URI=https://weeklyreport.turbosoft.kr/api/auth/synology/callback +SYNOLOGY_REDIRECT_URI=https://weeklyreport.turbosoft.kr/auth/synology/callback # EMAIL (SMTP) SMTP_HOST=smtp.gmail.com diff --git a/frontend/auth/synology/callback.vue b/frontend/auth/synology/callback.vue new file mode 100644 index 0000000..5c3c659 --- /dev/null +++ b/frontend/auth/synology/callback.vue @@ -0,0 +1,44 @@ + + + diff --git a/nuxt.config.ts b/nuxt.config.ts index 13e9c21..967a4fd 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -65,7 +65,7 @@ export default defineNuxtConfig({ synologyServerUrl: process.env.SYNOLOGY_SERVER_URL || 'https://sso.osolit.net', synologyClientId: process.env.SYNOLOGY_CLIENT_ID || 'afa90b7b4a9773af41f2c7b110f92d6e', synologyClientSecret: process.env.SYNOLOGY_CLIENT_SECRET || '', - synologyRedirectUri: process.env.SYNOLOGY_REDIRECT_URI || 'https://weeklyreport.turbosoft.kr/api/auth/synology/callback', + synologyRedirectUri: process.env.SYNOLOGY_REDIRECT_URI || 'https://weeklyreport.turbosoft.kr/auth/synology/callback', public: { appName: '주간업무보고' } diff --git a/server/api/auth/synology/index.get.ts b/server/api/auth/synology/index.get.ts index cbda5bc..aeb3d65 100644 --- a/server/api/auth/synology/index.get.ts +++ b/server/api/auth/synology/index.get.ts @@ -16,7 +16,7 @@ export default defineEventHandler(async (event) => { // Synology SSO Server OAuth 인증 URL const authUrl = new URL(`${config.synologyServerUrl}/webman/sso/SSOOauth.cgi`) - authUrl.searchParams.set('response_type', 'code') + authUrl.searchParams.set('response_type', 'token') authUrl.searchParams.set('app_id', config.synologyClientId) authUrl.searchParams.set('redirect_uri', config.synologyRedirectUri) authUrl.searchParams.set('scope', 'user_id') diff --git a/server/api/auth/synology/verify.post.ts b/server/api/auth/synology/verify.post.ts new file mode 100644 index 0000000..1513d9a --- /dev/null +++ b/server/api/auth/synology/verify.post.ts @@ -0,0 +1,90 @@ +/** + * Synology SSO Access Token 검증 및 로그인 처리 + * POST /api/auth/synology/verify + */ +import { sql } from '~/server/utils/db' + +export default defineEventHandler(async (event) => { + const body = await readBody(event) + const { accessToken } = body + + if (!accessToken) { + throw createError({ + statusCode: 400, + message: 'Access token이 없습니다.' + }) + } + + const config = useRuntimeConfig() + + try { + // Synology SSO Server에서 사용자 정보 조회 + const userInfoUrl = `${config.synologyServerUrl}/webman/sso/SSOAccessToken.cgi?action=exchange&access_token=${accessToken}&app_id=${config.synologyClientId}` + + const userInfoResponse = await $fetch(userInfoUrl) + + if (!userInfoResponse.success) { + throw createError({ + statusCode: 401, + message: userInfoResponse.error?.msg || 'Synology 토큰 검증에 실패했습니다.' + }) + } + + const synologyUsername = userInfoResponse.data?.user_name || userInfoResponse.data?.user_id + + if (!synologyUsername) { + throw createError({ + statusCode: 401, + message: 'Synology 사용자 정보를 가져올 수 없습니다.' + }) + } + + // DB에서 synology_username으로 사용자 조회 + const users = await sql` + SELECT employee_id, employee_name, employee_email, employee_role, company_id + FROM employees + WHERE synology_username = ${synologyUsername} + AND employee_status = 'active' + LIMIT 1 + ` + + if (users.length === 0) { + throw createError({ + statusCode: 404, + message: `Synology 계정 "${synologyUsername}"과 연결된 사용자를 찾을 수 없습니다. 관리자에게 문의하세요.` + }) + } + + const user = users[0] + + // 세션 생성 + const session = await useAuthSession(event) + await session.update({ + userId: user.employee_id, + userName: user.employee_name, + userEmail: user.employee_email, + userRole: user.employee_role, + companyId: user.company_id, + loginType: 'synology' + }) + + return { + success: true, + user: { + id: user.employee_id, + name: user.employee_name, + email: user.employee_email, + role: user.employee_role + } + } + } catch (error: any) { + if (error.statusCode) { + throw error + } + console.error('Synology SSO verify error:', error) + throw createError({ + statusCode: 500, + message: 'Synology 로그인 처리 중 오류가 발생했습니다.' + }) + } +})