着信認証APIの実装方法(Node.js編) — pauth-js SDK入門

公開日: 2026-03-02

このチュートリアルでは、pauth.me着信認証APIをNode.jsアプリケーションに組み込む方法を解説します。公式SDK pauth-js を使えば、わずか数行のコードで電話番号認証フローを実装できます。

前提条件

  • Node.js 18以上
  • npm または yarn
  • pauth.me のアカウント(APIキー取得のため)

アカウントは無料で作成できます。サンドボックスAPIキー(test_ プレフィックス)があれば、実際の電話を使わずに動作確認できます。

インストール

npm install pauth-js

TypeScriptを使う場合も同パッケージに型定義が含まれているため、追加インストールは不要です。

APIキーの設定

APIキーはソースコードに直書きせず、環境変数で管理します。

# .env ファイルに記述
PAUTH_API_KEY=test_your-api-key-here
npm install dotenv

認証フロー実装(基本)

verify() メソッドを使うと、認証フロー全体(トークン取得 → 着信待機 → PIN照合)を1ステップで実行できます。

require('dotenv').config();
const { PauthClient } = require('pauth-js');

const client = new PauthClient({ apiKey: process.env.PAUTH_API_KEY });

async function authenticateUser(phoneNumber) {
  // 電話番号は国際形式(+81始まり)で指定
  const result = await client.verify(phoneNumber);
  console.log('認証成功:', result.callerNumber);
  return result;
}

authenticateUser('+819012345678').catch(console.error);

電話番号の形式: 日本の場合、0312345678+81312345678(先頭の0を除いて+81を付与)です。

サンドボックス動作: APIキーが test_ で始まる場合、サンドボックスモードで動作します。約2秒後に自動でPIN 1234 が返るため、実際に電話しなくても認証フローを確認できます。

ステップ分割フロー(entry / apply)

ユーザーに「この番号に電話してください」と表示してから確認するUIを実装する場合は、entry()apply() を分けて使います。

require('dotenv').config();
const { PauthClient } = require('pauth-js');

const client = new PauthClient({ apiKey: process.env.PAUTH_API_KEY });

// Step 1: 認証セッション開始 — ユーザーに発信先番号を提示
async function startAuth(phoneNumber) {
  const session = await client.entry(phoneNumber);
  // session.callerd_number: ユーザーが電話すべき番号
  // session.expires_in:     有効期限(秒)
  console.log('この番号に電話してください:', session.callerd_number);
  return session;
}

// Step 2: ユーザーが電話 → PINを受け取って照合
async function verifyPin(phoneNumber, pin) {
  const isValid = await client.apply(phoneNumber, pin);
  if (isValid) {
    console.log('認証成功!');
  } else {
    console.log('PINが一致しません。');
  }
  return isValid;
}

Expressでの実装例(フルコード)

require('dotenv').config();
const express = require('express');
const { PauthClient, RateLimitError, ConflictError } = require('pauth-js');

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

const client = new PauthClient({ apiKey: process.env.PAUTH_API_KEY });

// 電話番号フォーマット変換(日本国内形式 → 国際形式)
function toInternational(phone) {
  return phone.replace(/^0/, '+81');
}

// POST /auth/start — 認証セッション開始
app.post('/auth/start', async (req, res) => {
  const { phone } = req.body;
  if (!phone) {
    return res.status(400).json({ error: '電話番号が必要です' });
  }

  try {
    const session = await client.entry(toInternational(phone));
    res.json({
      callNumber: session.callerd_number,
      expiresIn: session.expires_in,
      message: `${session.callerd_number} に電話してください(1コールで切ってOK)`,
    });
  } catch (err) {
    if (err instanceof ConflictError) {
      return res.status(409).json({ error: 'この番号で認証が進行中です。しばらく待ってから再試行してください。' });
    }
    if (err instanceof RateLimitError) {
      return res.status(429).json({ error: 'リクエストが多すぎます', retryAfter: err.retryAfter });
    }
    console.error('認証開始エラー:', err);
    res.status(500).json({ error: '認証を開始できませんでした' });
  }
});

// POST /auth/verify — PIN照合して認証完了
app.post('/auth/verify', async (req, res) => {
  const { phone, pin } = req.body;
  if (!phone || !pin) {
    return res.status(400).json({ error: '電話番号とPINが必要です' });
  }

  try {
    const isValid = await client.apply(toInternational(phone), pin);
    if (isValid) {
      res.json({ success: true, message: '認証完了' });
    } else {
      res.status(401).json({ success: false, error: 'PINが一致しません' });
    }
  } catch (err) {
    console.error('PIN照合エラー:', err);
    res.status(500).json({ error: '認証確認に失敗しました' });
  }
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

エラーハンドリング

エラークラス 発生条件 対応方法
AuthenticationError無効・期限切れのAPIキー(401)APIキーを確認してください
ConflictError同一番号で認証が既に進行中(409)ユーザーに待機を促す
RateLimitErrorレート制限超過(429)err.retryAfter 秒後にリトライ
TimeoutErrorPIN待機タイムアウトユーザーに再試行を促す
const {
  PauthClient,
  AuthenticationError,
  ConflictError,
  RateLimitError,
  TimeoutError,
} = require('pauth-js');

try {
  const result = await client.verify('+819012345678');
} catch (err) {
  if (err instanceof AuthenticationError) {
    console.error('APIキーが無効です。環境変数PAUTH_API_KEYを確認してください。');
  } else if (err instanceof RateLimitError) {
    console.error(`レート制限。${err.retryAfter}秒後にリトライしてください。`);
  } else if (err instanceof TimeoutError) {
    console.error('タイムアウト。ユーザーが電話しなかった可能性があります。');
  } else {
    throw err;
  }
}

本番環境の注意点

APIキーの安全な管理
本番用APIキー(live_ プレフィックス)はGitリポジトリに含めないでください。.env.gitignore に追加することを忘れずに。
レート制限への対応
pauth.meにはAPIのレート制限があります。RateLimitError を適切にキャッチし、err.retryAfter 秒後に自動リトライするか、ユーザーに待機を案内する実装を推奨します。
サンドボックス → 本番の切り替え
APIキーを test_ から live_ に変更するだけで本番環境に切り替わります。コードの変更は不要です。

まとめ

pauth-js SDKを使えば、以下のシンプルなステップで着信認証をNode.jsアプリに組み込めます。

  1. npm install pauth-js でインストール
  2. new PauthClient({ apiKey }) でクライアント初期化
  3. client.verify(phoneNumber) または entry() → apply(phoneNumber, pin) で認証フロー実行
  4. エラーハンドリングで ConflictError / RateLimitError に対応

着信認証を試してみませんか?

サンドボックスで即日お試し。クレジットカード不要。

無料で始める 料金を見る