コンテンツにスキップ

マルチテナンシーアーキテクチャ

Authrimのマルチテナンシーアーキテクチャは、単一のデプロイメント内で複数の隔離された顧客環境(テナント)を管理できます。このページでは、環境、テナント、クライアントの関係と、ドメイン命名パターンについて説明します。

アーキテクチャ概要

Authrimのマルチテナンシーモデルは、3つの主要概念に基づいています:

flowchart TB
    subgraph env["環境 (独立したインスタンス)"]
        subgraph tenant1["テナント: acme"]
            client1a["クライアント: web-app"]
            client1b["クライアント: mobile-app"]
            client1c["クライアント: api-service"]
        end
        subgraph tenant2["テナント: widget-co"]
            client2a["クライアント: dashboard"]
            client2b["クライアント: api"]
        end
        subgraph tenant3["テナント: default"]
            client3a["クライアント: admin"]
        end
    end

    style env fill:#f0f8ff
    style tenant1 fill:#fff8dc
    style tenant2 fill:#fff8dc
    style tenant3 fill:#fff8dc

1. 環境(インフラストラクチャレベル)

各環境は完全に独立したWorkersインスタンスとして動作します。

  • 目的: ライフサイクルステージの分離(開発、テスト、ステージング、本番)
  • 隔離: 独立したコードベースデプロイ、独立したデータベース、独立したKVストア
  • ドメイン: 各環境は独自のBASE_DOMAINを持つ
  • 独立性: 環境間でデータや設定を共有しない

:

本番環境: BASE_DOMAIN = "authrim.com"
ステージング: BASE_DOMAIN = "staging.authrim.com"
テスト: BASE_DOMAIN = "test.authrim.com"
開発: BASE_DOMAIN = "dev.authrim.com"

2. テナント(隔離境界)

