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

> Auth0 API を使用したパスワードレス認証の実装方法を説明します。

# パスワードレス API の使用

export const ReleaseStageNotice = ({feature, stage, plans, contact, terms}) => {
  const stageTextMap = {
    "beta": "Beta",
    "ea": "早期アクセス"
  };
  const stageText = stageTextMap[stage] || "製品リリース段階";
  const prsLink = "/docs/troubleshoot/product-lifecycle/product-release-stages";
  const linkify = (text, url) => {
    return <a href={url} target="_blank" rel="noreferrer" class="link">{text}</a>;
  };
  const includeDetails = (plans, contact, terms) => {
    const hasDetails = terms || plans || contact;
    if (!hasDetails) return null;
    return <span data-as="p">
            {plans && <>この機能は{linkify(`${plans}プラン`, "https://auth0.com/pricing")}でご利用いただけます。 </>}
            {contact && "参加をご希望の場合は、" + contact + "までお問い合わせください。 "}
            {terms && <>この機能を使用することにより、Oktaの該当する無料トライアル規約および{linkify("Master Subscription Agreement", "https://www.okta.com/legal")}に同意したものとみなされます。</>}
        </span>;
  };
  return <Warning>
            <span data-as="p">
                <strong>{feature}機能は現在、{linkify(stageText, prsLink)}です。</strong>
            </span>

            {includeDetails(plans, contact, terms)}
        </Warning>;
};

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASKED*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

<Tooltip tip="パスワードレス: 第1の認証要素としてパスワードに依存しない認証方式。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=Passwordless">パスワードレス</Tooltip> API は、次の 2 つのシナリオで使用できます。

* <Tooltip tip="Universal Login: ユーザーの本人確認のために、アプリケーションから Auth0 の認可サーバーでホストされている Universal Login にリダイレクトします。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=Universal+Login">Universal Login</Tooltip> を実装し、Auth0 と連携するために auth0.js を使ってログインページをカスタマイズしたい場合。
* アプリケーションにログインフローを埋め込みたい場合。

さまざまなシナリオで Universal Login 向けのパスワードレスや埋め込みログインを実装する方法について詳しくは、[Universal Login を使用したパスワードレス認証](/docs/ja-jp/authenticate/passwordless/implement-login/universal-login) または [埋め込みログインを使用したパスワードレス認証](/docs/ja-jp/authenticate/passwordless/implement-login/embedded-login) を参照してください。

<div id="passwordless-endpoints">
  ## パスワードレス エンドポイント
</div>

<div id="post-passwordlessstart">
  ### POST /passwordless/start
