Skip to main content
Glama
security.md11.8 kB
# BaaS Authentication Security Guide ## Overview BaaS 인증 시스템의 보안 모범 사례와 쿠키 설정에 대한 종합 가이드입니다. **카테고리**: security **Keywords**: security, cookie, authentication, CSRF, XSS, httpOnly, sameSite, 보안, 쿠키, 인증 ## 기본 개념 AIApp BaaS는 JWT 토큰을 HttpOnly 쿠키로 관리하여 XSS 공격을 방지하고, 서브도메인 간 쿠키 공유를 통해 통합 인증을 제공합니다. ## Core Security Principles ### 1. HttpOnly 쿠키 사용 ```javascript // ✅ 올바른 설정 (자동으로 설정됨) // 쿠키는 JavaScript로 접근할 수 없도록 httpOnly 플래그 사용 document.cookie; // BaaS 인증 쿠키는 여기에 표시되지 않음 ``` ### 2. Secure 및 SameSite 설정 ```javascript // BaaS에서 자동으로 설정되는 쿠키 옵션: { httpOnly: true, secure: true, // HTTPS에서만 전송 sameSite: 'Lax', // CSRF 공격 방지 domain: '.aiapp.link', // 서브도메인 간 공유 path: '/' } ``` ## 쿠키 설정 ### 프로덕션 환경 ```javascript const cookieOptions = { httpOnly: true, // XSS 공격 방지 (JavaScript 접근 차단) secure: true, // HTTPS 환경에서만 전송 domain: '.aiapp.link', // 서브도메인 공유 sameSite: 'None', // 크로스 도메인 허용 (대소문자 주의) maxAge: 86400, // 24시간 (1일, 초 단위) path: '/' // 모든 경로에서 접근 가능 }; // Express.js 예시 res.cookie('access_token', jwtToken, cookieOptions); ``` ### 개발 환경 ```javascript const cookieOptions = { httpOnly: true, secure: false, // HTTP 허용 domain: 'localhost', // 로컬 도메인 sameSite: 'lax', // 로컬 환경에서는 lax maxAge: 86400, path: '/' }; // Express.js 예시 res.cookie('access_token', jwtToken, cookieOptions); ``` ## Domain Configuration ### .aiapp.link 도메인 설정 BaaS는 `.aiapp.link` 도메인을 사용하여 서브도메인 간 인증 상태를 공유합니다. ```javascript // 지원되는 도메인 패턴 const supportedDomains = [ 'https://your-app.aiapp.link', 'https://api.aiapp.link', 'https://admin.aiapp.link' ]; // 쿠키 도메인 설정 // Domain: .aiapp.link (자동 설정됨) ``` ### 서브도메인 공유 시나리오 #### 도메인 구조 ``` aiapp.link (메인 도메인) ├── app.aiapp.link (사용자 앱) ├── admin.aiapp.link (관리자 페이지) ├── api.aiapp.link (API 서버) └── dashboard.aiapp.link (대시보드) ``` #### 쿠키 공유 설정 ```javascript // API 서버 (api.aiapp.link)에서 쿠키 설정 res.cookie('access_token', token, { domain: '.aiapp.link', // 점(.)으로 시작하여 서브도메인 공유 // ... 기타 옵션 }); // 모든 서브도메인에서 접근 가능: // - app.aiapp.link // - admin.aiapp.link // - dashboard.aiapp.link ``` ### CORS 및 크로스 도메인 요청 ```javascript // React/JS에서 credentials 포함 설정 const authRequest = async (url, options = {}) => { return fetch(url, { ...options, credentials: 'include', // 쿠키 자동 포함 headers: { 'Content-Type': 'application/json', ...options.headers } }); }; ``` ## XSS 방지 ### 1. Content Security Policy (CSP) ```html <!-- 권장 CSP 헤더 설정 --> <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';"> ``` ### 2. 사용자 입력 검증 ```javascript // ✅ 사용자 입력 필터링 const sanitizeInput = (input) => { return input .replace(/</g, '&lt;') .replace(/>/g, '&gt;') .replace(/"/g, '&quot;') .replace(/'/g, '&#x27;'); }; // ✅ 이메일 검증 const validateEmail = (email) => { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); }; ``` ## CSRF 방지 ### 1. SameSite 쿠키 활용 ```javascript // BaaS는 SameSite=Lax 설정으로 CSRF 공격 방지 // 크로스 사이트 요청에서 쿠키가 자동으로 제한됨 ``` ### 2. Origin 검증 ```javascript // 서버에서 Origin 헤더 검증 (BaaS에서 자동 처리) const allowedOrigins = [ 'https://your-app.aiapp.link', 'https://localhost:3000' // 개발 환경 ]; ``` ## Token Management ### 1. 자동 토큰 갱신 ```javascript // BaaS는 자동으로 토큰을 갱신하고 쿠키를 업데이트 // 클라이언트에서 별도의 토큰 관리 불필요 // React에서 토큰 상태 확인 const { user, isAuthenticated } = useAuth(); // 토큰 만료 시 자동 처리 if (!isAuthenticated) { // 자동으로 로그인 페이지로 리다이렉트 } ``` ### 2. 세션 만료 처리 ```javascript // 세션 만료 시 자동 정리 const handleSessionExpiry = () => { // BaaS가 자동으로 처리: // 1. 만료된 쿠키 삭제 // 2. 클라이언트 상태 초기화 // 3. 로그인 페이지로 리다이렉트 }; ``` ## Production Security Checklist ### ✅ 필수 보안 설정 - [ ] HTTPS 사용 (필수) - [ ] `.aiapp.link` 도메인 설정 - [ ] CSP 헤더 구성 - [ ] 입력 검증 구현 - [ ] 에러 메시지에서 민감한 정보 제거 ### ✅ 권장 보안 설정 - [ ] Rate limiting 구현 - [ ] 로그인 시도 제한 - [ ] 보안 헤더 추가 (HSTS, X-Frame-Options 등) - [ ] 정기적인 보안 감사 ### ⚠️ 주의사항 ```javascript // ❌ 피해야 할 패턴 localStorage.setItem('token', token); // 로컬 스토리지에 토큰 저장 금지 sessionStorage.setItem('user', JSON.stringify(user)); // 세션 스토리지 사용 금지 // ✅ BaaS 권장 패턴 // 모든 인증 정보는 httpOnly 쿠키로 자동 관리됨 // 클라이언트에서는 useAuth() 훅이나 AuthManager 사용 ``` ## 보안 모니터링 ### 로그인 이상 활동 감지 ```javascript // BaaS는 다음 이상 활동을 자동 감지: // 1. 비정상적인 로그인 시도 패턴 // 2. 다중 디바이스에서의 동시 접근 // 3. 지리적으로 이상한 위치에서의 접근 // 클라이언트에서 보안 상태 확인 const { securityStatus } = useAuth(); if (securityStatus?.requiresVerification) { // 추가 인증 필요 시 처리 } ``` ### 세션 무효화 ```javascript // 의심스러운 활동 감지 시 모든 세션 무효화 const invalidateAllSessions = async () => { try { await authManager.logoutFromAllDevices(); console.log('모든 세션이 무효화되었습니다.'); } catch (error) { console.error('세션 무효화 실패:', error); } }; ``` ## 환경별 서버 구현 ### Next.js API 라우트 ```typescript // pages/api/auth/account/login.ts 또는 app/api/auth/account/login/route.ts import { NextApiRequest, NextApiResponse } from 'next'; import { cookies } from 'next/headers'; export async function POST(request: Request) { try { const { user_id, user_pw } = await request.json(); // 인증 로직... const token = await authenticateUser(user_id, user_pw); const isProduction = process.env.NODE_ENV === 'production'; const response = new Response(JSON.stringify({ result: 'SUCCESS', message: '로그인 완료', data: { access_token: token, token_type: 'bearer' } }), { status: 200, headers: { 'Content-Type': 'application/json', 'Set-Cookie': [ `access_token=${token}; HttpOnly; ${isProduction ? 'Secure;' : ''} Domain=${isProduction ? '.aiapp.link' : 'localhost'}; SameSite=${isProduction ? 'None' : 'Lax'}; Max-Age=86400; Path=/` ].join(' ') } }); return response; } catch (error) { return new Response(JSON.stringify({ result: 'FAIL', errorCode: 'INVALID_USER', message: '로그인 실패' }), { status: 401 }); } } ``` ## 클라이언트 설정 ### JavaScript/Fetch ```javascript // 쿠키 포함 요청 const response = await fetch('https://api.aiapp.link/account/login', { method: 'POST', headers: { 'Content-Type': 'application/json', }, credentials: 'include', // 쿠키 포함 body: JSON.stringify({ user_id: 'johndoe', user_pw: 'password123' }) }); ``` ### Axios 설정 ```javascript import axios from 'axios'; // 전역 설정 axios.defaults.withCredentials = true; axios.defaults.baseURL = 'https://api.aiapp.link'; // 또는 개별 요청 const response = await axios.post('/account/login', { user_id: 'johndoe', user_pw: 'password123' }, { withCredentials: true }); ``` ### React Native React Native에서는 쿠키가 자동으로 관리되지 않으므로 별도 라이브러리 사용: ```javascript import CookieManager from '@react-native-cookies/cookies'; // 쿠키 설정 await CookieManager.set('https://api.aiapp.link', { name: 'access_token', value: token, domain: '.aiapp.link', path: '/', version: '1', expires: new Date(Date.now() + 86400000).toISOString() }); // 쿠키 조회 const cookies = await CookieManager.get('https://api.aiapp.link'); const accessToken = cookies.access_token; ``` ## 보안 고려사항 ### HTTPS 필수 ```javascript // 프로덕션에서는 반드시 secure: true const cookieOptions = { secure: process.env.NODE_ENV === 'production', // SameSite=None 사용 시 Secure 필수 sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax' }; ``` ### SameSite 정책 - **None**: 크로스 도메인 요청에서 쿠키 전송 (Secure 필수) - **Lax**: GET 요청에서만 크로스 도메인 쿠키 전송 - **Strict**: 같은 도메인에서만 쿠키 전송 ```javascript // 환경별 SameSite 설정 const sameSitePolicy = { development: 'lax', // 로컬 개발 staging: 'none', // 스테이징 환경 production: 'none' // 프로덕션 환경 }; ``` ### 쿠키 만료 관리 ```javascript // 짧은 만료 시간 + 리프레시 토큰 패턴 const shortLivedToken = { maxAge: 900000, // 15분 httpOnly: true }; const refreshToken = { maxAge: 604800000, // 7일 httpOnly: true, path: '/auth/refresh' // 제한된 경로 }; ``` ## 문제 해결 ### 쿠키가 설정되지 않는 경우 1. **HTTPS 확인**: 프로덕션에서 `secure: true` 사용 시 HTTPS 필수 2. **CORS 설정**: `credentials: true` 설정 확인 3. **도메인 매치**: 쿠키 도메인과 요청 도메인 일치 확인 4. **SameSite 정책**: 크로스 도메인 요청 시 적절한 정책 설정 ### 서브도메인에서 쿠키 접근 불가 ```javascript // 잘못된 설정 domain: 'aiapp.link' // 점 없음 - 정확한 도메인만 매치 // 올바른 설정 domain: '.aiapp.link' // 점 있음 - 서브도메인 포함 ``` ### 개발 환경 쿠키 문제 ```javascript // localhost에서는 도메인 설정하지 않음 const cookieOptions = { domain: process.env.NODE_ENV === 'production' ? '.aiapp.link' : undefined }; ``` ## 테스트 방법 ### 브라우저 개발자 도구 ```javascript // 콘솔에서 쿠키 확인 document.cookie; // 특정 쿠키 확인 document.cookie .split(';') .find(cookie => cookie.includes('access_token')); ``` ### cURL 테스트 ```bash # 로그인 요청 curl -c cookies.txt -X POST https://api.aiapp.link/account/login \ -H "Content-Type: application/json" \ -d '{"user_id": "test", "user_pw": "password"}' # 쿠키 파일 확인 cat cookies.txt # 쿠키로 인증 API 호출 curl -b cookies.txt https://api.aiapp.link/account/info ``` ## 참고 자료 - [OWASP Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html) - [MDN HTTP Cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) - [Web Security Guidelines](https://infosec.mozilla.org/guidelines/web_security)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mbaas-inc/BaaS-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server