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

# Auth0 Single-Page App SDK

> このシングルページアプリケーション用のAuth0 SDKは、PKCEを用いた認可コード付与フローを使用しています。

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 Single-Page App SDKは新しいJavaScriptライブラリーで、シングルページアプリ（SPA）でAuth0を使って認証と認可を実装します。高水準のAPIを提供して、大量の詳細情報を処理しているため、作成するコードの量を低減しながら、SPAにベストプラクティスを実装することができます。

Auth0 SPA SDKは、付与とプロトコルの詳細、トークンの失効と更新、そして、トークンの保管とキャッシュをも処理します。内部では、[ユニバーサルログイン](/docs/ja-jp/universal-login)と[PKCEを用いた認可コード付与フロー](/docs/ja-jp/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce)を実装しています。

[ライブラリ](https://github.com/auth0/auth0-spa-js)と[APIドキュメント](https://auth0.github.io/auth0-spa-js/)はGitHubでホストされます。

新しいJavaScript SDKを使用中に問題やエラーが発生した場合は、[FAQ（よくある質問）をお読みになられて](https://github.com/auth0/auth0-spa-js/blob/master/FAQ.md)、問題が提示されているか確認してください。

## インストール

プロジェクトでAuth0 SPA SDKを使用するには、いくつかのオプションがあります。

* CDNから：`<script src="https://cdn.auth0.com/js/auth0-spa-js/2.0/auth0-spa-js.production.js"></script>`。詳細については、「[FAQ](https://github.com/auth0/auth0-spa-js/blob/main/FAQ.md#how-to-use-from-a-cdn)」をお読みください。
* [npm](https://npmjs.org)を使用する場合：`npm install @auth0/auth0-spa-js`
* [yarn](https://yarnpkg.com)を使用する場合：`yarn add @auth0/auth0-spa-js`

## はじめに

### クライアントを作成する

まず、`Auth0Client`クライアントプロジェクトの新しいインスタンスを作成する必要があります。`Auth0Client`インスタンスを作成してから、アプリケーションのレンダリングまたは初期化を行います。これを行うには、async/awaitメソッドまたはpromiseを使用します。クライアントには必ずインスタンスを1つだけ作成します。

`createAuth0Client`を使用すると、いくつかの処理が自動的に行われます。

* `Auth0Client`のインスタンスを作成する。
* `getTokenSilently`を呼び出し、ユーザーセッションを更新する。
* `getTokenSilently`からのエラーをすべて抑止する（`login_required`を除く）。

#### async/awaitを使用する

export const codeExample1 = `import { createAuth0Client } from '@auth0/auth0-spa-js';

const auth0 = await createAuth0Client({
  domain: '{yourDomain}',
  clientId: '{yourClientId}'
});`;

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

#### promiseを使用する

export const codeExample2 = `createAuth0Client({
  domain: '{yourDomain}',
  clientId: '{yourClientId}'
}).then(auth0 => {
  //...
});`;

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

`Auth0Client`コンストラクターを使って、クライアントを直接作成することもできます。これは、以下の場合に便利です。

* 初期化時に`getTokenSilently`への呼び出しをバイパスする
* カスタムエラー処理を行う
* SDKを同期的に初期化する

export const codeExample3 = `import { Auth0Client } from '@auth0/auth0-spa-js';

const auth0 = new Auth0Client({
  domain: '{yourDomain}',
  clientId: '{yourClientId}'
});`;

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

### ログインしてユーザー情報を取得する

次に、ユーザーがクリックしてログインを始めるボタンを作成します。

`<button id="login">クリックしてログイン</button>`

作成したボタンのクリックイベントを待ち合わせます。イベントが発生した際には、適切なログインメソッドを実行してユーザーを認証します（この例では`loginWithRedirect()`）。ユーザーが認証されたら、`getUser()`メソッドでユーザープロファイルを取得できます。

#### async/awaitを使用する

```javascript lines theme={null}
document.getElementById('login').addEventListener('click', async () => {
  await auth0.loginWithRedirect({
    authorizationParams: {
      redirect_uri: 'http://localhost:3000/'
    }
  });
  //logged in. you can get the user profile like this:
  const user = await auth0.getUser();
  console.log(user);
});
```

#### promiseを使用する

```javascript lines theme={null}
document.getElementById('login').addEventListener('click', () => {
  auth0.loginWithRedirect({
    authorizationParams: {
      redirect_uri: 'http://localhost:3000/'
    }
  }).then(token => {
    //logged in. you can get the user profile like this:
    auth0.getUser().then(user => {
      console.log(user);
    });
  });
});
```

### APIを呼び出す

APIを呼び出すには、ユーザーのアクセストークンを取得することから始めます。それから、要求にアクセストークンを使用します。この例では、`getTokenSilently`メソッドを使ってアクセストークンを取得します。

`<button id="callApi">APIを呼び出す</button>`

#### async/awaitを使用する

```javascript lines theme={null}
document.getElementById('callApi').addEventListener('click', async () => {
  const accessToken = await auth0.getTokenSilently();
  const result = await fetch('https://exampleco.com/api', {
    method: 'GET',
    headers: {
      Authorization: 'Bearer ' + accessToken
    }
  });
  const data = await result.json();
  console.log(data);
});
```

#### promiseを使用する

```javascript lines theme={null}
document.getElementById('callApi').addEventListener('click', () => {
  auth0
    .getTokenSilently()
    .then(accessToken =>
      fetch('https://exampleco.com/api', {
        method: 'GET',
        headers: {
          Authorization: 'Bearer ' + accessToken
        }
      })
    )
    .then(result => result.json())
    .then(data => {
      console.log(data);
    });
});
```

### ログアウト

ユーザーがログアウトするのにクリックするボタンを追加します。

`<button id="logout">ログアウト</button>`

```javascript lines theme={null}
$('#logout').click(async () => {
  auth0.logout({
    logoutParams: {
      returnTo: 'http://localhost:3000/'
    }
  });
});
```

### ストレージオプションを変更する

Auth0 SPA SDKはデフォルトでトークンをメモリーに保管します。ところが、ページの更新やブラウザーのタブでは永続性が途絶えてしまします。代わりに、SDKの初期化時に`cacheLocation`プロパティを`localstorage`に設定することで、トークンをローカルストレージに保存するよう選択できます。これは、Auth0のセッションCookieがアクセストークンを長期保管するのに対して、ブラウザーのプライバシー保護技術がそのアクセスを妨げる弊害を低減するのに役立ちます。

<Warning>
  トークンをブラウザーのローカルストレージに保管すると、ページが更新されても、ブラウザータブが切り替わっても、持続性を確保できるというメリットがあります。しかし、攻撃者がクロスサイトスクリプティング（XSS）によってSPAでJavaScriptを実行できるようになると、ローカルストレージに保管されているトークンを取得されてしまいます。XSS攻撃の成功につながる脆弱性は、SPAソースコード、またはSPAに含まれるサードパーティのJavaScriptコード（ブートストラップ・jQuery・Google Analyticsなど）に存在する可能性があります。

  [トークンストレージ](/docs/ja-jp/secure/tokens/token-best-practices)についての詳細をお読みください。
</Warning>

export const codeExample4 = `const auth0 = await createAuth0Client({
  domain: '{yourDomain}',
  clientId: '{yourClientId}',
  cacheLocation: 'localstorage'
});`;

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

### リフレッシュトークンのローテーションを使用する

[リフレッシュトークンをローテーション](/docs/ja-jp/secure/tokens/refresh-tokens/refresh-token-rotation)させて、サイレントモードで新しいアクセストークンを取得するように、Auth0 SPA SDKを構成できます。これによって、サイレント認証時にAuth0のセッションCookieへのアクセスを妨げるブラウザーのプライバシー保護技術を迂回するだけでなく、再利用の検出を組み込むこともできます。

このためには、初期化時に`useRefreshTokens`を`true`に設定してSDKを構成します。

export const codeExample5 = `const auth0 = await createAuth0Client({
  domain: '{yourDomain}',
  clientId: '{yourClientId}',
  useRefreshTokens: true
});

// Request a new access token using a refresh token
const token = await auth0.getTokenSilently();`;

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

リフレッシュトークンは、SPAで使用する前に[テナント用に構成される](/docs/ja-jp/secure/tokens/refresh-tokens/configure-refresh-token-rotation)必要もあります。

構成を終えると、SDKは認可ステップ中に`offline_access`スコープを要求します。さらに、`getTokenSilently`は`/oauth/token`エンドポイントを呼び出し、フレッシュトークンをアクセストークンに直接交換します。SDKはリフレッシュトークンの保管について、ストレージ設定に従います。SDKがデフォルトのメモリー内ストレージに構成されている場合、リフレッシュトークンはページが更新されると失われます。

## 使用状況

以下は、SDKでさまざまなメソッドを使った例です。3つの例でjQueryが使用されていることに注意してください。

### リダイレクトでログインする

Auth0で`/authorize`エンドポイントにリダイレクトし、[ユニバーサルログイン](/docs/ja-jp/universal-login)フローを開始します。

```javascript lines theme={null}
$('#loginRedirect').click(async () => {
  await auth0.loginWithRedirect({
    authorizationParams: {
      redirect_uri: 'http://localhost:3000/'
    }
  });
});
```

### ポップアップでログインする

ユニバーサルログインのページでポップアップ画面を使用してログインします。

```javascript lines theme={null}
$('#loginPopup').click(async () => {
  await auth0.loginWithPopup();
});
```

ユーザーが認証フローを完了するのに、デフォルトの60秒のタイムアウトよりも長くかかった場合には、認証が中断されます。この際には、コードでエラーをキャッチして、以下のいずれかを行う必要があります。

再試行し、`error.popup.close`を使ってポップアップを手動で閉じることをユーザーに求めます。

```javascript lines theme={null}
$('#loginPopup').click(async () => {
  try {
    await auth0.loginWithPopup();
  } catch {error}
  if (error instanceof auth0.PopupTimeoutError) {
    // custom logic to inform user to retry
    error.popup.close();
  }
});
```

または、`options`オブジェクトでカスタム`popup`オプションを作成します。

```javascript lines theme={null}
$('#loginPopup').click(async () => {
  const popup = window.open(
    '',
    'auth0:authorize:popup',
    'left=100,top=100,width=400,height=600,resizable'
  );
  try {
    await auth0.loginWithPopup({ popup });
  } catch {error}
  if (error instanceof auth0.PopupTimeoutError) {
    // custom logic to inform user to retry
    error.popup.close();
  }
});
```

### リダイレクトのコールバックでログインする

ブラウザーがAuth0からSPAにリダイレクトされると、ログインフローを完了するために`handleRedirectCallback`を呼び出す必要があります。

```javascript lines theme={null}
$('#loginRedirectCallback').click(async () => {
  await auth0.handleRedirectCallback();
});
```

### ユーザーの関与なくアクセストークンを取得する

非表示のiframe と`prompt=none`を使用するか、またはリフレッシュトークンをローテーションさせることで、サイレントモードで新しいアクセストークンを取得します。リフレッシュトークンは、SDKの構成時に`useRefreshTokens`が`true`に設定されている場合に使用されます。

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  SafariやBraveなど、サードパーティクッキーをブロックするブラウザーでは、リフレッシュトークンを使用せずにサイレントでアクセストークンを取得することはできません。カスタムドメインでの回避策については、「[Safariを使ったトークン更新のトラブルシューティング](/docs/ja-jp/troubleshoot/authentication-issues/renew-tokens-when-using-safari)」をお読みください。
</Callout>

メモリー内ストレージ（デフォルト）の設定でリフレッシュトークンが使用されると、新しいトークンは対応しているブラウザーのウェブワーカー（Web Worker）を使って取得されます。

```javascript lines theme={null}
$('#getToken').click(async () => {
  const token = await auth0.getTokenSilently();
});
```

`getTokenSilently()`メソッドを使用する場合は、**［Allow Skipping User Consent（ユーザー同意をスキップさせる）］** が[DashboardのAPI設定](https://manage.auth0.com/#/apis)で有効になっている必要があります。さらに、ユーザー同意を['localhost'でスキップすることはできません](/docs/ja-jp/get-started/applications/third-party-applications/user-consent-and-third-party-applications)。

### ポップアップでアクセストークンを取得する

アクセストークンはポップアップでも取得することができます。`getTokenSilently`とは違って、サードパーティのCookieがデフォルトで阻止されているブラウザーでも動作します。

```javascript lines theme={null}
$('#getTokenPopup').click(async () => {
  const token = await auth0.getTokenWithPopup({
    authorizationParams: {
      audience: 'https://mydomain/api/',
      scope: 'read:rules'
    }
  });
});
```

### 異なるオーディエンスにアクセストークンを取得する

オプションは、ユーザー認証時に要求された、異なるオーディエンスとそのスコープを持つアクセストークンを取得する`getTokenSilently`に渡すこともできます。

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  これは、リフレッシュトークンを使わない場合（`useRefreshTokens: false`）にのみ有効です。リフレッシュトークンは、ユーザーの認証時に要求された特定のオーディエンスとスコープにバインドされているためです。
</Callout>

```javascript lines theme={null}
$('#getToken_audience').click(async () => {
  const differentAudienceOptions = {
    authorizationParams: {
      audience: 'https://mydomain/another-api/',
      scope: 'read:rules',
      redirect_uri: 'http://localhost:3000/callback.html'
    }
  };
  const token = await auth0.getTokenSilently(differentAudienceOptions);
});
```

### ユーザーを取得する

認証されたユーザーのプロファイルデータを取得するには、`getUser`メソッドを呼び出します。

```javascript lines theme={null}
$('#getUser').click(async () => {
  const user = await auth0.getUser();
});
```

### IDトークンのクレームを取得する

認証されたユーザーのIDトークンにあるクレームを取得するには、`getIdTokenClaims`メソッドを呼び出します。

```javascript lines theme={null}
$('#getIdTokenClaims').click(async () => {
  const claims = await auth0.getIdTokenClaims();
  // if you need the raw id_token, you can access it
  // using the __raw property
  const id_token = claims.__raw;
});
```

### ログアウト（デフォルト）

ログアウトのアクションを開始するには、`logout`メソッドを呼び出します。

```javascript lines theme={null}
$('#logout').click(async () => {
  auth0.logout({
    logoutParams: {
      returnTo: 'http://localhost:3000/'
    }
  });
});
```

### クライアントIDなしでログアウトする

クライアントIDが指定されていないログアウトのアクションを開始するには、`logout`メソッドを呼び出し、`clientId: null`を含めます。

```javascript lines theme={null}
$('#logoutNoClientId').click(async () => {
  auth0.logout({
    clientId: null,
    logoutParams: {
      returnTo: 'http://localhost:3000/'
    }
  });
});
```

## もっと詳しく

* [アクセストークンを検証する](/docs/ja-jp/secure/tokens/access-tokens/validate-access-tokens)
