# ZELLYY Core SSO 구현 계획 ## 개요 이 문서는 ZELLYY Core의 Single Sign-On (SSO) 구현 방안과 소셜 로그인(구글, 애플) 통합에 대해 설명합니다. ## SSO 구현 전략 ### 지원하는 인증 방식 1. **이메일/비밀번호** - 기본 인증 방식 2. **구글 OAuth** - 구글 계정을 통한 로그인 3. **애플 로그인** - 애플 계정을 통한 로그인 (iOS 앱 필수) ### Supabase Auth 활용 ZELLYY Core는 Supabase Auth를 활용하여 SSO를 구현합니다. Supabase는 다음 기능을 제공합니다: - 소셜 로그인 통합 (Google, Apple, Github 등) - JWT 토큰 관리 - 사용자 세션 관리 - 보안 설정 (2FA, 비밀번호 정책 등) ## 소셜 로그인 구현 단계 ### 1. 제공자 등록 및 설정 #### 구글 OAuth 설정 1. Google Cloud Console에서 프로젝트 생성 2. OAuth 2.0 클라이언트 ID 생성 3. 승인된 리디렉션 URI 설정: ``` https://[PROJECT_ID].supabase.co/auth/v1/callback ``` 4. 클라이언트 ID와 비밀번호를 Supabase 설정에 등록 #### 애플 로그인 설정 1. Apple Developer 계정에서 App ID 등록 2. Sign in with Apple 서비스 활성화 3. 서비스 ID 생성 및 도메인 검증 4. 승인된 리디렉션 URI 설정 5. 키 생성 및 Supabase 설정에 등록 ### 2. 프론트엔드 구현 #### 로그인 버튼 ```jsx import { supabase } from './supabaseClient'; const SocialLoginButtons = () => { const handleGoogleLogin = async () => { await supabase.auth.signInWithOAuth({ provider: 'google', options: { redirectTo: 'https://app.zellyy.com/auth/callback' } }); }; const handleAppleLogin = async () => { await supabase.auth.signInWithOAuth({ provider: 'apple', options: { redirectTo: 'https://app.zellyy.com/auth/callback' } }); }; return (
); }; ``` #### OAuth 콜백 처리 ```jsx import { useEffect } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { supabase } from './supabaseClient'; const AuthCallback = () => { const location = useLocation(); const navigate = useNavigate(); useEffect(() => { // URL에서 인증 정보 추출 const handleAuthCallback = async () => { const { error } = await supabase.auth.getSession(); if (error) { console.error('인증 오류:', error); navigate('/login?error=auth_callback_error'); return; } // 성공적으로 인증됨 navigate('/dashboard'); }; handleAuthCallback(); }, [navigate]); return
로그인 처리 중...
; }; ``` ### 3. 백엔드 구현 #### 사용자 프로필 동기화 새 사용자가 소셜 로그인으로 가입할 때 추가 정보를 저장하는 Supabase 함수: ```sql -- Supabase 함수로 auth.users 테이블에서 core.users로 사용자 정보 동기화 CREATE OR REPLACE FUNCTION public.handle_new_user() RETURNS TRIGGER AS $$ BEGIN INSERT INTO core.users (id, email, name, auth_provider, auth_provider_id, avatar_url) VALUES ( NEW.id, NEW.email, COALESCE(NEW.raw_user_meta_data->>'full_name', NEW.email), NEW.provider, NEW.provider_id, NEW.raw_user_meta_data->>'avatar_url' ); -- 기본 서비스 접근 권한 부여 (예: 처음 가입한 서비스) INSERT INTO core.service_access (user_id, service_id, access_level) SELECT NEW.id, id, 'user' FROM core.services WHERE name = 'budget'; -- 예시: 적자 탈출 가계부를 기본 서비스로 설정 RETURN NEW; END; $$ LANGUAGE plpgsql SECURITY DEFINER; -- 트리거 설정 CREATE TRIGGER on_auth_user_created AFTER INSERT ON auth.users FOR EACH ROW EXECUTE PROCEDURE public.handle_new_user(); ``` #### 서비스 간 인증 상태 공유 쿠키 또는 localStorage를 사용한 SSO 세션 관리: ```javascript // ZELLYY Core API 서비스 export const checkAndRefreshSession = async () => { const { data, error } = await supabase.auth.getSession(); if (error || !data.session) { // 세션이 없거나 만료됨 return { isAuthenticated: false }; } // 세션 활성 연장 if (data.session.expires_at - Date.now() / 1000 < 3600) { // 만료 1시간 전이면 갱신 await supabase.auth.refreshSession(); } return { isAuthenticated: true, user: data.session.user, accessibleServices: await getUserServices(data.session.user.id) }; }; // 사용자의 접근 가능한 서비스 목록 조회 const getUserServices = async (userId) => { const { data, error } = await supabase .from('service_access') .select(` service:service_id ( id, name, description, api_endpoint ), access_level `) .eq('user_id', userId); if (error) throw new Error('서비스 접근 권한 조회 실패'); return data.map(item => ({ ...item.service, accessLevel: item.access_level })); }; ``` ## 통합 사용자 경험 ### 1. 최초 로그인 1. 사용자가 어느 ZELLYY 서비스에서든 "구글로 로그인" 버튼 클릭 2. 구글 OAuth 인증 화면으로 리다이렉트 3. 인증 후 ZELLYY Core로 리다이렉트 4. 최초 로그인인 경우: - 사용자 프로필 정보 저장 - 접근한 서비스에 대한 권한 부여 - 환영 화면 표시 5. 로그인 완료 후 원래 서비스로 리다이렉트 ### 2. 서비스 간 전환 사용자가 이미 로그인한 상태에서 다른 ZELLYY 서비스 접근 시: 1. 서비스는 로컬 스토리지 또는 쿠키에서 토큰 확인 2. ZELLYY Core API에 토큰 검증 요청 3. 유효한 토큰이면 자동 로그인 처리 4. 접근 권한이 없는 서비스의 경우 권한 요청 화면 표시 ### 3. 로그아웃 1. 어느 서비스에서든 로그아웃 시 ZELLYY Core 로그아웃 API 호출 2. 모든 서비스에서 인증 토큰 삭제 3. SSO 세션 종료 ## 보안 고려사항 1. **PKCE 인증 흐름**: OAuth에 PKCE(Proof Key for Code Exchange) 사용 2. **토큰 관리**: 짧은 수명의 액세스 토큰과 리프레시 토큰 사용 3. **HTTPS**: 모든 통신은 HTTPS로 암호화 4. **CORS 설정**: API에 적절한 CORS 정책 적용 5. **CSP(Content Security Policy)**: 적절한 CSP 헤더 설정 ## 다음 단계 1. 구글 및 애플 개발자 계정 설정 및 OAuth 클라이언트 등록 2. Supabase Auth 설정 및 테스트 3. 로그인 UI 컴포넌트 개발 4. 소셜 로그인 통합 테스트 5. 서비스 간 SSO 흐름 테스트 ```