TypeScript

pauth.me × Next.js — 着信認証API実装ガイド

Next.js(TypeScript)プロジェクトにpAuth着信認証APIを組み込む手順を解説します。 API Routesでサーバーサイド処理を行い、フロントエンドからポーリングで認証完了を確認します。

※本ページのコード例は説明目的の擬似コードです。実際の実装では環境に合わせた調整が必要です。

前提条件

  • Node.js 18以上 / Next.js 13以上(App Router または Pages Router)
  • pauth.me APIキー(無料登録で取得)

Step 1: 環境変数の設定

# .env.local
PAUTH_API_KEY=your_api_key_here
PAUTH_BASE_URL=https://api.pauth.me

Step 2: API Route — 認証セッション開始

// pages/api/auth/start.ts
import type { NextApiRequest, NextApiResponse } from 'next'

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method !== 'POST') return res.status(405).end()

  const { phoneNumber } = req.body
  const response = await fetch(`${process.env.PAUTH_BASE_URL}/v1/auth/sessions`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.PAUTH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      phone_number: phoneNumber,
      callback_url: `${process.env.NEXT_PUBLIC_BASE_URL}/api/auth/callback`,
    }),
  })

  const data = await response.json()
  res.json({ sessionId: data.id, callNumber: data.call_number })
}

Step 3: フロントエンド — ポーリングで認証確認

// components/PhoneAuth.tsx
import { useState, useEffect } from 'react'

export function PhoneAuth({ sessionId }: { sessionId: string }) {
  const [status, setStatus] = useState<'pending' | 'verified' | 'expired'>('pending')

  useEffect(() => {
    if (status !== 'pending') return
    const timer = setInterval(async () => {
      const res = await fetch(`/api/auth/status?sessionId=${sessionId}`)
      const data = await res.json()
      if (data.status === 'verified') {
        setStatus('verified')
        clearInterval(timer)
        // ログイン処理へ
      } else if (data.status === 'expired') {
        setStatus('expired')
        clearInterval(timer)
      }
    }, 2000) // 2秒ごとにポーリング
    return () => clearInterval(timer)
  }, [sessionId, status])

  return (
    <div>
      {status === 'pending' && <p>電話をかけて認証を完了してください…</p>}
      {status === 'verified' && <p>認証完了!</p>}
      {status === 'expired' && <p>タイムアウトしました。再試行してください。</p>}
    </div>
  )
}

エラーハンドリング

// API Routeでのエラー処理
if (!response.ok) {
  const error = await response.json()
  return res.status(response.status).json({ error: error.message })
}

// フロントエンドでの最大試行回数制限
const MAX_POLLS = 30 // 60秒でタイムアウト
let pollCount = 0
const timer = setInterval(async () => {
  if (++pollCount > MAX_POLLS) {
    setStatus('expired')
    clearInterval(timer)
  }
  // ...ポーリング処理
}, 2000)

本番環境の注意点

  • APIキーはサーバーサイド(API Routes)のみで使用し、クライアントに公開しない
  • NEXT_PUBLIC_ プレフィックスをAPIキーに付けない
  • セッションIDをサーバーサイドセッション(NextAuth.js等)で管理する
  • App Routerの場合は Server Actions または Route Handlers を使用する

他のフレームワークでの実装