JS SDK
브라우저용 headless SDK — @snowoncard/snowpass-sdk
@snowoncard/snowpass-sdk 는 브라우저에서 WebAuthn/TOTP ceremony 를 수행하는 headless SDK 다.
UI 를 포함하지 않으므로 RP 가 화면을 완전히 통제한다. ESM 과 IIFE(index.global.js) 두 형태로
배포된다.
Installation
npm install @snowoncard/snowpass-sdkimport { Client, SnowPassError } from '@snowoncard/snowpass-sdk';또는 스크립트 태그 (IIFE — 전역 SnowPass):
<script src="/js/snowpass-sdk.js"></script>
<script>
const client = new SnowPass.Client({ baseUrl: '...', apiKey: 'pk_...' });
</script>Initialization
const client = new Client({
baseUrl: 'http://localhost:8080', // SnowPass public API 주소 (게이트웨이 뒤면 '/server' 같은 상대 경로 가능)
apiKey: 'pk_...', // public api key — 브라우저 노출 가능
});PassKey
// 이 브라우저에서 platform authenticator 사용 가능 여부
if (await client.isPasskeySupported()) {
// 등록: RP 백엔드가 발급한 registerToken(sprt_*) 사용
const reg = await client.registerPasskey(registerToken, { nickname: '내 맥북' });
// reg.resultToken 을 RP 백엔드로 전달해 검증
// 인증: authToken(spat_*) 사용
const auth = await client.authenticatePasskey(authToken);
// auth.resultToken 검증 → 세션 승격
}TOTP
// 등록: QR/secret 조회 → 사용자에게 QR 표시
const enrollment = await client.getTotpEnrollment(registerToken);
img.src = enrollment.qrPngDataUrl; // data URL 로 바로 표시
// enrollment.secret (Base32), enrollment.otpauthUri 도 제공
// 사용자가 입력한 6자리 코드 확인 — recovery codes 는 이 응답에서만 노출
const result = await client.verifyTotpEnrollment(registerToken, code);
showRecoveryCodesOnce(result.recoveryCodes);
// 인증
const auth = await client.verifyTotp(authToken, code);Error Handling
모든 오류는 SnowPassError 로 정규화된다 — code 는 서버 error.code 또는 SDK 자체 코드.
| code | 의미 |
|---|---|
CEREMONY_ABORTED | 사용자가 인증 창을 취소했거나 시간 초과 (NotAllowedError) |
AUTHENTICATOR_ALREADY_REGISTERED | 이 기기에 이미 등록된 passkey 존재 (InvalidStateError) |
ORIGIN_MISMATCH | rpId/origin 불일치 — 현재 도메인에서 WebAuthn 불가 (SecurityError) |
CONNECTION_ERROR | SnowPass 서버 연결 실패 |
CONFIG_ERROR | baseUrl/apiKey 누락 |
| 서버 코드 | CODE_INVALID, USER_LOCKED, TOKEN_EXPIRED 등 — Error Codes |
try {
await client.authenticatePasskey(authToken);
} catch (err) {
if (err instanceof SnowPassError && err.code === 'CEREMONY_ABORTED') {
// 사용자 취소 — 재시도 UI 표시
}
}