> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript認証クイックスタート

> JavaScriptで、有効化済みのDidit Authenticationアプリケーションをホスト型サインインに接続します。PKCE、コールバック検証、セッション確認、ログアウトに対応します。

> [!WARNING]
>
> Authenticationは新しい機能です。このホスト型フローのサンプルは、Authenticationを有効にしたアプリケーションで使用してください。`@didit-protocol/auth`パッケージはまだ公開されていません。以下のパッケージAPIはプレビューであり、インストールして使えるクイックスタートではありません。

## ホスト型サインインを設定する

サンドボックスアプリケーションに、正確なコールバックURLとWebオリジンを登録します。[概要](https://docs.didit.me/ja/authentication/overview.md)で説明しているとおり、コンソールからサインインオリジン(`https://<slug>.sandbox.auth.didit.me`)をコピーしてください。このサンプルはブラウザの暗号APIを使用するため、HTTPSが必要です(サンドボックスではlocalhostも使用できます)。登録する内容については[ローカル開発](https://docs.didit.me/ja/authentication/overview.md#ローカル開発)を参照してください。

`state`とPKCEベリファイアはアプリケーションが管理します。パスワード、メール、パスキー、電話番号、SSO、必須のMFAの各画面はホスト型サインインが管理します。このコードにAPIキーを含めてはいけません。

```javascript auth.js theme={null}
// Replace both values with your registered application configuration.
const AUTH_BASE = "https://YOUR_SLUG.sandbox.auth.didit.me/";
const REDIRECT_URI = "https://YOUR_APP_ORIGIN/auth/callback";
const PENDING = "didit.auth.pending";
let tokens = null;

function base64url(bytes) {
  return btoa(String.fromCharCode(...bytes))
    .replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}

export async function signIn() {
  const verifier = base64url(crypto.getRandomValues(new Uint8Array(32)));
  const state = base64url(crypto.getRandomValues(new Uint8Array(32)));
  const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
  sessionStorage.setItem(PENDING, JSON.stringify({ verifier, state, startedAt: Date.now() }));
  const url = new URL("sign-in", AUTH_BASE);
  url.search = new URLSearchParams({
    redirect_uri: REDIRECT_URI,
    state,
    code_challenge: base64url(new Uint8Array(digest)),
    code_challenge_method: "S256",
  }).toString();
  window.location.assign(url.href);
}

export async function handleCallback() {
  const query = new URLSearchParams(window.location.search);
  const saved = sessionStorage.getItem(PENDING);
  sessionStorage.removeItem(PENDING);
  history.replaceState(null, "", window.location.pathname);
  if (!saved) throw new Error("Start sign-in again.");
  const pending = JSON.parse(saved);
  if (query.get("state") !== pending.state || Date.now() - pending.startedAt > 600000) {
    throw new Error("Invalid or expired sign-in. Start again.");
  }
  if (query.has("error") || !query.get("code")) throw new Error("Sign-in was not completed.");
  const response = await fetch(new URL("token/", AUTH_BASE), {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      grant_type: "authorization_code",
      code: query.get("code"),
      code_verifier: pending.verifier,
      redirect_uri: REDIRECT_URI,
    }),
  });
  if (!response.ok) throw new Error("Code exchange failed. Start sign-in again.");
  tokens = await response.json();
  return getSession();
}

export async function getSession() {
  if (!tokens) return null;
  const response = await fetch(new URL("session/", AUTH_BASE), {
    headers: { Authorization: `Bearer ${tokens.access_token}` },
    cache: "no-store",
  });
  if (!response.ok) {
    tokens = null;
    throw new Error("Session check failed. Sign in again.");
  }
  return response.json();
}

export async function signOut() {
  const current = tokens;
  tokens = null;
  if (!current) return;
  const response = await fetch(new URL("session/", AUTH_BASE), {
    method: "DELETE",
    headers: { Authorization: `Bearer ${current.access_token}` },
  });
  if (response.status !== 204) throw new Error("Local state cleared; server logout failed.");
}
```

サインインボタンから`signIn()`を呼び出します。登録済みのコールバックページでは`handleCallback()`を1回だけ呼び出し、読み込み中の状態を表示し、失敗した場合はそのエラーを表示します。現在のユーザーの取得には`getSession()`を、ログアウトには`signOut()`を使用します。コールバックは、リクエストを送信する前にアドレスバーからコードを削除します。

この最小限のサンプルではトークンをメモリに保持するため、ページの再読み込み後やアクセストークンの期限切れ後には再度サインインが必要です。永続的なセッションが必要な場合は、バックエンドとセキュアなCookieを使用するか、直列化した[リフレッシュローテーション](https://docs.didit.me/ja/authentication/tokens-and-jwks.md)を実装してください。リフレッシュトークンをURLやログに含めてはいけません。フロントエンドでのセッション確認は表示を制御するだけです。バックエンドは、保護されたすべてのリクエストで呼び出し元を検証する必要があります。

## Authentication SDKのリリースプレビュー

予定されている`@didit-protocol/auth`のコアは、`createDiditAuth({publishableKey})`、`signIn()`、`handleRedirectCallback()`、`getSession()`、`getToken()`、`onAuthStateChange`、`signOut()`を公開し、アイデンティティには`vendorData`が含まれます。また、デバイスシグナルの自動付与と、`verifyToken()`を備えたサーバー用エントリーポイントの追加を予定しています。

公開可能キーは、`pk_live_`(本番アプリケーション)または`pk_test_`(サンドボックスアプリケーション)の後に、アプリケーションのオリジンをパディングなしでbase64urlエンコードした文字列が続く形式です。
SDKはAPI呼び出しをそのオリジンに送信します。
このキーは公開情報です。アプリケーションを識別するためのものであり、シークレットではありません。

### プレビューにおけるステップアップと再認証

* `stepUp({ action, amount?, currency?, redirectUri? })`は、アプリケーションの`POST step-up/`を呼び出し、`action`に本人確認が必要かどうかを問い合わせます。
  `action`は`payout`、`bank`、`contact`のいずれかで、payoutには`amount`が必要です。
  ステップアップルールのいずれかが適用される場合は、Diditが返す検証ページに遷移します。
* `handleStepUpCallback(url?)`は、ユーザーが戻ってくるページで実行します。
  `?step_up=<id>`を読み取り、アドレスバーから削除したうえで、`GET step-up/{id}/`で結果を取得します。
* `reauthenticate({ method? })`は、同じユーザーを再度サインインさせます。ホスト型ページ(`method: "redirect"`、デフォルト)またはパスキー(`method: "passkey"`、アプリケーションのDiditサインインドメイン上でのみ)を使用します。
  ホスト型ページの後は、`handleRedirectCallback()`で完了させます。
  別のユーザーが完了した場合は`step_up_user_mismatch`で拒否され、元のセッションは維持されます。

どちらのステップアップメソッドも`{ id, status, approved, rule, method }`で解決されます。`status`は`not_required`、`pending`、`approved`、`review`、`declined`、`expired`のいずれかです。
`redirectUri`のデフォルトはクライアントのリダイレクト先アドレスで、アプリケーションに登録済みのリダイレクト先アドレスのいずれかと完全に一致する必要があります。確認が必要な場合、Diditはそれ以外のアドレスを拒否します。
ブラウザから報告された結果は改ざんされる可能性があるため、バックエンドはステップアップに基づいて処理を行う前に、ユーザーのアクセストークンを使って`GET step-up/{id}/`でステップアップを再度取得します。

ヘッドレスサインインでは、アプリケーションの保護ルールに該当する場合に`protection_required`が返されることもあります。
その場合、ユーザーはDiditからメールで届いたコード(`protection.verify({ code })`)またはパスキー(`protection.passkey()`)で完了させます。`methods`には、そのどちらを使用できるかが示されます。

推測したバージョンをインストールしたり、推測したコールバックオプションに基づいてコードを書いたりしないでください。ホスト型のサンプルを置き換える前に、公開されたパッケージのエクスポート、issuer、キーの設定を確認してください。パスワード、メールコード、マジックリンク、パスキー、電話番号、MFA、ソーシャルサインイン、ステップアップ、エージェントの各方式は、そのリリースでサポートされるAPIに依存します。

## 他のプロダクトを追加する

バックエンドはアクセストークンを検証し([トークンとJWKS](https://docs.didit.me/ja/authentication/tokens-and-jwks.md)を参照)、その`vendor_data`を読み取ります。[検証セッションの作成](https://docs.didit.me/ja/sessions-api/create-session.md)や[取引トークンの発行](https://docs.didit.me/ja/transaction-monitoring/sdk-transaction-submission.md)の際に、その値を`vendor_data`として使用してください。サインインに成功しても、いずれかのプロダクトがユーザーを承認したことにはなりません。

リリース前に、有効化済みのサンドボックスアプリケーションで、サインアップ、再度のサインイン、キャンセル、stateの不一致、コードの再利用、パスワードを忘れた場合、MFA、期限切れ、ログアウトを試してください。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.