
# ホステッドページとフロント API のWebセキュリティ

ホステッドログイン、アカウントポータル、メールページ（確認、パスワードリセット、招待）、およびそれらが呼び出すブラウザ API は、すべてのプランで共通の固定の Web セキュリティ基準に従います。これらの保護は無効にできる設定ではありません。お客様が制御できる設定は、ブラウザからOAuth エンドポイントを呼び出せる Web オリジンの指定のみです。

## クロスサイトリクエストフォージェリ（CSRF）

状態を変更するリクエストは、何かを読み取ったり変更したりする前に検証されます。

- **オリジンの確認。** ホステッドのサインイン API、または確認ページやリセットページへの状態変更リクエストには、環境のログインホストと完全に一致する `Origin` ヘッダーを含める必要があります。それ以外のオリジンは `origin_not_allowed` で拒否されます。
- **同意画面。** 同意画面へのフォーム送信は、`Origin` がページ自身のホストではない場合、または `Sec-Fetch-Site` が存在し `same-origin` ではない場合に拒否されます。
- **フォームトークン。** サインインのトランザクションごと、メールフォームごとに、個別の CSRF トークンがあります。このトークンは、環境ごとのキーから HMAC-SHA256 で生成されます。サインイン API は `Idp-Csrf-Token` ヘッダーでこのトークンを受け取ります。あるフォームのトークンは、別のフォームでは使えません。トークンは定数時間で比較されます。
- **Cookie。** サインインの状態を保持する Cookie は `SameSite=Lax` を使用します（後述）。そのため、別サイトから開始されたリクエストでは送信されません。

## オリジン間リクエスト（CORS）

CORS に応答するのは、ブラウザアプリケーションが呼び出す OAuth エンドポイントのみです。具体的には、トークン、取り消し、Pushed Authorization Request、ユーザー情報のエンドポイントです。これはパブリックなシングルページアプリケーション（`spa` タイプ）にのみ適用されます。

- 許可するオリジンは、アプリケーションごとに `allowed_web_origins`（`https://host[:port]`、最大 20 件、ワイルドカード不可）で設定します。詳しくは [アプリケーションを作成する](/docs/api/management/applications/create) を参照してください。
- ブラウザのプリフライトリクエストには、どのアプリケーションが呼び出しているかが含まれません。そのため、環境内で有効なパブリックなシングルページアプリケーションの許可オリジンの和集合を基に応答します。実際のリクエストは、呼び出し元アプリケーションのオリジン一覧に対して検証されます。
- そのアプリケーションの一覧に含まれないオリジンは、`403 origin_not_allowed` で拒否され、`Access-Control-Allow-Origin` ヘッダーは返されません。
- 許可されたオリジンは、そのまま返されます。`*` と `null` は決して送信されず、`Access-Control-Allow-Credentials` も送信されません。すべてのオリジン間の応答には `Vary: Origin` が付与されます。
- ログインホスト自身からのリクエストはオリジン間ではないため、影響を受けません。

## サインイン後のリダイレクト

Next.js SDK を使用している場合、`returnTo` はお客様のアプリケーション内のパスである必要があります。完全な URL や `//evil.example` のような値は無視され、ユーザーは `/` に移動します。詳しくは [Next.js SDK](/docs/sdk/nextjs) を参照してください。

## セキュリティヘッダー

ホステッドページは、すべてのレスポンスに次のヘッダーを設定します。

| ヘッダー | 値 |
|---|---|
| `Content-Security-Policy` | `default-src 'none'`。スクリプトは、レスポンスごとに新しく生成された nonce を持つものだけを許可。`style-src 'self'`、`connect-src 'self'`、`frame-ancestors 'none'`、`base-uri 'none'`、`object-src 'none'`、`upgrade-insecure-requests`。スクリプトには Trusted Types が必須 |
| `Reporting-Endpoints` と `report-to` | ポリシー違反は、同じホスト上の `/u/csp-report` に報告されます |
| `X-Frame-Options` | `DENY`。ホステッドページはフレームに埋め込めません |
| `X-Content-Type-Options` | `nosniff` |
| `Referrer-Policy` | `no-referrer` |
| `Cross-Origin-Opener-Policy` | `same-origin` |
| `Permissions-Policy` | カメラ、マイク、位置情報、決済、USB、シリアル、HID、Bluetooth は無効です。パスキーのリクエストは、ページ自身に対してのみ許可されます |
| `Cache-Control` | `no-store` |

このポリシーでは、インラインスクリプトと `unsafe-` キーワードは許可されません。フォームの送信は、ページ自身のホストに限定されます。同意画面では、ポリシーは、要求元アプリケーションのリダイレクトアドレスも許可するため、判断結果をそのアプリケーションに戻すことができます。

レポートエンドポイントが受け付けるのは、最大 8 KiB のブラウザ違反レポートのみで、IP アドレスごとにレート制限がかかります。レポートはディレクティブごとに集計されます。ログに記録される際には、クエリ文字列、フラグメント、ユーザー情報は含まれません。

### Strict-Transport-Security

- `keenauth.app` 上の環境ホストは、`max-age=63072000; includeSubDomains` を送信します。
- [カスタムドメイン](/docs/guides/custom-domains) は、`includeSubDomains` を含まず、`max-age=63072000` のみを送信します。KeenAuth はお客様のドメインの他のサブドメインについて判断できないため、その選択はお客様に委ねられます。

## Cookie

サインインの状態を保持する Cookie には `__Host-` プレフィックスが付けられます。そのため、ブラウザは HTTPS 経由で、`Path=/` かつ `Domain` 属性なしの場合にのみ受け入れます。兄弟サブドメインから設定することはできません。

| Cookie | フラグ | 用途 |
|---|---|---|
| `__Host-idp_session` | `Secure`、`HttpOnly`、`SameSite=Lax` | ユーザーのセッション。有効期間は、セッションの絶対的な有効期限で終了します |
| `__Host-idp_device` | `Secure`、`HttpOnly`、`SameSite=Lax` | デバイスの認識 |
| `__Host-idp_ltx` と `__Host-idp_azr_*` | `Secure`、`HttpOnly`、`SameSite=Lax` | サインインまたは認可の試行を、それを開始したブラウザに紐付けます |
| `__Host-idp_fed_bind` | `Secure`、`HttpOnly`、`SameSite=None` | エンタープライズの SAML サインイン用の短期間の紐付け。IDプロバイダは別サイトから戻ってくるため、`Lax` では破棄されてしまいます |

Cookie の値は、ページのスクリプトからは読み取れません（`HttpOnly`）。

## 関連情報

- [ダッシュボードアクセスのセキュリティ](/docs/security/dashboard-access)
- [テナントの分離](/docs/security/tenant-isolation)
- [ログインページのブランディング](/docs/guides/branding)
