SDK 가이드

SecureKey API를 다양한 언어에서 사용하는 방법입니다.

설치npm
npm install @secondkey/node
SMS OTP
import { TwoFactorClient } from '@secondkey/node';

const client = new TwoFactorClient({
  apiKey: '2fa_your_api_key',
  baseUrl: 'https://securekey.ideacode.co.kr'
});

// SMS 발송
const result = await client.sms.send({
  phone: '01012345678',
  purpose: 'login'
});

// SMS 검증
const verify = await client.sms.verify({
  phone: '01012345678',
  code: '123456'
});
console.log(verify.verified); // true
TOTP
// TOTP 설정 시작
const setup = await client.totp.setup({
  userId: 'user_123',
  accountName: '[email protected]'
});
// setup.uri → otpauth:// URI
// setup.qrCodeDataUrl → QR 코드 이미지 (base64 PNG)

// TOTP 검증
const verify = await client.totp.verify({
  userId: 'user_123',
  token: '123456'
});
Email OTP
// Email OTP 발송
const result = await client.email.send({
  email: '[email protected]',
  purpose: 'login'
});

// Email OTP 검증
const verify = await client.email.verify({
  email: '[email protected]',
  code: '123456'
});
console.log(verify.verified); // true
WebAuthn / Passkey
// 1. 등록 옵션 요청 (서버) — userName 필수
const regOptions = await client.webauthn.registerOptions({
  userId: 'user_123',
  userName: '[email protected]'
});

// 2. 브라우저에서 Credential 생성
const credential = await navigator.credentials.create({
  publicKey: regOptions.publicKey
});

// 3. 등록 검증 (서버) — 브라우저 credential 필드를 최상위로 전달
const regResult = await client.webauthn.registerVerify({
  userId: 'user_123',
  id: credential.id,
  rawId: btoa(String.fromCharCode(...new Uint8Array(credential.rawId))),
  type: credential.type,
  response: credential.response,
  deviceName: 'Chrome on MacOS'
});

// 4. 인증 옵션 요청 (서버)
const authOptions = await client.webauthn.authenticateOptions({
  userId: 'user_123'
});

// 5. 브라우저에서 Credential 사용
const assertion = await navigator.credentials.get({
  publicKey: authOptions.publicKey
});

// 6. 인증 검증 (서버)
const authResult = await client.webauthn.authenticateVerify({
  userId: 'user_123',
  id: assertion.id,
  rawId: btoa(String.fromCharCode(...new Uint8Array(assertion.rawId))),
  type: assertion.type,
  response: assertion.response
});
Push 인증
// 1. 기기 등록 (FCM 토큰)
await client.push.registerDevice({
  userId: 'user_123',
  fcmToken: 'fcm_token_from_firebase_sdk',
  deviceName: 'iPhone 15',
  platform: 'ios'
});

// 2. Push 인증 요청 발송
const push = await client.push.send({
  userId: 'user_123',
  title: '로그인 승인 요청',
  body: '새로운 기기에서 로그인을 시도합니다.'
});

// 3. 사용자 기기에서 승인/거부 (모바일 앱)
await client.push.respond(push.requestId, 'approve');

// 4. 서버에서 결과 폴링 (requestId만 전달)
const result = await client.push.verify(push.requestId);
console.log(result.verified); // true
Webhook 수신
import crypto from 'crypto';
import express from 'express';

const app = express();
app.use(express.json());

app.post('/webhook/securekey', (req, res) => {
  // HMAC 서명 검증
  const signature = req.headers['x-securekey-signature'];
  const expected = 'sha256=' + crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(JSON.stringify(req.body))
    .digest('hex');

  if (!crypto.timingSafeEqual(
    Buffer.from(signature), Buffer.from(expected)
  )) {
    return res.status(401).send('Invalid signature');
  }

  const { event, channel, data } = req.body;
  console.log(channel + ' 인증 완료: ' + data.externalUserId);
  res.sendStatus(200);
});

PWA React PWA Push 인증 예제

Push 인증의 전체 흐름(기기등록 → 인증 요청 → 승인/거부 → Service Worker)을 React + TypeScript로 구현한 예제입니다.

examples/react-pwa/src/App.tsx — UI 및 인증 흐름
examples/react-pwa/src/sw.ts — Service Worker (백그라운드 Push 수신)

인증 방식

X-API-Key API Key를 헤더로 전달 (권장)
Authorization: Bearer Bearer 토큰 방식도 지원

응답 형식

// 성공
{ "success": true, "message": "...", "data": { ... } }

// 실패
{ "success": false, "error": "...", "code": "ERROR_CODE" }

// MFA 정책에 의한 추가 인증 요구
{ "success": false, "code": "MFA_REQUIRED",
  "requiredChannels": ["totp"], "matchedPolicies": ["결제 시 추가 인증"] }

Rate Limiting

전역: 100 req/min per IP

OTP 발송: 3 req/min per IP

인증 시도: 10 req/min per IP

초과 시 429 Too Many Requests 반환