# カスタムバックエンドの設定

{% hint style="warning" %}
このガイドでは、ドキュメント用の保護されたサインイン画面を設定する手順を説明します。このガイドを読む前に、まず次の手順を完了していることを確認してください。 [認証済みアクセスを有効にする](https://gitbook-v2-q67etdj25-gitbook.vercel.app/url/gitbook.com/docs/documentation/ja-gitbook-documentation/publishing-documentation/authenticated-access/enabling-authenticated-access).
{% endhint %}

このガイドでは、独自の **カスタム** 認証バックエンドを使用して、GitBook のドキュメントサイト用の保護されたサインイン画面を設定する手順を説明します。

{% hint style="info" %}
サポートしている認証プロバイダーのいずれかを使用している場合、または [OpenID Connect](https://auth0.com/docs/authenticate/protocols/openid-connect-protocol) （OIDC）準拠のバックエンドをお持ちの場合は、より簡単に設定できる統合ガイドをご覧ください。\
\
[Auth0](https://gitbook-v2-q67etdj25-gitbook.vercel.app/url/gitbook.com/docs/documentation/ja-gitbook-documentation/publishing-documentation/authenticated-access/setting-up-auth0) | [Azure AD](https://gitbook-v2-q67etdj25-gitbook.vercel.app/url/gitbook.com/docs/documentation/ja-gitbook-documentation/publishing-documentation/authenticated-access/setting-up-azure-ad) | [Okta](https://gitbook-v2-q67etdj25-gitbook.vercel.app/url/gitbook.com/docs/documentation/ja-gitbook-documentation/publishing-documentation/authenticated-access/setting-up-okta) | [AWS Cognito](https://gitbook-v2-q67etdj25-gitbook.vercel.app/url/gitbook.com/docs/documentation/ja-gitbook-documentation/publishing-documentation/authenticated-access/setting-up-aws-cognito) | [OIDC](https://gitbook-v2-q67etdj25-gitbook.vercel.app/url/gitbook.com/docs/documentation/ja-gitbook-documentation/publishing-documentation/authenticated-access/setting-up-oidc)
{% endhint %}

### 概要

GitBook サイトにカスタム認証システムを設定するには、次の主要な手順に従います。

{% stepper %}
{% step %}
[**ユーザーを認証するためのカスタムバックエンドを作成する**](#id-1.-create-a-custom-backend-to-authenticate-your-users)

ユーザーにログインを促し、認証するバックエンドを実装します。
{% endstep %}

{% step %}
[**JWT トークンに署名して GitBook に渡す**](#id-2.-sign-and-pass-a-jwt-token-to-gitbook)

JWT トークンを作成し、サイトの秘密鍵で署名します。
{% endstep %}

{% step %}
[**フォールバック URL を設定する**](#id-3.-configure-a-fallback-url)

未認証の訪問者がサイトにアクセスしたときに使用する URL を設定します。
{% endstep %}

{% step %}
[**マルチテナントの認証済みアクセスを設定する（オプション）**](#id-4.-set-up-multi-tenant-authenticated-access)

複数の GitBook サイトにまたがる認証を処理するようにバックエンドを設定します。
{% endstep %}

{% step %}
[**アダプティブコンテンツ用にバックエンドを設定する（オプション）**](#id-5.-configure-your-backend-for-adaptive-content)

GitBook のアダプティブコンテンツで動作するようにバックエンドを設定します。
{% endstep %}
{% endstepper %}

### 1. ユーザーを認証するためのカスタムバックエンドを作成する

ユーザーがドキュメントにアクセスできるようになる前に認証を開始するには、ユーザーのログインと認証を処理できるサーバーを用意する必要があります。

バックエンドは次のことを行う必要があります。

* 希望する認証方法を使用してユーザーにログインを促す。
* ユーザーの認証情報を検証し、認証する。
* 次を生成して署名する **JSON Web トークン（JWT）** 認証成功時に。
* JWT を URL に含めてユーザーを GitBook にリダイレクトする。

### 2. JWT トークンに署名して GitBook に渡す

バックエンドがユーザーを認証したら、 **JWT を生成し** 、 **GitBook に渡す** 際に **リダイレクトして** サイトへ送る必要があります。トークンは次のものを使用して署名する必要があります。 **秘密鍵** サイトの audience 設定で提供されたものを使用します。 [認証済みアクセスを有効にする](https://gitbook-v2-q67etdj25-gitbook.vercel.app/url/gitbook.com/docs/documentation/ja-gitbook-documentation/publishing-documentation/enabling-authenticated-access#enable-authenticated-access).

次の例は、カスタムバックエンド内のログインリクエストハンドラーがどのように見えるかを示しています。

{% code title="index.ts" %}

```typescript
import { Request, Response } from 'express';
import * as jose from 'jose';

import { getUserInfo } from '../services/user-info-service';
import { getFeatureFlags } from '../services/feature-flags-service';

const GITBOOK_VISITOR_SIGNING_KEY = process.env.GITBOOK_VISITOR_SIGNING_KEY!;
const GITBOOK_DOCS_URL = 'https://mycompany.gitbook.io/myspace';

export async function handleAppLoginRequest(req: Request, res: Response) {
    // ログインリクエストを処理するためのビジネスロジック
    // たとえば、認証情報を確認してユーザーを認証する
    //
    // 例：
    // const loggedInUser = await authenticateUser(req.body.username, req.body.password);
    
    // 署名済み JWT を生成する
    const gitbookVisitorJWT = await new jose.SignJWT({})
        .setProtectedHeader({ alg: 'HS256' })
        .setIssuedAt()
        .setExpirationTime('2h') // 任意の 2 時間の有効期限
        .sign(new TextEncoder().encode(GITBOOK_VISITOR_SIGNING_KEY));
    
    // JWT トークンを URL に含めてユーザーを GitBook にリダイレクトする
    const redirectURL = `${GITBOOK_DOCS_URL}/?jwt_token=${gitbookVisitorJWT}`;
    res.redirect(redirectURL);
}
```

{% endcode %}

### 3. フォールバック URL を設定する

フォールバック URL は、未認証の訪問者が保護されたサイトにアクセスしようとしたときに使用されます。その後、GitBook はその訪問者をこの URL にリダイレクトします。

この URL はカスタムバックエンド内のハンドラーを指し、そこでログインを促し、認証し、その後 URL に JWT を含めてサイトへ戻すようにリダイレクトします。

たとえば、ログイン画面が `https://example.com/login`にある場合、この値をフォールバック URL として含める必要があります。

このフォールバック URL は、サイトの audience 設定の「Authenticated access」タブで設定できます。

<figure><img src="https://4217681718-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNkEGS7hzeqa35sMXQZ4X%2Fuploads%2FB48PEdMz1tCDf0Q0lo4d%2FScreenshot%202025-03-25%20at%2015.00.08.png?alt=media&#x26;token=e22fe867-e1f6-44f7-8b4f-a868ac620464" alt="A GitBook screenshot showing where to configure a fallback URL"><figcaption><p>フォールバック URL を設定する</p></figcaption></figure>

フォールバック URL にリダイレクトする際、GitBook は `location` クエリパラメータをフォールバック URL に追加します。これをハンドラーで利用して、ユーザーを元の場所にリダイレクトできます。

```javascript
const gitbookVisitorJWT = await new jose.SignJWT({})
    .setProtectedHeader({ alg: 'HS256' })
    .setIssuedAt()
    .setExpirationTime('2h') // 任意の 2 時間の有効期限
    .sign(new TextEncoder().encode(GITBOOK_VISITOR_SIGNING_KEY));
    
// JWT を jwt_token クエリパラメータとして含めて、元の GitBook ドキュメント URL にリダイレクトする
// location が指定されている場合、ユーザーは元の移動先に戻される
const redirectURL = `${GITBOOK_DOCS_URL}/${req.query.location || ''}?jwt_token=${gitbookVisitorJWT}`;
res.redirect(redirectURL);
```

{% hint style="warning" %}
GitBook は `location` search param に依存しているため、フォールバック URL には使用できません。たとえば、 `https://auth.gitbook.com/?location=something` は有効なフォールバック URL ではありません。
{% endhint %}

### 4. マルチテナントの認証済みアクセスを設定する（オプション）

GitBook を複数の顧客にコンテンツを提供するプラットフォームとして使用している場合、マルチテナントの認証済みアクセスを設定する必要がある可能性が高いです。認証バックエンドは、複数の異なるサイトにまたがる認証を処理する責任を持つ必要があります。これは、カスタム認証バックエンドのコードに少し手を加えるだけで GitBook で可能です。

#### すべてのテナントを認証サーバーに追加する

認証バックエンドは、JWT 署名鍵と、処理対象となるすべての GitBook サイトの URL を把握している必要があります。組織に Customer A と Customer B の 2 つのサイトがある場合、認証コードで次のような対応関係を保存できます。

```typescript
const CUSTOMER_A = {
  jwtSigningKey: 'aaa-aaa-aaa-aaa',
  url: 'https://mycompany.gitbook.io/customer-a'
};

const CUSTOMER_B = {
  jwtSigningKey: 'bbb-bbb-bbb-bbb',
  url: 'https://mycompany.gitbook.io/customer-b'
};
```

#### 認証サーバーに追加のコンテキストを与える

GitBook がユーザーのリクエストを認証できない場合、フォールバック URL にリダイレクトします。この URL は認証バックエンドを指し、ユーザーを認証して要求されたコンテンツに戻す役割を担います。

複数のテナントをサポートするには、ユーザーがどの GitBook サイトにアクセスすべきかを認証バックエンドが把握している必要があります。この情報はフォールバック URL で渡せます。

たとえば、各サイトのフォールバック URL を次のように設定できます。

<table><thead><tr><th width="150.75390625">GitBook サイト</th><th>フォールバック URL</th></tr></thead><tbody><tr><td>Customer A のサイト</td><td><code>https://auth-backend.acme.org/login?site=customer-a</code></td></tr><tr><td>Customer B のサイト</td><td><code>https://auth-backend.acme.org/login?site=customer-b</code></td></tr></tbody></table>

その後、認証バックエンドはこの情報を確認し、それに応じて正しいサイトへのリダイレクトを処理できます。

```javascript
const customerInfo = req.query.site === 'customer-a' ? CUSTOMER_A : CUSTOMER_B;
  
const gitbookVisitorJWT = await new jose.SignJWT({})
    .setProtectedHeader({ alg: 'HS256' })
    .setIssuedAt()
    .setExpirationTime('2h') // 任意の 2 時間の有効期限
    .sign(new TextEncoder().encode(customerInfo.jwtSigningKey));
    
// JWT を jwt_token クエリパラメータとして含めて、元の GitBook ドキュメント URL にリダイレクトする
// location が指定されている場合、ユーザーは元の移動先に戻される
const redirectURL = `${customerInfo.url}/${req.query.location || ''}?jwt_token=${gitbookVisitorJWT}`;
res.redirect(redirectURL);
```

### 5. アダプティブコンテンツ用にバックエンドを設定する（オプション）

認証済みアクセス設定でアダプティブコンテンツ機能を活用するには、カスタムバックエンドが生成する JWT のペイロードに追加のユーザー属性（クレーム）を含め、ユーザーをサイトにリダイレクトする際に URL に含めることができます。

これらのクレームは JWT に含められると、GitBook によって [コンテンツを適応させる](https://gitbook-v2-q67etdj25-gitbook.vercel.app/url/gitbook.com/docs/documentation/ja-gitbook-documentation/publishing-documentation/adaptive-content/adapting-your-content) ために、サイト訪問者向けに動的に使用されます。

まとめると、次のコード例は、これらのクレームを JWT に含める方法を示しており、その後 GitBook が訪問者向けにコンテンツを適応させるために使用できます。

{% code title="index.ts" %}

```typescript
import { Request, Response } from 'express';
import * as jose from 'jose';

import { getUserInfo } from '../services/user-info-service';
import { getFeatureFlags } from '../services/feature-flags-service';

const GITBOOK_VISITOR_SIGNING_KEY = process.env.GITBOOK_VISITOR_SIGNING_KEY!;
const GITBOOK_DOCS_URL = 'https://mycompany.gitbook.io/myspace';

export async function handleAppLoginRequest(req: Request, res: Response) {
    // ログインリクエストを処理するためのビジネスロジック
    // たとえば、認証情報を確認してユーザーを認証する
    //
    // 例：
    // const loggedInUser = await authenticateUser(req.body.username, req.body.password);
    
    // この例では、ログイン済みユーザーオブジェクトがあると仮定する
    const loggedInUser = { id: '12345' }; // 実際の認証ロジックに置き換えてください

    // GitBook に渡すユーザー情報を取得する
    const userInfo = await getUserInfo(loggedInUser.id);
    
    // 署名済み JWT を生成し、ユーザー属性をクレームとして含める
    const gitbookVisitorClaims = {
        firstName: userInfo.firstName,
        lastName: userInfo.lastName,
        isBetaUser: userInfo.isBetaUser,
        products: userInfo.products.map((product) => product.name),
        featureFlags: await getFeatureFlags({ userId: loggedInUser.id })
    };
    
    const gitbookVisitorJWT = await new jose.SignJWT(gitbookVisitorClaims)
        .setProtectedHeader({ alg: 'HS256' })
        .setIssuedAt()
        .setExpirationTime('2h') // 任意の 2 時間の有効期限
        .sign(new TextEncoder().encode(GITBOOK_VISITOR_SIGNING_KEY));
    
    // JWT トークンを URL に含めてユーザーを GitBook にリダイレクトする
    const redirectURL = `${GITBOOK_DOCS_URL}/?jwt_token=${gitbookVisitorJWT}`;
    res.redirect(redirectURL);
}
```

{% endcode %}

GitBook に送る適切なクレームを設定・構成したら、「[コンテンツを適応させる](https://gitbook-v2-q67etdj25-gitbook.vercel.app/url/gitbook.com/docs/documentation/ja-gitbook-documentation/publishing-documentation/adaptive-content/adapting-your-content)」に進んでサイトの設定を続けてください。
