Auth JS SDK
Auth JS SDK는 앱 사용자의 Google/Apple 로그인, callback relay, session 조회, service token 발급, logout을 담당한다.
설치
npm install @spectra-platform/auth-sdk@0.1.10
0.1.10은 2026-09-05 GitHub Packages에 발행됐다. 역할 70이 registry latest, 새 캐시 설치,
공개 import·타입과 발행 tarball의 다운로드 일치를 확인했다. Private package이므로 소비 앱 설치 환경에
GitHub Packages registry 설정과 read 권한이 필요하다. 발행 패키지.
SDK 설치와 Auth/Console 서버 배포는 별개다. 모바일 HTTP 경로의 운영 상태는 통합 가이드를 확인한다.
API tree
Auth JS SDK
├─ Client setup
│ ├─ new SpectraAuthClient(config)
│ ├─ createSpectraAuth(config)
│ ├─ createLocalStorageSessionStore()
│ └─ createMemorySessionStore()
├─ Login
│ ├─ signInWithGoogle(options?)
│ ├─ preflightSignIn(options?) [0.1.10]
│ ├─ signInWithApple(options?)
│ ├─ relaySpectraAuthCallback()
│ └─ readSpectraAuthCallback()
└─ Session and tokens
├─ getSession()
├─ getAccessToken(options?)
├─ refresh()
└─ logout()
앱에 필요한 값
projectId: Console에서 생성한 Project IDpublicClientId: 현재 Auth SDK package가 요구하는 호환 field. 새 제품 계약의 주요 user-managed key는 아니다.environment:test또는liveredirectUri: 로그인 완료 후 돌아갈 앱 또는 웹 callback URLbaseUrl: 필요 시 Spectra Auth API public endpointsessionStore: 선택 사항. 브라우저 새로고침 후 유지가 필요하면createLocalStorageSessionStore()를 쓴다.
redirectUri는 Google/Apple 개발자 콘솔에 등록하는 provider callback이 아니다. 이 값은 앱이 로그인 결과를 받을 주소이며, Console의 App/Web Callback 영역에서 관리한다.
로컬 개발에서도 같은 규칙을 쓴다.
http://localhost:5174/auth/callbackhttp://127.0.0.1:5174/auth/callback
브라우저 보안 모델에서는 localhost와 127.0.0.1이 서로 다른 origin이다. 로컬 앱이 공개 Spectra Auth API를
호출하려면 결과를 받을 전체 URL을 App/Web Callback에 등록한다. 배포된 Auth에서 활성 Test App Client의
등록된 웹 callback origin은 Auth SDK CORS에 자동 반영된다. 기존 static/loopback 허용도 유지된다.
운영 배포 상태와 활성화 조건은 Console Test 개발 설정을 따른다.
기존 Public test 검증 기록에서는 http://localhost:5173, http://localhost:5174,
http://127.0.0.1:5173, http://127.0.0.1:5174 origin의 Auth SDK social login challenge 호출이 허용됐다.
빠른 시작
모바일 LAN HTTP 개발은 모바일 로컬 HTTP 로그인을 따른다.
development?: { allowInsecureHttp?: boolean }와 preflightSignIn()은 발행된 0.1.10에 포함된다.
소스 7a7e521의 로컬 검증과 registry 새 캐시 설치 검증을 통과했다. Auth/Console 배포 및
실기기 검증 상태는 SDK 발행과 구분한다.
development: { allowInsecureHttp: import.meta.env.DEV }는 지원 SDK 확인 후 test의 실제 HTTP
private IPv4/loopback과 same-origin callback에서만 fallback을 허용한다. same-origin 제약은 이 새 fallback에만
적용하며 기존 HTTPS의 별도 origin callback과 localhost native Web Crypto 로그인 동작은 유지한다.
SDK가 개발 빌드를 자동 판별하지는 않는다. Vite 예제의 import.meta.env.DEV가 production build에서 옵션을 끈다.
HTTP 개발에는 test 환경에 등록·활성화된 해당 App Client와 Provider 설정을 사용한다. environment만
바꿔 live 구성을 자동 재사용하지 않으며 기존 live 설정을 유지한다. 이미 Auth Test라면 기존 구성을 사용한다.
Secret Key 환경은 Auth App Client 환경과 별개이며 재발급은 필요 없다.
import {
SpectraAuthClient,
createLocalStorageSessionStore,
} from "@spectra-platform/auth-sdk";
const auth = new SpectraAuthClient({
baseUrl: "https://auth.spectra.kr",
projectId: "proj_...",
// Current Auth SDK compatibility field. It is not a primary product key.
publicClientId: "app_...",
environment: "test",
redirectUri: "https://myapp.example.com/auth/callback",
sessionStore: createLocalStorageSessionStore(),
});
const session = await auth.signInWithGoogle();
console.log(session.user?.email);
Apple 로그인은 같은 client 설정을 사용한다.
await auth.signInWithApple();
Apple key/client secret이 아직 발급되지 않은 프로젝트라면 Google부터 검증한다. Apple credential 미발급은
소비 앱 버그가 아니라 provider 준비 범위 밖의 상태로 기록한다.
Callback 페이지
redirectUri로 등록한 페이지에서는 SDK callback helper를 호출해 원래 로그인 popup으로 결과를 전달한다.
import { relaySpectraAuthCallback } from "@spectra-platform/auth-sdk";
relaySpectraAuthCallback();
일반 앱 코드는 callback 내부의 challengeId, broker callback, provider callback 같은 내부 값을 알 필요가 없다.
API detail
new SpectraAuthClient(config)
Auth client를 만든다.
- 현재 package 기준으로
projectId,publicClientId,environment는 필수다.publicClientId는 제품 계약상 주요 key가 아니라 구현 정렬 전 호환 field로 본다. redirectUri는 앱 또는 웹 callback URL이다.baseUrl기본값은https://auth.spectra.kr이다.sessionStore를 주입하지 않으면 memory store가 사용되어 새로고침 시 세션이 사라진다.
createSpectraAuth(config)
new SpectraAuthClient(config)와 같은 결과를 반환하는 factory helper다.
createLocalStorageSessionStore()
브라우저 localStorage 기반 session store를 만든다. 앱이 새로고침 후에도 로그인 상태를 유지해야 하면 이 store를 명시적으로 사용한다.
preflightSignIn(options?)
0.1.10에서는 클릭 핸들러의 SDK 직접 호출이 동기 preflight 후 popup을 확보한다.
새 auth.preflightSignIn(options?: SpectraSignInOptions): void는 실패 시 동기 throw하며,
앱이 자체 popup을 유지할 때만 생성 전에 별도로 호출한다. 일반 SDK 로그인에서는 선행 popup이 필요 없다.
이 API는 발행된 0.1.10에 포함되며 full-page redirect API는 제공하지 않는다.
signInWithGoogle(options?)
Google Hosted Login popup을 열고 로그인 완료 후 Spectra app-user session을 저장한다.
options.redirectUri로 일회성 callback URL override가 가능하다.- 성공하면
SpectraAuthSession을 반환한다. - provider secret이나 Google client secret은 앱에 들어가지 않는다.
signInWithApple(options?)
Apple Hosted Login popup을 열고 같은 session 발급 흐름으로 처리한다.
- Apple private key와 client secret 생성은 서버가 맡는다.
- 앱은 현재 SDK 호환 설정과 callback URL만 가진다.
relaySpectraAuthCallback()
callback page에서 호출한다. 현재 URL의 로그인 결과를 opener window에 전달하고, 원래 signInWithGoogle() 또는 signInWithApple() promise가 session exchange를 완료하도록 돕는다.
readSpectraAuthCallback()
callback URL에서 SDK callback payload를 직접 읽어야 하는 낮은 수준 helper다. 일반 앱은 대부분 relaySpectraAuthCallback()만 사용한다.
getSession()
현재 저장된 app-user session snapshot을 반환한다. 로그인 전이면 null이다.
반환 형태는 getSession(): SpectraAuthSession | null이며 동기 메서드다.
반환되는 사용자 정보는 provider와 Auth 서버가 검증한 비민감 요약이다.
emailemailVerifieddisplayNamegivenNamefamilyName
getAccessToken(options?)
반환 형태는 getAccessToken(options?: SpectraGetAccessTokenOptions): Promise<string>이며 await해서 읽는다.
세션이 없으면 SESSION_UNAVAILABLE로 reject한다.
현재 access token을 반환한다. 만료가 가까우면 SDK가 refresh를 시도한다. 0.1.6 source부터 같은 SDK
인스턴스에서 동시에 들어온 동일 service token 요청은 한 번의 refresh와 한 번의 service-token 발급 결과를 공유하고,
Auth API가 429를 반환하면 service별 cooldown 동안 같은 요청을 반복 전송하지 않는다.
const authToken = await auth.getAccessToken();
const storageToken = await auth.getAccessToken({ service: "storage" });
const chatToken = await auth.getAccessToken({ service: "chat" });
service에는 email, notification, storage, chat, call을 사용할 수 있다. 다른 SDK는 보통 이 함수를 직접 호출하지 않고 Auth 객체를 주입받아 필요한 service token을 내부적으로 요청한다.
신규 Chat 나가기 계약의 chat.rooms.leave는 app-user Chat token에만 발급되는
권한이다. 기존 token의 scope는 소급 승격되지 않으며 현재 Auth session으로 새 service token을 발급받아야 한다.
Chat SDK의 기존401/4031회 force-refresh 경로를 사용하고 소비자가 scope를 직접 설정하거나 Secret Key를
추가하지 않는다. 새 token의 활성 여부와 Chat의 현재 membership 허용 여부도 별개다.
이 신규 grant는 이번 로컬 변경에서 undeployed이며 Auth·Chat 배포 및 Chat SDK0.2.0발행 전에는 활성 계약이 아니다.
refresh()
refresh token으로 app-user session을 갱신한다. 성공하면 session store를 업데이트하고 service token cache를 비운다.
동시에 여러 refresh()가 호출되면 SDK 인스턴스 안에서 하나의 요청으로 합쳐진다.
logout()
현재 session revoke를 서버에 요청하고 local session과 service token cache를 정리한다. session이 이미 없으면 local store만 비운다.
Local Google login QA
로컬에서 SDK 방식으로 Google 로그인을 확인할 때는 소비 앱에서 Auth 서버를 로컬로 띄울 필요가 없다. 앱은
브라우저에서 공개 https://auth.spectra.kr를 호출하고, 로그인 완료 후 redirectUri로 지정한 로컬 callback
페이지가 결과를 받아 relaySpectraAuthCallback()으로 원래 창에 전달한다.
체크 순서는 다음과 같다.
1. 소비 앱의 redirectUri가 실제 브라우저 주소와 같은 origin인지 확인한다.
- 예: 앱이 http://127.0.0.1:5174에서 열리면 callback도 http://127.0.0.1:5174/auth/callback
2. Console의 App/Web Callback에도 같은 URL을 저장한다.
3. Test callback의 origin 자동 CORS 반영과 실제 OPTIONS/SDK 요청을 확인한다. 등록만으로 로그인 권한이 부여되지는 않는다.
4. callback route에서 relaySpectraAuthCallback()을 호출한다.
5. signInWithGoogle() 버튼을 눌렀을 때 Google 계정 선택 화면까지 열리는지 확인한다.
6. callback 후 getSession()과 getAccessToken()으로 실제 app-user session/token을 확인한다.
2026-08-02 public smoke 기준으로 Origin: http://127.0.0.1:5174의
POST /platform/v1/auth/social/challenges는 201을 반환했고, modo-camp 로컬 Google 로그인은
Google account chooser까지 정상 진입했다.
Error handling
로그인 시작 전 SDK crypto/local preflight, popup 차단 또는 브라우저 CORS 실패에는 requestId가 없을 수 있다.
이때는 origin, callback, SDK 버전, 시각과 실패 단계를 기록한다. 자세한 구분과 실기기 Google/Apple QA는
모바일 로컬 HTTP 로그인을 본다.
Auth API가 rate limit이나 validation 오류를 반환하면 SDK는 SpectraAuthError로 정규화한다. 0.1.4부터
안전한 진단 metadata인 retryAfterSeconds와 requestId를 함께 읽을 수 있다.
SpectraAuthErrorDetails는 생성자 입력 타입이며 소비 시에는 error.status, error.requestId,
error.retryAfterSeconds를 직접 읽는다. error.details 아래에 있는 필드가 아니다.
새 HTTP/popup 경로의 INSECURE_HTTP_NOT_ALLOWED, REDIRECT_URI_INVALID, SIGN_IN_IN_PROGRESS,
POPUP_BLOCKED, POPUP_CLOSED, SIGN_IN_TIMEOUT별 조치는 모바일 실패 진단을 본다.
import { isSpectraAuthError } from "@spectra-platform/auth-sdk";
try {
await auth.signInWithGoogle();
} catch (error) {
if (isSpectraAuthError(error) && error.code === "RATE_LIMITED") {
console.log(`Retry after ${error.retryAfterSeconds ?? "a few"} seconds.`);
console.log(`Request ID: ${error.requestId ?? "unknown"}`);
return;
}
throw error;
}
Try again later.만 화면에 보여주면 사용자가 원인을 알기 어렵다. 소비 앱은 가능한 한 error.code,
error.status, error.retryAfterSeconds, error.requestId를 함께 표시하거나 로그에 남긴다.
Storage/Chat/Notification token 진단
다른 SDK에 Auth 객체를 주입했는데 service token 발급이 실패하면 먼저 앱 안의 Auth session이 살아 있는지 확인한다.
const session = auth.getSession();
const storageToken = await auth.getAccessToken({
service: "storage",
});
console.log(Boolean(session), Boolean(storageToken));
getSession()이 null이면 소비 앱의 callback/sessionStore 흐름을 먼저 확인한다. getSession()은 존재하는데
APP_SESSION_UNAUTHORIZED가 발생하면 SDK error의 requestId를 Platform CS에 전달한다. Platform 쪽에서는
Auth API audit의 내부 denial_reason으로 token 누락, JWT 검증 실패, session row 부재, inactive session,
claim mismatch를 구분한다.
forceRefresh: true는 Platform CS가 특정 requestId 진단을 위해 요청한 단발성 확인에만 사용하고,
파일 선택·업로드 루프·렌더링 흐름에서 반복 호출하지 않는다.
Backend token verification
앱 Backend는 Auth access token을 직접 신뢰하지 말고 검증해야 한다.
권장 순서:
1. 브라우저/모바일 앱에서 auth.getAccessToken()을 옵션 없이 호출한다.
2. 앱 Backend가 그 bearer를 받아 GET https://auth.spectra.kr/platform/v1/auth/sessions/current로 검증한다.
3. 응답의 project_id, public_client_id, environment, app_user_id, 상태 값을 앱 서버 설정과 대조한다.
4. app-user profile, nickname, subscription 같은 도메인 데이터는 앱 Backend DB에서 관리한다.
const spectraToken = await auth.getAccessToken();
await fetch("/api/auth/spectra/session", {
method: "POST",
headers: {
Authorization: `Bearer ${spectraToken}`,
},
});
getAccessToken({ service: "chat" }), getAccessToken({ service: "storage" }) 같은 service token은 Chat/Storage
SDK용이다. backend 로그인 검증 API에 보내면 403 AUTH_SESSION_SCOPE_FORBIDDEN으로 거절된다.
자세한 예시는 Backend token verification을 본다.
Secret과 provider credential
Secret Key는 환경(test/live)에 묶인 만료일 없는 비밀값이며 최초 발급/재발급 직후 1회만 보여진다. Auth SDK 기본 설정은 Secret Key를 요구하지 않는다.
Provider credential은 브라우저 또는 모바일 앱 bundle에 넣지 않는다.
- Google client secret
- Apple private key
- Keycloak client secret