네 단계로 연동
프런트엔드에서 로그인 시작
@tutu/id-sdk의 createTutuId({ baseUrl, clientId })로 인스턴스를 만들고 클릭 시 idSdk.startLogin()을 호출합니다. SDK가 PKCE 쌍을 생성하고 TutuId 인가 페이지로 리디렉션합니다.
사용자가 TutuId에서 인가
/oauth/authorize 동의 화면에서 사용자가 “허용”을 클릭합니다(이미 인가했다면 자동 건너뜀). TutuId가 client_id와 redirect_uri 화이트리스트를 검증한 뒤 인가 코드를 담아 당신의 /auth/callback으로 돌려보냅니다.
콜백 페이지에서 code 받기
/auth/callback에서 idSdk.completeCallback()을 호출해 { code, codeVerifier }를 받습니다. 이 두 값을 당신의 백엔드로 넘기고, 브라우저에서 직접 token을 교환하지 마세요.
백엔드에서 token 교환 → 계정 생성
당신의 백엔드는 code + codeVerifier를 access_token으로 교환하고 /userinfo를 호출해 { sub, email, emailVerified, ... }를 받은 뒤 sub로 로컬 계정을 매핑하거나 생성하고, 자체 세션을 발급합니다.
★ 계정 탈취 방어(반드시 준수)
당신의 백엔드는 sub(계정 고유 ID)로만 로컬 계정을 연결하거나 생성할 수 있습니다. emailVerified === true일 때만 이메일로 기존 로컬 계정을 연결할 수 있으며, 그렇지 않으면 별도 계정을 만들고 이메일을 비워 두세요.
이유: 공격자가 피해자의 이메일로 Tutu 계정을 선점 등록할 수 있습니다. 미확인 이메일로 병합하면 피해자의 로컬 계정을 넘겨주는 셈입니다. 이는 CVE 급 레드라인입니다.
SDK API 레퍼런스
@tutu/id-sdk · 순수 클라이언트, 의존성 제로(Web Crypto + sessionStorage 필요).
createTutuId({ baseUrl, clientId, redirectUri? }) SDK 인스턴스를 만듭니다. redirectUri 기본값은 ${location.origin}/auth/callback이며 dev/prod에 맞춰 적응합니다.
startLogin(scope?) PKCE 쌍을 생성하고 인가 페이지로 리디렉션하여 “Tutu 계정으로 로그인”을 시작합니다.
trySilentLogin(scope?) 사일런트 로그인: 중앙 세션이 있고 이전 인가가 있으면 자연스럽게 코드를 교환하고, 아니면 즉시 로그아웃 상태로 되돌립니다(사용자를 방해하지 않음).
completeCallback() 콜백 페이지에서 결과를 파싱합니다: 성공 시 { code, codeVerifier }, 실패/취소 시 { error }를 반환합니다.
logoutEverywhere(returnTo?) 중앙 세션을 로그아웃하고 스위트의 모든 제품을 연쇄적으로 로그아웃한 뒤 returnTo로 돌아갑니다.
먼저 동작을 보고 싶으신가요?