> ## 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.

# OIDC バックチャネルログアウト

> Auth0 の OIDC Back-Channel Logout 機能について説明します。

Auth0 は、Enterprise プランを契約しているすべてのテナントで [OpenID Connect Back-Channel Logout 1.0 specification](https://openid.net/specs/openid-connect-backchannel-1_0.html#Backchannel) をサポートしています。

この仕様では、<Tooltip tip="IDトークン: リソースへのアクセスではなく、クライアント自体のための資格情報です。" cta="用語集を見る" href="/ja/docs/glossary?term=ID+tokens">IDトークン</Tooltip> に含まれるセッション ID (`sid`) と ログアウトトークン を使用して、バックチャネル通信によるセッション終了を連携させます。異なるセッション ID は、テナント内のユーザーエージェントまたはデバイスごとの個別のセッションを表します。ログアウトトークン は、ログアウト対象のエンドユーザーとセッションを識別します。

<div id="back-channel-communications">
  ## バックチャネル通信
</div>

Back-Channel Logout を使用するには、アプリケーションで、テナントサーバーからアクセス可能な Back-Channel Logout URI を公開する必要があります。この URI は、アプリケーションが ログアウトトークン を含むリクエストを受信するエンドポイントです。アプリケーションがこのリクエストを受信した場合は、トークン内のクレームに一致するローカルセッション状態をクリアする必要があります。

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  バックチャネルログアウトを機能させるには、アプリケーションがバックチャネル通信を受信できる必要があります。
</Callout>

<div id="tokens-in-oidc-back-channel-logout-communications">
  ### OIDC バックチャネルログアウト通信におけるトークン
</div>

バックチャネル経由で通信が行われる場合、アプリケーションはどのセッションを終了すべきかを判断するために<Tooltip tip="セッション Cookie: 存在すると、ユーザーが認証済みと見なされるエンティティ。" cta="用語集を表示" href="/ja/docs/glossary?term=session+cookies">セッションクッキー</Tooltip>に依存することはできません。代わりに、このサービスは IDトークンとログアウトトークンに含まれる共有セッション識別子 (`sid`) を使用します。

エンドユーザーがログイン時に Auth0 で正常に認証されると、<Tooltip tip="認可サーバー: ユーザーのアクセス境界の定義に関与する集中管理サーバー。たとえば、認可サーバーはユーザーが利用できるデータ、タスク、機能を制御できます。" cta="用語集を表示" href="/ja/docs/glossary?term=authorization+server">認可サーバー</Tooltip>がアクセストークンとIDトークンを発行します。ログアウトトークンは、ログアウト操作やセッションの失効などでセッションが破棄されたときに生成されます。IDトークンとログアウトトークンの両方には、アプリケーションが Back-Channel Logout ワークフローを実行するために必要なクレームが含まれます。クレームの詳細については、[JSON Web Token Claims](/ja/docs/secure/tokens/json-web-tokens/json-web-token-claims) を参照してください。

<Frame>
  <img src="https://mintcdn.com/translations/MV7tE-x71x8RWRES/docs/images/cdy7uua7fh8z/5jQ5HogFNeD9tqUGEJuJHE/663f1f52b285f7019fd1157f5a26caf0/2023-09-29_09-32-00.png?fit=max&auto=format&n=MV7tE-x71x8RWRES&q=85&s=2b7fbbaf0b09b46cf3f64b42509b7bc7" alt="バックチャネルログアウトのワークフロー" width="849" height="324" data-path="docs/images/cdy7uua7fh8z/5jQ5HogFNeD9tqUGEJuJHE/663f1f52b285f7019fd1157f5a26caf0/2023-09-29_09-32-00.png" />
</Frame>

1. ログイン - ユーザー認証中に、Auth0 テナントは IDトークンに `sid` を追加します。
2. ログイン - アプリケーションは受け取ったセッション識別子を独自のセッションストアに保存し、アプリケーション固有のセッションに関連付けます。
3. ログアウト - IdP が事前登録されたログアウトコールバック URL を呼び出し、このエンドポイントにログアウトトークンを POST します。このトークンには、他のパラメーターとともに `user_id` (`sub`) と `sid` が含まれます。
4. ログアウト - アプリケーションのバックエンドは、OIDC 仕様に従ってログアウトトークンを検証し、`sid` を抽出する必要があります。その後、バックエンドはこのトークンを使用して、その識別子に関連付けられたセッションを特定し、必要に応じて終了できます。

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  ログアウトが成功した場合、想定されるレスポンスは `HTTP 200` です。誤ったリクエストや不正な形式のリクエストを示す `HTTP 400` を受け取った場合は、トラブルシューティングのヒントを利用できます。詳細については、[Configure Back-Channel Logout](/ja/docs/authenticate/login/logout/back-channel-logout/configure-back-channel-logout) を参照してください。
</Callout>

<div id="how-it-works">
  ### 仕組み
</div>

このサンプルのユースケースでは、複数のアプリケーションで Back-Channel Logout がどのように機能するかを示します。

<Frame>
  <img src="https://mintcdn.com/translations/MV7tE-x71x8RWRES/docs/images/cdy7uua7fh8z/54mbNobsvLec0A2tz0DXUG/99ce79c9e93ffe526472d6250373778c/2023-06-20_09-39-12.png?fit=max&auto=format&n=MV7tE-x71x8RWRES&q=85&s=0af402480a71445e216e9cc5427d3aca" alt="複数アプリケーションでの Back-channel logout のユースケース" width="2476" height="2562" data-path="docs/images/cdy7uua7fh8z/54mbNobsvLec0A2tz0DXUG/99ce79c9e93ffe526472d6250373778c/2023-06-20_09-39-12.png" />
</Frame>

1. アプリケーションの設定時に、Application A は Back-Channel Logout URI を Auth0 に登録します。
2. アプリケーションの設定時に、Application B は Back-Channel Logout URI を Auth0 に登録します。

   <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
     OIDC Back-Channel Logout URL は、次の要件を満たす必要があります。

     * IdP からアクセスできること
     * TLS で暗号化されたエンドポイントを使用すること
     * [ログアウトトークンを検証する](https://openid.net/specs/openid-connect-backchannel-1_0.html#Validation)
   </Callout>
3. エンドユーザーのログイン時に、ユーザーは Application A にアクセスするために Auth0 で認証されます。
4. Auth0 は `sid` を含む IDトークンを Application A に送信します。詳しくは、[ID Token Structure](/ja/docs/secure/tokens/id-tokens/id-token-structure) を参照してください。
5. ユーザーは Application B にアクセスするために Auth0 で認証されます。
6. Auth0 は同じ `sid` を含む IDトークンを Application B に送信します。アプリケーションはセッション情報を保存する必要があります。
7. ログアウト時に、Application A または他のエンティティがフロントチャネルでログアウトを開始します。
8. Auth0 はセッションクッキーを介して Auth0 のセッションレイヤーを終了します。
9. Auth0 は Application A の Back-Channel Logout URI を呼び出し、ログアウトトークン を POST します。
10. Application A は ログアウトトークン を検証し、セッションを終了します。
11. Auth0 は Application B の Back-Channel Logout URI を呼び出し、ログアウトトークン を POST します。
12. Application B は ログアウトトークン を検証し、セッションを終了します。

Back-channel logout リクエストは非同期キューに格納され、できるだけ速やかに処理されます。高負荷時には、ログアウトリクエストが実行されるまでにわずかな遅延が発生する可能性があるため、この結果整合性を考慮してアプリケーションを設計してください。

<div id="sample-token">
  #### サンプルトークン
</div>

Auth0 で ログアウトトークン として使用するには、アプリケーションが <Tooltip tip="JSON Web Token（JWT）: 2者間でクレームを安全に表すために使用される標準的な IDトークン形式（多くの場合、アクセストークン形式でもあります）。" cta="用語集を見る" href="/ja/docs/glossary?term=JWTs">JWTs</Tooltip> を解析して検証できる必要があります。詳細については、[JSON Web Tokens を検証する](/ja/docs/secure/tokens/json-web-tokens/validate-json-web-tokens) を参照してください。

アプリケーションがトークンを検証してデコードすると、その内容は次の例のようになります。

```json JSON lines theme={null}
{
  "iss": "https://artex-dev.eu.auth0.com/",
  "sub": "auth0|602e93db83fa6f00749a23e6",
  "aud": "TuhNLv7ulXD3RfyLlSMbOvszzwJJFPpO",
  "iat": 1698160928,
  "exp": 1698161048,
  "jti": "44a91215-dfb4-4dfe-a1eb-fcafa911deba",
  "events": {
    "http://schemas.openid.net/event/backchannel-logout": {}
  },
  "trace_id": "81b336a94a4a5707",
  "sid": "375UIp_ID5mCTClIeBEHpXfGwq51tF_L"
}
```

<div id="auth0-sdks">
  ### Auth0 SDKs
</div>

完全なサンプルと本番環境向けのコードは、[express-openid-connect SDK](https://github.com/auth0/express-openid-connect/blob/master/EXAMPLES.md#11-back-channel-logout) の **Back-Channel Logout Example** セクションにすでに含まれています。

<div id="implementation-examples">
  ## 実装例
</div>

<div id="session-storage">
  ### セッションストレージ
</div>

このセッションストレージの例は Node (Express) で構築されており、[Express OpenID Connect Web App Sample](https://github.com/auth0-samples/auth0-express-webapp-sample/tree/master/01-Login) をベースにしています。

アプリケーションの Sessions タブで、ログアウトトークン を受信するよう設定したルートを公開します。トークンを検証し、ユーザーのセッションを終了します。

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  この例では、デモ用にインメモリのセッションストアを使用しています。
</Callout>

```javascript routes/index.js lines expandable theme={null}
const express = require('express');
const router = express.Router();
const { requiresAuth } = require('express-openid-connect');

// ログアウトトークンを検証するミドルウェア
const requiresValidLogoutToken = require('../middlewares/validateLogoutToken');

// ユーザーセッションを削除するヘルパー関数
const deleteUserSessions = require('../utils/sessions');

// バックチャネルログアウトトークンを受信する新しいルート
// Auth0 管理ダッシュボードの Application -> Sessions タブで
// 設定する必要があります
router.post(
  '/backchannel-logout',
  requiresValidLogoutToken,
  function (req, res, next) {
    // この時点でログアウトトークンは有効です（requiresValidLogoutToken ミドルウェアによって検証済み）
    // リクエストオブジェクトからアクセスできます: req.logoutToken

    // ユーザーセッションを削除してログアウトさせる
    deleteUserSessions(
      req.app.locals.sessionStore,
      req.logoutToken.sub,
      req.logoutToken.sid
    );

    res.sendStatus(200);
  }
);

router.get('/', function (req, res, next) {
  res.render('index', {
    title: 'Auth0 Webapp sample Nodejs',
    isAuthenticated: req.oidc.isAuthenticated(),
    headline: process.env.APP_NAME,
    backgroundColor: process.env.BACKGROUND_COLOR,
    baseURL: process.env.BASE_URL,
  });
});

router.get('/profile', requiresAuth(), function (req, res, next) {
  res.render('profile', {
    userProfile: JSON.stringify(req.oidc.user, null, 2),
    title: 'Profile page',
    headline: process.env.APP_NAME,
    backgroundColor: process.env.BACKGROUND_COLOR,
    baseURL: process.env.BASE_URL,
  });
});

module.exports = router;
```

```javascript middlewares/validateLogoutToken.js lines expandable theme={null}
// このミドルウェアは、以下で定義されているログアウトトークンを検証します:
// https://openid.net/specs/openid-connect-backchannel-1_0.html#Validation

const jose = require('jose');

async function requiresValidLogoutToken(req, res, next) {

  // トークン検証用のリモートキーセットを取得する
  const JWKS = jose.createRemoteJWKSet(
    new URL(process.env.ISSUER_BASE_URL + '/.well-known/jwks.json')
  );

  const logoutToken = req.body.logout_token;

  if (!logoutToken) {
    res.status(400).send('Need logout token');
  }

  try {
    const { payload, protectedHeader } = await jose.jwtVerify(
      logoutToken,
      JWKS,
      {
        issuer: process.env.ISSUER_BASE_URL + '/',
        audience: process.env.CLIENT_ID,
        typ: 'JWT',
        maxTokenAge: '2 minutes',
      }
    );

    // ログアウトトークンに sub クレーム、sid クレーム、またはその両方が含まれていることを確認する
    if (!payload.sub && !payload.sid) {
      res
        .status(400)
        .send(
          'Error: Logout token must contain either sub claim or sid claim, or both'
        );
    }

    // ログアウトトークンに events クレームが含まれていることを確認する
    // その値は、メンバー名 http://schemas.openid.net/event/backchannel-logout を含む JSON オブジェクトであること
    if (!payload.events['http://schemas.openid.net/event/backchannel-logout']) {
      res
        .status(400)
        .send(
          'Error: Logout token must contain events claim with correct schema'
        );
    }

    // ログアウトトークンに nonce クレームが含まれていないことを確認する
    if (payload.nonce) {
      res
        .status(400)
        .send('Error: Logout token must not contain a nonce claim');
    }

    // 有効なログアウトトークンをリクエストオブジェクトに添付する
    req.logoutToken = payload;

    // トークンが有効な場合、次のミドルウェアを呼び出す
    next();
  } catch (error) {
    res.status(400).send(`Error:  ${error.message}`);
  }
}

module.exports = requiresValidLogoutToken;
```

<div id="logout-token-store">
  ### ログアウトトークンストア
</div>

トークンの保存方法として一般的なのは、セッションストアモデルの代替としてログアウトストアを定義するアプローチです。アプリケーションは、永続化レイヤーに ログアウトトークン のコレクションを保持します。

アプリケーションが認証状態を確認する必要があるたびに、ログアウトトークン ストアを参照して、そのセッションがまだアクティブかどうかを確認します。ログアウトストアは、必要な情報だけを残すために、古くなった情報を定期的に削除します。

<Frame>
  <img src="https://mintcdn.com/translations/Dcx0M11uuptU53TX/docs/images/cdy7uua7fh8z/2zTtcie1d0fjiSuxZ4huyV/dbcf45fb68a045bd1b1918315f8025f7/image__21_.png?fit=max&auto=format&n=Dcx0M11uuptU53TX&q=85&s=a5dcbbfe2b72204119f6f3447334799c" alt="Logout Token Store" width="2978" height="1144" data-path="docs/images/cdy7uua7fh8z/2zTtcie1d0fjiSuxZ4huyV/dbcf45fb68a045bd1b1918315f8025f7/image__21_.png" />
</Frame>

<div id="security-considerations">
  ## セキュリティに関する考慮事項
</div>

Back-Channel ログアウトトークン はインターネット経由で配信されるため、それらを受信するコールバックエンドポイントは、信頼性と安全性の高い運用を確保するためのベストプラクティスに従う必要があります。以下の推奨事項は網羅的なものではなく、実際のデプロイや運用状況に応じて適切に判断し、対応する必要があります。以下の一覧では、Back-Channel ログアウトトークン を処理するアプリを「アプリ」と呼びます。

* アプリは、後で Back-Channel ログアウトトークン を受信した際に参照できるよう、ユーザーのログイン時に受信したセッション ID (`sid` クレーム) を保存できなければなりません。
* アプリは、受信したすべてのトークンを [JWT validation best practices](/ja/docs/secure/tokens/json-web-tokens/validate-json-web-tokens) に従って検証しなければなりません。
* アプリは、信頼できるテナントによって発行されたトークンのみを受け入れなければなりません。悪意のある第三者が、他の Auth0 テナントによって発行されたトークンを送信しようとする可能性があるため、そのような試みは拒否しなければなりません。
* アプリは、アプリが認識できる `sid` 値 (セッション ID) を含むトークンのみを受け入れなければなりません。無効なセッション ID (期限切れまたは未認識) を含むトークンは拒否しなければなりません。
* アプリは、コールバックエンドポイントを TLS 経由でのみ公開しなければなりません。暗号化されていない通信チャネルは許可されません。
* アプリは、公開されている [outbound IP addresses](/ja/docs/secure/security-guidance/data-security/allowlist) の一覧に含まれる送信元からのリクエストのみを受け入れることが推奨されます。
* アプリは、監視、ログ記録、レート制限に関する一般的なベストプラクティスに従うことが推奨されます。ただし、これらの詳細はこのドキュメントの対象外です。
* アプリは、古くなった、または期限切れのセッションを定期的にクリーンアップすることが推奨されます。
* エンドポイントアドレスに変更があった場合は、ログアウトトークン が常に正しい Back-Channel Logout Callback URL に配信されるよう、テナント設定と同期しなければなりません。
