SnowPass

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-sdk
import { 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_MISMATCHrpId/origin 불일치 — 현재 도메인에서 WebAuthn 불가 (SecurityError)
CONNECTION_ERRORSnowPass 서버 연결 실패
CONFIG_ERRORbaseUrl/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 표시
  }
}

On this page