</div>

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  アプリケーションの**設定**にある **Advanced Settings** > **Grant Types** で、[Auth0 Dashboard > アプリケーション > アプリケーション](https://manage.auth0.com/#/applications) から **Passwordless OTP** グラントを有効にする必要があります。
</Callout>

[POST /passwordless/start](https://auth0.com/docs/api/authentication#get-code-or-link) エンドポイントを呼び出すと、クラシックログインと埋め込みログインの両方でパスワードレス認証プロセスを開始できます。

エンドポイントに指定するパラメーターに応じて、Auth0 は次のいずれかを送信してユーザー検証プロセスを開始します。

* メールまたは SMS による使い捨てコード
* メールによる使い捨てリンク

API 呼び出しは次の構造に従う必要があります。

export const codeExample1 = `POST https://{yourDomain}/passwordless/start
Content-Type: application/json
{
  "client_id": "{yourClientID}",
  "client_secret": "{yourClientSecret}", // 従来型Webアプリケーションの場合
  "connection": "email|sms",
  "email": "{email}", // connection=email の場合に指定
  "phone_number": "{phoneNumber}", // connection=sms の場合に指定
  "send": "link|code", // null の場合は既定で link
  "authParams": { // 追加する認証パラメータ
    "scope": "openid",     // マジックリンクをリクエストする際に使用
    "state": "{yourState}"  // マジックリンクをリクエストする際、またはカスタムログインページ利用時に使用
  }
}`;

<AuthCodeBlock children={codeExample1} language="json" />

マジックリンクを使用する場合、ユーザーには Authentication API によって生成されたリンクが送信されます。ユーザーがそのリンクをクリックすると、\{`yourAuth0Tenant}.auth0.com/passwordless/verify-redirect` への呼び出しがトリガーされます。Auth0 はユーザーをアプリケーションにリダイレクトし、ユーザーはログインされます。

コードを使用する場合、アプリケーションはそのコードの入力を求める必要があります。その後、そのコードを認証トークンと交換するために、`/oauth/token` エンドポイントまたは auth0.js SDK の `passwordlessLogin` メソッドを使用します。

<div id="post-oauthtoken">
  ### POST /oauth/token
</div>

ネイティブアプリケーションまたは従来型Webアプリケーションにパスワードレスを実装する場合、OTPコードを認証トークンに交換するために `/oauth/token` を使用する必要があります。このエンドポイントはシングルページアプリケーションからは使用できません。

これを行うには、まず [Auth0 Dashboard > アプリケーション > アプリケーション](https://manage.auth0.com/#/applications) のアプリケーションの **設定** にある **Advanced Settings** > **Grant Types** で、**Passwordless OTP** グラントを有効にする必要があります。

ユーザーはOTPコードを受け取り、ネイティブアプリケーションまたは Web アプリケーションでその入力を求められます。ユーザーがコードを入力したら、以下のパラメーターを指定して `/oauth/token` エンドポイントを呼び出すことで、認証フローを完了できます。

export const codeExample2 = `POST https://{yourAuth0Domain}/oauth/token
Content-Type: application/json
{
  "grant_type" : "http://auth0.com/oauth/grant-type/passwordless/otp",
  "client_id": "{yourAuth0ClientID}",
  "client_secret": "{yourClientSecret}", // web app のみ。Native アプリには client secret はありません
  "username":"<メールアドレス>", // または "<電話番号>"
  "otp": "CODE",
  "realm": "email", // または "sms" 
  "audience" : "your-api-audience", // 特定の API 用のアクセストークンが必要な場合
  "scope": "openid profile email" // 必要なスコープを指定します
}`;

<AuthCodeBlock children={codeExample2} language="json" />

問題なく進めば、Auth0 は次のようなレスポンスを返します。

```json lines theme={null}
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token":"eyJz93a...k4laUWw",
"refresh_token":"GEbRxBN...edjnXbL",
"id_token":"eyJ0XAi...4faeEoQ",
"token_type":"Bearer",
"expires_in":86400
}
```

その後、<Tooltip tip="ID トークン: リソースへのアクセス用ではなく、クライアント自体のための資格情報です。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=ID+Token">ID トークン</Tooltip>をデコードしてユーザーに関する情報を取得するか、<Tooltip tip="アクセストークン: API へのアクセスに使用される、opaque な文字列または JWT 形式の Authorization 資格情報です。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=Access+Token">アクセストークン</Tooltip>を使って通常どおり API を呼び出せます。

<div id="using-auth0js">
  ## Auth0.js の使用
</div>

シングルページアプリケーションや、カスタマイズした Universal Login ページでパスワードレス認証を実装する場合は、[Auth0.js とその passwordlessLogin メソッドを使用してください](/docs/ja-jp/libraries/auth0js)。実装は複雑なため、API を直接呼び出すのではなく、ライブラリを使用することをお勧めします。

<div id="rate-limiting-in-passwordless-endpoints">
  ## パスワードレスのエンドポイントにおけるレート制限
</div>

Auth0 のレート制限と <Tooltip tip="攻撃対策: Auth0 が攻撃を検出して緩和するために提供する機能です。これには、総当たり攻撃対策、不審な IP スロットリング、漏えいパスワードの検知、ボット検出、適応型多要素認証が含まれます。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=attack+protection">攻撃対策</Tooltip> 機能は、API 呼び出しを行っているマシンの IP のみを考慮します。API 呼び出しがバックエンドサーバーから行われる場合、通常は Auth0 にサーバーではなくエンドユーザーの IP を考慮させたいはずです。

Auth0 では、API 呼び出しで `auth0-forwarded-for` ヘッダーを指定できますが、これが考慮されるのは次の場合に限られます。

* API 呼び出しが機密アプリケーションに対して行われる場合。
* API 呼び出しに <Tooltip tip="クライアントシークレット: クライアント（アプリケーション）が認可サーバーで認証するために使用する Secret です。クライアントと認可サーバーだけが知っている必要があり、推測されないよう十分にランダムでなければなりません。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=client+secret">クライアントシークレット</Tooltip> が含まれている場合。
* **Trust <Tooltip tip="トークンエンドポイント: 認可サーバー上で、プログラムからトークンを要求するために使用されるエンドポイントです。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=Token+Endpoint">トークンエンドポイント</Tooltip> IP Header** トグルがオンになっている場合。

詳しくは、[リソース所有者パスワードフローと攻撃対策でよくある問題を回避する](/docs/ja-jp/get-started/authentication-and-authorization-flow/resource-owner-password-flow/avoid-common-issues-with-resource-owner-password-flow-and-attack-protection) をご覧ください。

<div id="customize-mfa">
  ## MFA をカスタマイズする
</div>

<ReleaseStageNotice feature="Resource Owner Password Grant、埋め込み、またはリフレッシュトークンのフローでカスタマイズ可能な MFA" stage="ea" terms="true" contact="Auth0 Support" />

<Tooltip tip="多要素認証 (MFA): SMS 経由のコードなど、ユーザー名とパスワードに加えて認証要素を使用するユーザー認証プロセスです。" cta="用語集を表示" href="/docs/ja-jp/glossary?term=MFA">MFA</Tooltip> は、パスワードレス API を使用してカスタマイズできます。アプリケーションがアクセストークンをリクエストするために `/oauth/token` エンドポイントを呼び出すと、<Tooltip tip="認可サーバー: ユーザーのアクセス範囲の境界を定義するのに役立つ集中管理サーバーです。たとえば、認可サーバーはユーザーが利用できるデータ、タスク、機能を制御できます。" cta="用語集を表示" href="/docs/ja-jp/glossary?term=authorization+server">認可サーバー</Tooltip> は `mfa_required` エラーを返します。このエラーには次が含まれます。

* 登録とチャレンジのために MFA API を呼び出す際に必要な `mfa_token`。

* `mfa_requirements` パラメーター。チャレンジでアプリケーションがサポートする認証要素の `type` を示します。

```json lines theme={null}
{
  "error": "mfa_required",
  "error_description": "Multifactor authentication required",
  "mfa_token": "Fe26...Ha",
  "mfa_requirements": {
    "challenge": [
      { "type": "otp" },
      { "type": "push-notification" },
      { "type": "phone" },
      { "type": "recovery-code" }
    ]
  }
}
```

`mfa_token` を使用して [`mfa/authenticator`](https://auth0.com/docs/api/authentication/muti-factor-authentication/list-authenticators) エンドポイントを呼び出し、ユーザーが登録済みの認証要素をすべて一覧取得したうえで、アプリケーションがサポートする `type` と一致するものを特定します。チャレンジを発行するには、一致する `authenticator_type` も取得する必要があります:

```json lines theme={null}
[
  {
    "type": "recovery-code",
    "id": "recovery-code|dev_qpOkGUOxBpw6R16t",
    "authenticator_type": "recovery-code",
    "active": true
  },
  {
    "type": "otp",
    "id": "totp|dev_6NWz8awwC8brh2dN",
    "authenticator_type": "otp",
    "active": true
  }
]
```

[`request/mfa/challenge`](https://auth0.com/docs/api/authentication/muti-factor-authentication/request-mfa-challenge) エンドポイントを呼び出して、MFA チャレンジを必須にします。

Auth0 Actions を使用すると、MFA フローをさらにカスタマイズできます。詳しくは、[Actions トリガー: post-challenge - API オブジェクト](/docs/ja-jp/customize/actions/explore-triggers/password-reset-triggers/post-challenge-trigger/post-challenge-api-object) をお読みください。