テナントは、環境内の隔離された顧客ワークスペースです。

  • 目的: 顧客/組織データの隔離
  • スコープ: すべてのデータ(ユーザー、セッション、トークン、ポリシー)はテナントにスコープされる
  • ドメイン: サブドメインで識別(例: acme.authrim.com
  • 隔離: 完全な論理分離 — テナント間でデータの閲覧やアクセスは不可

主な特徴:

  • BASE_DOMAINが設定されている場合、マルチテナントモードは常に有効
  • 各テナントは以下を隔離:
    • ユーザーディレクトリ
    • クライアントアプリケーション
    • セッションとトークン
    • 監査ログ
    • 認可ポリシー
  • テナント間のデータ共有なし(明示的に連携しない限り)

3. クライアント(アプリケーション)

クライアントは、テナント内に登録されたアプリケーションです。

  • 目的: ユーザーを認証するアプリケーションを表す
  • スコープ: 正確に1つのテナントに属する
  • 種類: Webアプリ、モバイルアプリ、SPA、バックエンドサービス、M2Mアプリケーション
  • プロトコル: OAuth 2.0、OIDC、SAML 2.0

:

  • テナント: acme
    • クライアント: web-dashboard (OIDC, authorization_code + PKCE)
    • クライアント: mobile-app (OIDC, authorization_code + PKCE)
    • クライアント: api-service (OAuth 2.0, client_credentials)
    • クライアント: legacy-app (SAML 2.0 SP)

ドメインパターン

有効なパターン

Authrimはサブドメインベースのテナント隔離を使用します。単一レベルのサブドメインのみが許可されます。

本番環境 (BASE_DOMAIN = "authrim.com")

ドメインテナントID説明
authrim.comPRIMARY_TENANT_ID または defaultネイキッドドメイン(プライマリテナント)
acme.authrim.comacmeシンプルなテナント名
acme-corp.authrim.comacme-corpハイフン付きテナント名
acme-prod.authrim.comacme-prodサフィックス付きテナント
tenant123.authrim.comtenant123英数字テナント
a.authrim.coma1文字テナント

ステージング環境 (BASE_DOMAIN = "staging.authrim.com")

ドメインテナントID説明
staging.authrim.comdefaultネイキッドドメイン
acme.staging.authrim.comacmeステージング環境のテナント
widget-co.staging.authrim.comwidget-co別のテナント

テスト環境 (BASE_DOMAIN = "test.authrim.com")

ドメインテナントID説明
test.authrim.comdefaultネイキッドドメイン
acme.test.authrim.comacmeテスト環境のテナント

無効なパターン(拒否される)

❌ サブサブドメインは許可されません

多階層サブドメインは、曖昧さを防ぎセキュリティを維持するために拒否されます。

ドメインエラー理由
dev.acme.authrim.cominvalid_format (400)サブサブドメインは不可
api.acme.authrim.cominvalid_format (400)サブサブドメインは不可
auth.tenant.staging.authrim.cominvalid_format (400)サブサブドメインは不可
acme.other.comtenant_not_found (404)BASE_DOMAINの不一致
-acme.authrim.cominvalid_format (400)先頭のハイフン
acme-.authrim.cominvalid_format (400)末尾のハイフン
tenant_name.authrim.cominvalid_format (400)アンダースコア不可

サブサブドメインが禁止されている理由:

  1. 曖昧性: dev.acme.authrim.comdevはサービスプレフィックス?それともテナント名の一部?
  2. シンプルさ: 単一レベルのサブドメインは理解・管理が容易
  3. セキュリティ: DNSベースの攻撃や設定ミスを防止
  4. アーキテクチャ: 環境は独立したインスタンスであり、サブドメインではない

解決策: テナント名にハイフンを使用:

  • dev.acme.authrim.com → ✅ acme-dev.authrim.com
  • api.tenant.authrim.com → ✅ tenant-api.authrim.com

環境設定

環境変数

各環境インスタンスには以下の変数が必要です:

Terminal window
# マルチテナントモード用のベースドメイン
BASE_DOMAIN="authrim.com"
# デフォルトテナントID(テナント未指定時に使用)
DEFAULT_TENANT_ID="default"
# ネイキッドドメインアクセス用のプライマリテナント(オプション)
PRIMARY_TENANT_ID="main"
# ユーザーIDフォーマット(uuid または nanoid)
USER_ID_FORMAT="nanoid"

ネイキッドドメインルーティング

ネイキッドドメイン(例: authrim.com)にアクセスした場合、Authrimは以下の優先順位を使用:

  1. PRIMARY_TENANT_IDが設定されている → そのテナントにルーティング
  2. DEFAULT_TENANT_IDが設定されている → そのテナントにルーティング
  3. フォールバック: "default"テナントにルーティング

:

Terminal window
BASE_DOMAIN="authrim.com"
PRIMARY_TENANT_ID="main"
DEFAULT_TENANT_ID="default"
  • authrim.com → テナント"main"にルーティング
  • acme.authrim.com → テナント"acme"にルーティング
  • widget.authrim.com → テナント"widget"にルーティング

関係の例

例1: SaaSプラットフォーム

シナリオ: 複数の顧客を持つSaaS企業

本番環境 (BASE_DOMAIN = "myplatform.com"):
├── テナント: acme
│ ├── クライアント: web-dashboard (OIDC)
│ ├── クライアント: mobile-app (OIDC)
│ └── クライアント: reporting-api (OAuth M2M)
├── テナント: widget-co
│ ├── クライアント: admin-panel (OIDC)
│ └── クライアント: public-api (OAuth M2M)
└── テナント: default
└── クライアント: platform-admin (OIDC)
ステージング環境 (BASE_DOMAIN = "staging.myplatform.com"):
├── テナント: acme
│ ├── クライアント: web-dashboard (テスト中)
│ └── クライアント: mobile-app (テスト中)
└── テナント: test-customer
└── クライアント: demo-app (テスト中)

ドメイン:

  • 本番: acme.myplatform.com, widget-co.myplatform.com
  • ステージング: acme.staging.myplatform.com, test-customer.staging.myplatform.com

例2: シングルテナント(社内利用)

シナリオ: 社内認証にAuthrimを使用する企業

本番環境 (BASE_DOMAIN = "auth.company.com"):
└── テナント: company (PRIMARY_TENANT_ID経由)
├── クライアント: employee-portal (OIDC)
├── クライアント: mobile-app (OIDC)
├── クライアント: legacy-intranet (SAML)
└── クライアント: api-gateway (OAuth M2M)
テスト環境 (BASE_DOMAIN = "auth-test.company.com"):
└── テナント: company
└── クライアント: employee-portal (テスト中)

設定:

Terminal window
# 本番
BASE_DOMAIN="auth.company.com"
PRIMARY_TENANT_ID="company"
# ユーザーはネイキッドドメイン経由でアクセス: auth.company.com → テナント"company"

例3: マルチ環境開発

シナリオ: 複数の環境を持つ開発チーム

開発環境 (BASE_DOMAIN = "dev.authrim.com"):
├── テナント: alice-dev
│ └── クライアント: test-app
└── テナント: bob-dev
└── クライアント: test-app
テスト/CI (BASE_DOMAIN = "test.authrim.com"):
├── テナント: ci-runner-1
│ └── クライアント: automated-tests
└── テナント: ci-runner-2
└── クライアント: automated-tests
ステージング (BASE_DOMAIN = "staging.authrim.com"):
└── テナント: demo
├── クライアント: web-app
└── クライアント: mobile-app
本番 (BASE_DOMAIN = "authrim.com"):
├── テナント: customer-a
│ ├── クライアント: web-app
│ └── クライアント: mobile-app
└── テナント: customer-b
├── クライアント: dashboard
└── クライアント: api

ベストプラクティス

1. 環境分離

推奨:

  • 各環境に別々のBASE_DOMAINを使用
  • 各環境を独立したWorkersインスタンスとしてデプロイ
  • 環境固有のデータベースとKVストアを使用

非推奨:

  • 同じ環境でテストデータと本番データを混在させる
  • サブサブドメインで環境を表現(例: test.acme.authrim.com

2. テナント命名

推奨:

  • 小文字英数字とハイフンを使用
  • テナント名は短く説明的に
  • 複数単語の名前にはハイフンを使用: acme-corp, widget-co

非推奨:

  • ハイフンで開始/終了: -acme, acme-
  • 特殊文字を使用: acme_corp, acme@company
  • サブサブドメインを作成: dev.acme.authrim.com

3. クライアント管理

推奨:

  • 各アプリケーションを別々のクライアントとして登録
  • 適切なクライアントタイプを使用(バックエンドはconfidential、SPA/モバイルはpublic)
  • すべてのpublicクライアントでPKCEを有効化
  • M2Mサービスにはclient_credentialsグラントを使用

非推奨:

  • テナント間でクライアント認証情報を共有
  • 複数の環境で同じclient_idを使用(環境ごとに別クライアントを使用)
  • publicクライアントでPKCEを無効化

セキュリティ考慮事項

テナント隔離

  • データベースレベルの隔離: すべてのクエリは自動的にテナントIDにスコープされる
  • セッション隔離: セッションはテナント間で共有できない
  • トークン隔離: アクセストークンは発行元テナントにバインドされる
  • 監査隔離: 監査ログはテナントごとに分離

ドメイン検証

  • Hostヘッダー検証: AuthrimはすべてのリクエストでHostヘッダーを検証
  • BASE_DOMAIN強制: *.BASE_DOMAINにマッチするリクエストのみ受け入れ
  • サブサブドメイン拒否: 多階層サブドメインは400 Bad Requestで拒否
  • CORS強制: CORSポリシーはテナントスコープ

テナント間アクセス

デフォルトで、テナント間アクセスは禁止されています。連携アクセスが必要な場合:

  1. 外部IdPブリッジを使用: ソーシャルログインまたはエンタープライズSSOを設定
  2. SAMLフェデレーション: テナント間にSAML信頼を設定
  3. トークン交換: OAuth 2.0トークン交換(RFC 8693)を実装

マイグレーションシナリオ

シングルテナントからマルチテナントへ

シングルテナントデプロイメントから移行する場合:

  1. BASE_DOMAINを設定: ベースドメインを設定(例: authrim.com
  2. PRIMARY_TENANT_IDを設定: ネイキッドドメインを既存テナントに向ける
  3. ユーザーを移行: 既存のすべてのユーザーはプライマリテナントに属する
  4. 新しいテナントを追加: Admin API経由で新しいテナントを作成
  5. DNSを更新: *.authrim.comのワイルドカードDNSを設定

:

Terminal window
# 移行前(シングルテナント)
ISSUER_URL="https://auth.company.com"
# 移行後(マルチテナント)
BASE_DOMAIN="auth.company.com"
PRIMARY_TENANT_ID="company"
# ネイキッドドメイン(auth.company.com)は引き続き動作 → テナント"company"にルーティング

新しいテナントの追加

新しいテナントを追加するには:

  1. Admin API経由でテナントを作成:
Terminal window
POST /admin/tenants
{
"tenantId": "new-customer",
"displayName": "New Customer Inc."
}
  1. DNSを設定: new-customer.authrim.comがWorkersに解決されることを確認
  2. クライアントを登録: 新しいテナント用のOAuth/OIDCクライアントを作成
  3. アクセスをテスト: new-customer.authrim.comでログインを確認

トラブルシューティング

よくある問題

問題: tenant_not_foundエラー(404)

原因:

  • ドメインがBASE_DOMAINと一致しない
  • サブサブドメインを使用(例: dev.acme.authrim.com
  • データベースにテナントが存在しない

解決策:

  • BASE_DOMAIN設定を確認
  • 単一レベルのサブドメインを使用: acme.authrim.com
  • Admin API経由でテナントを作成

問題: invalid_formatエラー(400)

原因:

  • サブサブドメインを使用(例: api.tenant.authrim.com
  • サブドメインに無効な文字
  • ハイフンが先頭または末尾

解決策:

  • ハイフンを使用: tenant-api.authrim.com
  • 英数字とハイフンのみ使用: [a-z0-9-]+
  • 先頭/末尾のハイフンがないことを確認

問題: missing_hostエラー(400)

原因: リクエストからHostヘッダーが欠落

解決策:

  • HTTPクライアントがHostヘッダーを送信することを確認
  • リバースプロキシ設定を確認
  • Cloudflare設定を確認

関連ドキュメント