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

# 機密アプリケーションからパスワードレスエンドポイントへ移行する

> 要求にクライアントシークレットを使わない機密アプリケーションからの/passwordless/startエンドポイントの使用がAuth0で廃止されることに関して、ユーザーに必要な移行手順について説明します。

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>;
};

アプリケーションに代わった呼び出しをAuth0が認証できない場合に、機密アプリケーションから`/passwordless/start`エンドポイントを使用することが廃止されます。

<Tooltip data-tooltip-id="react-containers-DefinitionTooltip-0" href="/docs/ja-jp/glossary?term=oath2" tip="OAuth 2.0: 認可プロトコルとワークフローを定義する認可フレームワーク。" cta="用語集の表示">OAuth</Tooltip>は、シークレットを保管できるアプリケーションに「機密」という用語を使用します。これらはAuth0で「通常のWebアプリケーション」と呼ばれ、バックエンドアプリからのWebページを処理します。シングルページアプリケーションとネイティブアプリケーションは「公開アプリケーション」とみなされるため、この変更による影響はありません。

Auth0が`/passwordless/start`に対する呼び出しを認証できるのは、パラメーターに`client_secret`が含まれているか、呼び出しがユニバーサルログインのカスタムログインページか行われて`state`パラメーターが転送される場合です。

## 影響のある機能

使用しているアプリケーションのいずれかが現在、Webアプリケーションからパスワードレス認証を始めるために、`/passwordless/start`エンドポイントを直接呼び出して、`client_secret`をパラメーターとして送っていない場合は、この廃止がユーザーに影響します。

ユニバーサルログインページを使ってパスワードレス認証を実装し、Auth0ライブラリーの初期化にデフォルトの方法を変更した場合にも、影響を受ける可能性があります。

影響があるかを確認するには、[テナントログ](https://manage.auth0.com/#/logs)を調べるか、「Deprecation Notice（廃止通知）」でフィルタリングして「Enforce client authentication for <Tooltip data-tooltip-id="react-containers-DefinitionTooltip-0" href="/docs/ja-jp/glossary?term=passwordless" tip="パスワードレス: 最初の要素としてパスワードに依存しない認証の形式。" cta="用語集の表示">passwordless</Tooltip> connections（パスワードレス接続のクライアント認証を強制する）」というログを確認します。この検索は、「`type:depnote AND description:*passwordless*`」というクエリを使って直接行うこともできます。この特定のクエリはパブリッククラウドのテナントにのみ機能します。プライベートクラウドのログは説明フィールドで検索できないため注意してください。

## アクション

アプリケーションを正しく認証することなく、`/passwordless/start`エンドポイントを呼び出している場合には、以下を行います。

* 以下の指示に従って、`/passwordless/start`を正しく呼び出すようにコードを調整する
* 変更が正しく行われたこと、「Enforce client authentication for passwordless connections（パスワードレス接続のクライアント認証を強制する）」という廃止ログが生成されていないことを[テナントログ](https://manage.auth0.com/#/logs)で確認する
* **［Advanced Tenant Settings（高度なテナント設定）］** の **［Migrations（移行）］** セクションで、**［Enforce client authentication for passwordless connections（パスワードレス接続のクライアント認証を強制する）］** を有効にします。

影響を受けるユースケースもいくつかありますが、それぞれでの移行パスは比較的単純です。

### バックエンドからのAPI呼び出し

バックエンドから`/passwordless/start`エンドポイントへの呼び出しにはすべて、パラメーターにクライアントシークレットを含める必要があります。

`/passwordless/start`に直接POST要求を行うには、`client_secret`をペイロードの一部として含めます。

export const codeExample = `POST https://{yourDomain}/passwordless/start
    Content-Type: application/json
    {
      "client_id": "{yourClientId}",
      "client_secret": "{yourClientSecret}",
      "connection": "email|sms",
      "email": "{userEmailAddress}", //set for connection=email
      "phone_number": "{userPhoneNumber}", //set for connection=sms
      "send": "link|code",
      "authParams": { 
          "scope": "openid",
          "state": "{yourState}"
        }
      }`;

<AuthCodeBlock children={codeExample} language="javascript" />

SDKを使用している場合には、パスワードレスフローを開始するメソッドにパラメーターを追加します。これはSDKごとに異なり、すべてのSDKが更新されているわけではありません。更新されていないSDKを使用している場合は、更新されるまで、HTTP呼び出しを直接行っても構いません。

### ユニバーサルログインページのページAuth0.jsまたはLock.js

Webアプリケーションのパスワードレス認証にユニバーサルログインページが使用されている場合は、Lock.jsまたはAuth0.js使って`/passwordless/start`エンドポイントを呼び出しています。

クライアントシークレットはWebページに保管できないため、呼び出しを認証するには、ユニバーサルログインページで受け取った`state`パラメーターを`/passwordless/start`エンドポイントに転送する必要があります。そのパラメーターは、カスタムログインページの`config.internalOptions`フィールドに保管されます。

ログインページをカスタマイズするためのデフォルトのテンプレートは、Lock.jsまたはauth0.jsを初期化する際に以下のように使用します。

```javascript lines theme={null}
var lock = new Auth0Lock(
  config.clientID, 
  config.auth0Domain, 
  {
    auth: {
      // .. other fields set
      params: {
       scope: config.internalOptions.scope,
       _csrf: config.internalOptions._csrf,
       state: config.internalOptions.state,
      }
    }
  });
```

```javascript lines theme={null}
var params = Object.assign({
    scope: config.internalOptions.scope,
    _csrf: config.internalOptions._csrf,
    state: config.internalOptions.state,
  }, {
    // ...auth params
  });

var webAuth = new auth0.WebAuth(params);
```

カスタムページの実装で、そのコードが削除されていないことを確認してください。

### Webアプリケーションのクライアントから/passwordless/startを呼び出す

`/passwordless/start`エンドポイントを呼び出すのに、通常のWebアプリからページにJavaScriptを使用している（そのページのAuth0.jsを使うなど）場合、JavaScriptを使った呼び出しにはクライアントシークレットを指定できません。使用しているアプリケーションがこれに該当する場合は、`/passwordless/start`の呼び出しがフロントエンドからではなく、Webアプリケーションのバックエンドから行われるように、アプリを変更する必要があります。

### レート制限

`/passwordless/start`にクライアント認証を追加すると、要求で送信されたヘッダーをAuth0が信頼できるようになります。`auth0-forwarded-for`ヘッダーを設定すると、ログにIPアドレスが表示され、攻撃防御のために利用されます。

認証された`/passwordless/start`要求は、通常の認証済みのAPI要求として扱われ、認証APIのグローバルレート制限が適用されます。
