sumsub-integrate-id-connect について
アプリに Sumsub ID Connect を組み込む開発スキルです。Sumsub 側の前提条件と事前チェックを確認してから、フロントエンドとバックエンドの OIDC フローを実装できます。
主な機能
- 01統合前提条件の確認
- 02ワークスペースと認証レベルの事前チェック
- 03PKCE による OIDC 認可の案内
- 04トークン交換と ID 再利用の連携
活用シーン
- 01アプリに Sumsub ID の認証導線を追加
- 02OIDC クライアントとコールバック設定の確認
- 03認可結果の受信とトークン交換
- 04Sumsub ID の情報を申請者として再利用
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sumsub/ agent-skills --skill sumsub-integrate-id-connectインストール後、Claude Code で/sumsub-integrate-id-connectを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
examples/express-callback.jsoidc-button.htmloidc-modal.htmloidc-redirect.htmlreferences/scopes-and-claims.mdscripts/preflight.sh詳細
Sumsub — ID Connect 統合
「Verify with Sumsub ID」OIDC フローを、前提条件 → 事前チェック → ボタン → バックエンドでの交換 → 同意 → ワークスペース内の申請者まで、エンドツーエンドで組み込みます。
⚠️ サンドボックストークンのみ
セットアップ中に本番用の App Token/シークレットを使用しないでください。
https://cockpit.sumsub.com/checkus/home?sbx=true から
サンドボックスのペアを必ず入手してください — Connect Sumsub to
your AI agent -> Build & configure -> Generate token。トークンとシークレットは作成時に一度だけ表示されるため、ダイアログを閉じる前に両方をコピーしてください。事前チェックでは sbx: プレフィックスの確認によってこれを強制します。
認証の詳細な仕組みについては、sumsub-api-auth を参照してください。
⛔ 操作の順序 — 先にアプリをスキャフォールドしないでください
これは、このスキルで最も重要なルールです。以下の両方のゲートを通過するまで、フロントエンドやバックエンドのコードを書いたり、デモプロジェクトを作成したり、スキャフォールドしたりしないでください。クライアント側の Sumsub 設定(ステージ 0a)は手動で行う必要があり、あなたが実行することはできません。これが完了する前にコードを書き始めても、認証もリダイレクトも再利用もできないアプリができあがるだけです。必ず次の手順に従ってください。
- ステージ 0a の前提条件をユーザーと1つずつ確認します。 完了していると決めつけないでください。各項目について存在するかどうかをユーザーに尋ね、存在しない場合は、いったん停止し、正確な手動手順と実施場所を案内します(サポートへのメールテンプレート、Dev Space → OIDC Settings への登録、App Token の発行ページ、レベル作成の引き継ぎ)。これらは Sumsub ダッシュボードまたはサポートでの操作のみであり、公開 API がないため、ユーザーに代わって実行することはできません。次に進む前に、すべての項目が確認されるまで待ってください。
- ステージ 0b の事前チェックを実行し、終了コード 0 を必須とします。 前提条件の確認後にのみ、
scripts/preflight.shを実行してください。すべての FAIL を解決してください(必要に応じてステージ 0a に戻ります)。FAIL が1つでもある場合は先に進まないでください。 - 両方のゲートを通過してから構築します。 両方のゲートが通過したら、ステージ 1 に進み、フロントエンド/バックエンドをスキャフォールドしてください。
ゲートを通過する前にユーザーが「とにかくデモを作って」と言った場合は、まだ動作しない理由を簡潔に説明し、まず不足している前提条件を満たす手順を案内してください。コードを書くのは最初ではなく、最後の手順です。
ID Connect とは(また、何ではないか)
Sumsub ID Connect を使うと、企業はエンドユーザーが所有する Sumsub ID アカウントから、年齢、氏名、国籍、メールアドレス、居住国、本人確認など、特定の検証済みアイデンティティ情報を要求できます。サインイン、アカウント作成(必要な場合)、メール OTP、不足している検証手順、受取人ごとの同意画面など、ユーザー向けフロー全体を Sumsub がホストします。アプリは、署名付き OIDC トークンとして結果を受け取ります。また、必要に応じて Reusable KYC を通じてワークスペース内に申請者が作成されます。
これは WebSDK ではありません。WebSDK はページ内で完全な KYC 情報取得を実行しますが、ID Connect では UX 全体を Sumsub に委ねます。
ライフサイクルの全体像
┌──────────────────────────────┐
│ Stage 0a Preconditions check │ manual setup on Sumsub side
│ Stage 0b scripts/preflight.sh │ automated validation
└──────────────┬───────────────┘
│ clientId, levelName, allowlist
┌──────────────▼───────────────┐
│ Stage 1: Frontend "Verify…" │ authorize redirect with PKCE
│ button │
└──────────────┬───────────────┘
│ onSuccess({ code, state })
┌──────────────▼───────────────┐
│ Stage 2: code → access_token │ POST id.sumsub.com/api/snsId/oauth/token
│ (client_secret_basic) │
└──────────────┬───────────────┘
│ access_token
┌──────────────▼───────────────┐
│ Stage 3a: → share token │ POST /resources/accessTokens/sumsubIdShareToken
└──────────────┬───────────────┘
│ sharingAllowed?
┌───────┴────────┐
│ false │
▼ ▼ true
┌──────────────────┐ ┌──────────────────────────────┐
│ Stage 3b: │ │ Stage 4: reuse/preview + │
│ shareLink │ │ reuse/commit │
│ redirect + retry │ │ → applicant in your workspace │
└────────┬─────────┘ └──────────────────────────────┘
│
└──────► back to Stage 3a (retry — now sharingAllowed: true)
エンドポイント
| METHOD | URL | Auth | Stage |
|---|---|---|---|
| (ブラウザーのリダイレクト) | https://id.sumsub.com/api/snsId/oauth/authorize | なし | 1 |
| GET | https://id.sumsub.com/.well-known/openid-configuration | なし | 0b |
| GET | https://id.sumsub.com/.well-known/jwks.json | なし | (id_token の検証) |
| POST | https://id.sumsub.com/api/snsId/oauth/token | client_secret_basic | 2 |
| POST | https://api.sumsub.com/resources/accessTokens/sumsubIdShareToken | App Token + HMAC | 3a |
| POST | https://api.sumsub.com/resources/snsId/oauth/shareLink | App Token + HMAC + Bearer | 3b |
| GET | https://api.sumsub.com/resources/api/reusableIdentity/reuse/preview | App Token + HMAC | 4 |
| POST | https://api.sumsub.com/resources/api/reusableIdentity/reuse | App Token + HMAC | 4 |
「Enable Sumsub ID Connect」トグル、OIDC クライアント登録 (client_secret + redirect_uri の許可リスト)、共有パートナー登録は、Sumsub ダッシュボードの UI でのみ実行できます — 公開 API に相当するものはありません。
ステージ 0a — 事前条件チェックリスト
コード作成や事前チェックを行う前に、Sumsub 側で以下がすべて用意されている必要があります。各項目は、以下のチェック項目または未対応の場合の実行時エラーに対応しています。
-
Sumsub サポートがワークスペースで ID Connect を有効にしていること。これはセルフサービスで切り替えられる設定ではありません。サポートが有効化するまでは OIDC クライアントを作成できず、事前チェックで
connect_token: ID Connect not enabled for this workspaceと報告されます。まず担当の CSM または[email protected]にメールを送り、確認を待ってください。テンプレート:``` Subject: Enable Sumsub ID Connect for clientId <YOUR_CLIENT_ID> (sandbox) Hi Sumsub team, Please enable Sumsub ID Connect for our workspace. Environment: sandbox clientId: <YOUR_CLIENT_ID> (Dashboard top-left) Intended scopes: openid, share, name (adjust as needed) Intended recipients: self (or list partner clientIds) Use case: <one-line description of where the button will live> Once enabled we'll register the OIDC client + redirect URIs in Dev Space → OIDC Settings. Thanks ``` -
App Token + シークレット(sandbox)。 https://cockpit.sumsub.com/checkus/home?sbx=true で Connect Sumsub to your AI agent -> Build & configure -> Generate token を選択して発行します。両方の値は作成時に一度だけ表示されます。→
SUMSUB_APP_TOKEN/SUMSUB_SECRET_KEYとしてエクスポートします。 -
OIDC クライアントが Dashboard → Dev Space → OIDC Settings に登録されていること。以下の 3 項目を控えてください。 -
client_id(公開情報 — ブラウザーに設定します。一般的な自己受取人のケースでは、共有トークンのforClientIdとして使用します) -client_secret(作成時に一度だけ表示されます。紛失した場合は再発行が必要で、既存の連携は無効になります)。ステージ 2 のコード→トークン交換に必要です — サーバー側だけで管理してください。 -redirect_uriの許可リストに、両方のコールバックを登録します(Sumsub はバイト単位で照合するため、末尾のスラッシュ、大文字と小文字、ポート、クエリがすべて一致している必要があります)。 - 認可コールバック(例:https://yourapp.com/auth/callback) - shareLink コールバック(例:https://yourapp.com/share-complete) Sumsub はブラウザーをこれらの URL にリダイレクトするため、公開された HTTPS が必要です。http://localhost:3000だけではローカルテストに使えません。お使いのマシンで開発するには、ngrok などの公開 HTTPS トンネルを使ってローカルサーバーを公開し、そのオリジンを許可リストに追加してください — 詳細は以下のngrok を使ったローカル開発を参照してください。 -
このワークスペースに少なくとも 1 つの検証レベルが存在すること。
levelNameを控えてください。存在しない場合は、まずsumsub-create-levelに引き継いでください — ステージ 4 では、検証レベルなしに申請者を作成できません。 -
**エンドツーエンドテスト用に、検証済みデータがある Sumsub ID アカウントが少なくとも 1 つ存在すること。**KYC が完了していないメールのみのアカウントでは、ステージ 4 でエラーコード
10521 reusable-kyc-inactive-sumsub-id-accountが発生します — ステージ 4 の最後にあるエラー表を参照してください。
ステージ 0b — 事前チェック
scripts/preflight.sh は、OIDC コードの発行や申請者の作成を行わずに確認できる前提条件を、機械的に検証します。何も変更しません。
SUMSUB_APP_TOKEN=sbx:... SUMSUB_SECRET_KEY=... \
bash scripts/preflight.sh
チェック項目(それぞれ独立して実行されるため、1 つの失敗でほかのチェックが中断されることはありません):
| チェック | 確認できること |
|---|---|
connect_token | App-Token の HMAC 署名が受け付けられ、ワークスペースで ID Connect が有効になっていることを確認します。既知の不正なコードでエンドポイントにプローブし、401 Invalid code が返ることを想定します(404 invalid clientId が返る場合は、ID Connect が有効になっていません)。これは接続性/利用資格のプローブであり、ステージ 2 の交換ルートではありません。 |
oidc_discovery | https://id.sumsub.com/.well-known/openid-configuration が有効な OIDC ディスカバリードキュメントを返すこと |
levels | このワークスペースに少なくとも 1 つの検証レベルが存在すること |
すべて PASS、または PASS と WARN の組み合わせの場合は終了コード 0、FAIL が 1 つでもある場合は 10 です。ステージ 1 に進む前に、すべての FAIL を解消してください。
ngrok を使ったローカル開発
ID Connect は http://localhost に対してテストできません。Sumsub は authorize フロー(ステージ 1)の後と shareLink の同意フロー(ステージ 3b)の後に、ブラウザーを redirect_uri にリダイレクトします。また、その URL は一般公開された HTTPS であり、OIDC クライアントの redirect_uri 許可リストに一字一句違わず登録されている必要があります。localhost の URL は一般公開されておらず HTTPS でもないため、リダイレクトに失敗します。ローカル開発では、ngrok を使ってローカルサーバーの前に HTTPS の公開トンネルを設置し、そのオリジンを許可リストに追加してください。
-
バックエンドをローカルで起動します(この例では
PORT=3000で待ち受けます)。PORT=3000 node examples/express-callback.js -
そのポートへのトンネルを開きます。 再起動後も URL が変わらないよう、予約済み(静的)ドメインを使うことをおすすめします。無料のランダムな ngrok URL は起動するたびに変わるため、その都度、許可リストを編集する必要があります。
ngrok http 3000 --domain=your-reserved-name.ngrok-free.app # or, ephemeral URL (changes each restart): ngrok http 3000ngrok が転送先 URL を表示します。例:
https://your-reserved-name.ngrok-free.app。 -
ngrok のオリジンに両方のコールバックを許可リストに追加します。 Dashboard → Dev Space → OIDC Settings(サンドボックスワークスペース)で、末尾のスラッシュも含めて一字一句違わずに登録してください。
https://your-reserved-name.ngrok-free.app/ https://your-reserved-name.ngrok-free.app/share-complete -
localhost ではなく公開 URL をアプリに設定します。 ブラウザーの
redirect_uriとサーバー側の shareLinkredirectUriは、同じ公開オリジンを基にする必要があります。そのため、PUBLIC_BASE_URLを設定して再起動します。PUBLIC_BASE_URL=https://your-reserved-name.ngrok-free.app \ PORT=3000 node examples/express-callback.js次に、ブラウザーで
localhost:3000ではなくngrok URLを開き、送信されるredirect_uriが許可リストと一致するようにします。
⚠️ URL が変わるたびに再登録してください。 一時的な ngrok URL を使う場合、ngrok の再起動のたびに許可リストのエントリーと
PUBLIC_BASE_URLを更新する必要があります。予約済みドメインを使えば、この手間を避けられます。ngrok の無料インタースティシャルページ(「You are about to visit…」)が影響するのは API/XHR 呼び出しのみで、ブラウザーのトップレベルナビゲーションには影響しないため、OIDC リダイレクトは妨げられません。予約済みドメインまたは有料プランを使えば、このページは完全に表示されなくなります。
ステージ 1 — フロントエンド:ボタン
⛔ ゲート。 ステージ 0a の前提条件をすべてユーザーに確認し、ステージ 0b の事前チェックが終了コード 0 で終了するまで、このステージを開始しないでください。両方を完了していない場合は戻ってください。上記の「作業の順序」を参照してください。ここがコードを書く最初のステージです。それより前に行うことはすべてセットアップであり、事前に確認する必要があります。
アーキテクチャ — お客様側とSumsub側の担当範囲
Sumsubが提供するもの:OIDCサービス(id.sumsub.com)、HMAC API
(api.sumsub.com)、およびボタンをマウントするオプションの
@sumsub/id-connect JSライブラリ。
統合の両方の部分はお客様が実装します。
- フロントエンド(このステージ) — ボタンを設置するページです。PKCEを生成し、
id.sumsub.comへのOIDCリダイレクトを開始して、コールバックで?code=を受け取り、{ code, codeVerifier }をお客様のバックエンドにPOSTします。 - バックエンド(ステージ2〜4) — フロントエンドからPOSTを受け取るHTTPエンドポイントです。App TokenとシークレットでSumsub APIへの呼び出しに署名します(これらをブラウザーに渡すことは絶対に避けてください)。
code → access_token → share token → reuseの一連の処理を調整し、マテリアライズされた申請者を返します。
両方の部分は、1つのルート名で連携します。例ではPOST /api/sumsub/id-connect/exchangeを使用しています。お客様のルーティングに合わせて変更してください。一致するリファレンスのペアは次のとおりです。
examples/oidc-button.html(フロントエンド)+
examples/express-callback.js(バックエンド)。
バックエンドは薄いオーケストレーター(Node/Expressで約180行)です。ワイヤ形式は言語に関係なく同一なので、お好みのスタックに移植してください。
⚠️
onSuccessは検証完了を示すシグナルではありません。 ユーザーがOIDCの同意手順を完了し、Sumsubが認可コードを発行したことを確認するだけです。 実際の検証結果はステージ4で取得します。/reuseレスポンスのapplicant.review.reviewStatus(受取先レベルで追加チェックが実行されない場合は即時)またはapplicantReviewedwebhook(再利用後にチェックを実行するレベルでは、いずれも正式な結果)です。onSuccessの発火を根拠にアクセスを許可したり、機能をロック解除したりしないでください。
3つの方式があります。デフォルトでは**方式1(createButton)**を使用してください。ほかの方式は、デザインシステムやバンドラーを使用しない環境向けです。
方式1 — @sumsub/id-connectによる組み込みボタン(推奨)
import { createButton } from '@sumsub/id-connect';
// PKCE helpers (S256 — full versions in examples/oidc-button.html).
const b64url = (buf) => btoa(String.fromCharCode(...new Uint8Array(buf)))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
const sha256 = (s) => crypto.subtle.digest('SHA-256', new TextEncoder().encode(s));
// Generate the PKCE pair yourself, store the verifier under YOUR key — Stage 2
// on the backend needs that verifier to exchange the code for an access token.
const verifier = b64url(crypto.getRandomValues(new Uint8Array(32)));
const challenge = b64url(await sha256(verifier));
sessionStorage.setItem('myapp.pkce.verifier', verifier);
createButton({
clientId: '<your-client-id>',
permissions: ['openid', 'share', 'name'],
container: document.getElementById('button-container'),
codeChallenge: challenge, // library uses YOUR challenge — skips its own PKCE gen
loginHint: '[email protected]', // optional, prefills the email field
onSuccess: async ({ code, state }) => {
const v = sessionStorage.getItem('myapp.pkce.verifier');
await fetch('/api/sumsub/id-connect/exchange', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code, codeVerifier: v, redirectUri: location.href }),
});
},
onError: (err) => console.error('sumsub-id-connect error', err),
});
PKCEを自分で生成する理由:ステージ2のトークン交換にはverifierが必要です。
ライブラリに生成を任せると、onSuccessで値を読み戻すために、ライブラリ内部のsessionStorageキー(マイナーバージョンごとに仕様が公開されていません)に依存することになります。独自のcodeChallengeを渡せば、自分で管理するキーにverifierを保存できます。同じ方法は方式2と3でも使えます。
実行可能な例:examples/oidc-button.html。
方式2 — 独自のトリガー+ライブラリのモーダル
同じライブラリを使い、トリガー要素はお客様が用意します。ライブラリはopenModal({...})でオーバーレイ内にフローを開きます。デザインシステム独自のボタンがある場合に使用してください。
実行可能な例:examples/oidc-modal.html。
方式3 — 生のOIDCリダイレクト(ライブラリなし)
OIDC認可エンドポイントに直接移動するため、ページにSumsubのスクリプトを読み込みません。CSPでサードパーティスクリプトが禁止されている場合、SSRのみの環境、または複数のプロバイダーに対応する汎用OIDCクライアントを管理している場合に適しています。
GET https://id.sumsub.com/api/snsId/oauth/authorize
?client_id=<your-client-id>
&response_type=code
&redirect_uri=<allowlisted URI>
&scope=openid+share+name
&state=<random CSRF nonce>
&code_challenge=<base64url(SHA256(code_verifier))>
&code_challenge_method=S256
&login_hint=<optional email>
code_verifier(43〜128文字、URLセーフ)を生成し、code_challenge = base64url(SHA256(verifier))を導出して、verifierを保存し(sessionStorage)、コールバック後にバックエンドへ渡します。
Sumsubが受け付けるのはcode_challenge_method=S256のみです(plainは拒否されます)。また、redirect_uriは許可リストとバイト単位で完全に一致する必要があります。
実行可能な例:examples/oidc-redirect.html。
スコープの選択
デフォルトは['openid', 'share', 'name']です。下流のロジックで実際に読み取る場合に限り、email、profile、またはoffline_access(リフレッシュトークン)を追加してください。スコープを追加すると、ユーザー向けフローで追加チェックが発生します。全項目の表:
references/scopes-and-claims.md。
ステージ 2 — バックエンド:コード → access_token
OIDC トークンエンドポイントで認可コードを交換します。このコードはブラウザーの認可フローから取得したものなので、対応するエンドポイントは標準の OIDC トークンエンドポイントです。OIDC の client_secret(client_secret_basic)で認証します。HMAC ではありません。
POST https://id.sumsub.com/api/snsId/oauth/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(<client_id>:<client_secret>)
grant_type=authorization_code
&code=<the code your frontend got>
&redirect_uri=<exact-match URI from Stage 1 — byte-for-byte>
&code_verifier=<PKCE verifier matched to the code_challenge from Stage 1>
レスポンス(有効期間 24 時間の access_token):
{
"access_token": "snd-id-con-a-...",
"refresh_token": "snd-id-con-r-...", // only with `offline_access`
"token_type": "Bearer",
"expires_in": 86400,
"id_token": "eyJhbGc..." // only with `openid` — RS256-signed
}
後で grant_type: "refresh_token" を使って更新できます。更新時に要求できるスコープは、同意時に付与されたスコープまでです。
client_secretはサーバー側に保持し、ブラウザーバンドルには決して含めないでください。交換にはclient_secret_basic/client_secret_postを使用します。HMAC 署名はしないでください。(App-Token + HMAC 認証は、ステージ 3a/4 で共有トークンと再利用の呼び出しに引き続き使用します。)
注意点
Invalid code401 の一般的な原因は 3 つあります。PKCE の不一致(verifier のハッシュが認可時に送信された challenge と一致しない)、コードの使用済み(1 回限りのため、コールバックページの再読み込みで二重に呼び出される)、またはコードの有効期限切れ(有効期間が短いため、すぐに交換してください)。redirect_uriはステージ 1 とバイト単位で一致する必要があります。末尾のスラッシュ、大文字と小文字の区別、ポート、クエリもすべて照合対象となり、一致しない場合は交換に失敗します。id_tokenの検証には、.well-known/openid-configurationのjwks_uriを使い、実績のあるライブラリ(jose、pyjwt、jjwt)を使用してください。検証されていない JWT の内容を決して信頼しないでください。
ステージ 3 — バックエンド:access_token → 共有トークン + 同意
受信者(forClientId)にスコープを限定した共有トークンを発行します。**必ず同意のフォールバック(ステージ 3b)を実装してください。**ユーザーがこの特定の forClientId との共有をまだ許可していない場合は、常に sharingAllowed: false が返されます。一般的な自分自身を受信者とするケースでは、通常、両方の同意がステージ 1 の同意画面で一度に付与されます。しかし、sharingAllowed: true の場合しか処理しない本番コードでは、ユーザーがフローに再度入ったときや、受信者の設定が異なるときに問題が発生します。
ステージ 3a — 共有トークンの発行
POST https://api.sumsub.com/resources/accessTokens/sumsubIdShareToken
{
"sumsubIdConnectToken": "<access_token from Stage 2>",
"forClientId": "<recipient clientId>",
"ttlInSecs": 1800
}
forClientId:
- 自分自身を受信者とする場合(一般的なケース):Dashboard の左上に表示されている、自分のワークスペースの
clientId。 - 第三者を受信者とする場合:パートナーの
clientId(そのパートナーは Dashboard で事前にパートナーとして登録されている必要があります)。
レスポンス:
{
"token": "_act-snsId-...",
"forClientId": "<echoed>",
"sharingAllowed": true // or false → continue to Stage 3b
}
ステージ 3b — パートナー同意の shareLink
sharingAllowed: false の場合は、同意リンクを発行してユーザーをリダイレクトします。
POST https://api.sumsub.com/resources/snsId/oauth/shareLink
Authorization: Bearer <access_token from Stage 2>
X-App-Token + X-App-Access-Ts + X-App-Access-Sig
{
"redirectUri": "<your shareLink callback URL — must be in the allowlist>",
"forClientId": "<same recipient clientId>",
"displayMode": "page",
"state": "<csrf-or-correlation-id>"
}
レスポンス:{ "link": "https://id.sumsub.com/share/<id>" } — 有効期限は 5 分です。
state をキーとして、access_token をサーバー側に保存します(デモではインメモリの Map で構いません。本番環境では Redis/暗号化 Cookie/セッションテーブルを使用してください)。ユーザーを link にリダイレクトします。同意後、Sumsub は redirectUri に ?token=<JWT> としてリダイレクトします。これは、ペイロードに state を含む署名済み RS256 JWT です(sharingAllowed: true と forClientId も含まれます)。
⚠️
stateは JWT ペイロードの中にあり、最上位の?state=クエリパラメーターにはありません。tokenJWT をデコードしてstateを読み取ります(まずjwks_uriに対して署名を検証してください)。次に、そのstateをキーとして保存済みのaccess_tokenを取得します。ステージ 3a をもう一度呼び出すと、共有トークンでsharingAllowed: trueが返されます。デコードしたペイロードの形式:{ iss, sub, aud, iat, exp, sharingAllowed, state, forClientId }。
完全なリファレンス実装:
examples/express-callback.js(state をキーとするインメモリの pendingShare Map、/share-complete ハンドラー)。
ステージ 4 — 申請者の作成
使用可能な共有トークンを使って、自分のワークスペースに申請者を作成します。必ず最初にプレビューしてください。
プレビュー(副作用なし)
GET https://api.sumsub.com/resources/api/reusableIdentity/reuse/preview
?shareToken=<token>
&levelName=<your-level>
&userId=<externalUserId>
/reuse で作成されるものと同じ ApplicantPublicDto 形式を返します。確定する前に互換性エラーを表示するために使用してください。
確定(申請者を作成)
POST https://api.sumsub.com/resources/api/reusableIdentity/reuse
?shareToken=<token>
&levelName=<your-level>
&userId=<externalUserId>
userId は、Sumsub が申請者に保存する externalUserId です。実際のユーザーごとに一意で、ユーザーには意味が分からない値であり、認証システムに紐付いています。WebSDK と同じルールです。
再利用エラーコード
すべての 400 レスポンスには、コードによる分岐に適した errorCode(整数)と errorName(ケバブケース)が含まれます。401 はトークンの有効性に関する一般的なエラーで、errorCode は含まず、description のみが含まれます。
| HTTP / errorCode | name | 原因 | 対処方法 |
|---|---|---|---|
| 401 / — | Token is invalid | 共有トークンの有効期限切れ(TTL 超過)、使用済み、または形式が不正です | ステージ 3a に従って再発行します。有効な access_token を使って /sumsubIdShareToken を再度呼び出してください |
400 / 10501 | not-in-partners-list | forClientId がワークスペースの共有パートナーとして登録されていません | ダッシュボードで受信者をパートナーとして追加します(Sumsub UI のみ。公開 API はありません) |
400 / 10502 | invalid-partner-id | 共有トークンから抽出されたパートナー ID が無効です | forClientId を再確認し、実在するパートナーに対して共有トークンを再発行します |
400 / 10503 | invalid-share-token | 共有トークンの形式が不正、または有効期限切れです | ステージ 3a に従って再発行します |
400 / 10504 | non-suitable-share-token | 指定された levelName で共有トークンを再利用できません(スコープが一致しません) | 一致するスコープで共有トークンを再発行し、同じレベルに対して再試行します |
400 / 10505 | reusable-kyc-disabled | このワークスペースでは再利用可能な KYC が無効になっています | Sumsub サポートに連絡し、ワークスペースで再利用可能な KYC を有効にしてもらいます |
400 / 10506 | reusable-kyc-not-reusable | 一般的なフォールバックです。提供者が再利用の適格条件を満たしておらず、より具体的な理由にも該当しません | ダッシュボードで提供者を確認し、別の提供者を選ぶか、WebSDK に切り替えます |
400 / 10507 | reusable-kyc-not-approved-applicant | 提供者の申請者が承認済みの状態ではありません(保留中/却下/保留措置中) | 提供者の KYC が承認されるまで待つか、承認済みステータスの提供者を使用します |
400 / 10508 | reusable-kyc-not-active-applicant | 提供者の申請者が無効です(無効化/ブロック済み) | 別の提供者を使用します。再有効化は Sumsub 側で行う必要があります |
400 / 10509 | reusable-kyc-not-kyc-moderation-type | 提供者の審査元のモデレーションタイプは再利用に適していません | 提供者には標準的な KYC モデレーションが必要です。特殊なフローは再利用できません |
400 / 10510 | reusable-kyc-not-selfie-or-identity-doc | 提供者に必要なセルフィーまたは本人確認書類がありません | その書類セットを必要としないレベルを選ぶか、提供者に再確認を依頼します |
400 / 10511 | reusable-kyc-not-selfie-liveness | 受信者のレベルではライブネスが必要ですが、提供者のセルフィーはライブネスを伴わずに撮影されています | SELFIE の videoRequired: passiveLiveness を設定していないレベルを使用するか、提供者にライブネスを伴う再確認を依頼します |
400 / 10512 | reusable-kyc-not-req-doc-overlap | 提供者と受信者のレベルで、必須の書類タイプが重複していません | 必須書類が提供者のものの部分集合となる受信者レベルを選びます |
400 / 10513 | reusable-kyc-not-compatible-doc-type | 受信者のレベルで、提供者が保持していない書類タイプが必要です | 要件の緩いレベルを使用するか、完全な書類取得のために WebSDK に切り替えます |
400 / 10514 | reusable-kyc-not-actual-poi-date | 提供者の本人確認書類(POI)が古く、再利用できません | 提供者に新しい POI を再提出してもらうか、受信者レベルの POI の有効期間を緩和します |
400 / 10515 | reusable-kyc-not-actual-poa-date | 提供者の住所確認書類(POA)が古く、再利用できません | 提供者に新しい POA を再提出してもらうか、受信者レベルの POA の有効期間を緩和します |
400 / 10516 | reusable-kyc-not-acceptable-age | 提供者が受信者レベルの年齢条件を満たしていません | 対処方法はありません。別のユーザーが必要です |
400 / 10517 | reusable-kyc-incompatible-capture-settings | 提供者と受信者の間で撮影設定(ファイルアップロードかライブカメラかなど)が一致しません | 受信者レベルの captureParams を提供者が使用した設定に合わせるか、提供者に再撮影を依頼します |
400 / 10518 | reusable-kyc-email-mismatch | 提供者のメールアドレスが、受信者の申請者にすでに登録されているメールアドレスと一致しません | 申請者の重複を解消します。異なる externalUserId を使用するか、メールアドレスを一致させます |
400 / 10519 | reusable-kyc-phone-mismatch | 提供者の電話番号が、受信者の申請者にすでに登録されている電話番号と一致しません | 10518 と同様に、重複を解消します |
400 / 10521 | reusable-kyc-inactive-sumsub-id-account | 提供者の Sumsub ID アカウントに保存済みの書類がありません(メールアドレスのみで、KYC が未完了です) | 提供者はまず id.sumsub.com で KYC を完了する必要があります。テストには、Sumsub が提供する認証済みテストアカウントを使用してください |
申請者が作成された後、applicantReviewed webhook が検証結果を示す正式なシグナルになります。WebSDK と同じ方法で設定してください。webhook の資料については | |||
sumsub-integrate-websdk を、サンドボックスでの webhook サブスクリプションの設定については | |||
sumsub-manage-webhooks を参照してください。 |
本番稼働チェックリスト
ユーザーが「本番環境に移行する準備ができました」と言った場合:
- Sumsub サポートが、本番環境の
clientId(サンドボックスとは別)で Sumsub ID Connect を有効にしている。 - 本番環境の
redirectUris(authorize と shareLink の両方のコールバック)が、本番ワークスペースの Dashboard の許可リストに登録されている。 - バックエンドのトークン交換エンドポイントで認証が必須になっている(認証済みのユーザーのみが、そのユーザー用に発行されたコードを交換できる)。
-
id_tokenの署名が本番環境の JWKS に照らして検証されている。 -
externalUserIdが実際のユーザーごとに一意で安定している(メールアドレスや表示名は使用しない)。 -
/reuseの前に/reuse/previewが呼び出され、互換性エラーが 4xx エラーとしてではなく UX 上で明らかになる。 - ステージ 3b の shareLink フローが実装・テストされている —
sharingAllowed: trueの場合だけを処理するコードをリリースしないでください。 - shareLink コールバックで使われているインメモリ状態が、実際のセッションストア(Redis/暗号化された Cookie/DB)に置き換えられている。
- App Token、secret、OIDC
client_secretが本番環境の secret ストアに保存されている(コミットされておらず、ブラウザーのバンドルにも含まれていない)。 - リフレッシュトークンを保存する場合、サーバー側のみで保存し、保存時に暗号化し、シングルテナントで運用している。
関連項目
references/scopes-and-claims.md— スコープの全一覧、トークンエンドポイントのレスポンス形式、エラーコード。scripts/preflight.sh— 前提条件の検証ツール。examples/oidc-button.html— 方法 1(createButton) — 推奨。examples/oidc-modal.html— 方法 2(openModal)。examples/oidc-redirect.html— 方法 3(PKCE を使った OIDC リダイレクトの直接実装)。examples/express-callback.js— バックエンドの全実装(ステージ 3b の同意フローを含むステージ 2〜4)。sumsub-api-auth— 認証署名のリファレンス。sumsub-create-level— ワークスペースに受取人レベルがまだない場合。sumsub-integrate-websdk— 関連スキル。申請者が作成された後は、その webhook 資料を再利用してください。