コンテンツにスキップ

アーキテクチャ

Authrimは、Cloudflare Workersエコシステム上に構築された統合アイデンティティ&アクセスプラットフォームです。このページでは、マルチワーカーシステム、データベース抽象化レイヤー、PIIパーティションルーティング、Durable Objectリージョンシャーディングについて解説します。

システム概要

Authrimは、Service Bindingsで接続された複数の専門Workerで構成されています。ar-router Workerが中央のエントリーポイントとして機能し、ドメイン固有のWorkerにリクエストを振り分けます。

flowchart LR
    router["ar-router
(エントリーポイント)"] subgraph endpoints["OIDC / Auth"] discovery["ar-discovery
(OIDCメタ)"] auth["ar-auth
(認可EP)"] token["ar-token
(トークンEP)"] userinfo["ar-userinfo
(UserInfo EP)"] end subgraph federation["フェデレーション"] saml["ar-saml
(SAML IdP)"] bridge["ar-bridge
(外部IdP)"] end subgraph ops["運用"] mgmt["ar-management
(管理API)"] async["ar-async
(バックグラウンド処理)"] end router --> discovery & auth & token & userinfo router --> saml & bridge router --> mgmt & async
Worker役割
ar-routerリクエストルーティング、レート制限、CORS
ar-discovery/.well-known/openid-configuration、JWKS
ar-auth認可エンドポイント、同意、ログインフロー
ar-tokenトークンエンドポイント(コード交換、リフレッシュ、デバイス)
ar-userinfoUserInfoエンドポイント
ar-management管理API(ユーザー、クライアント、ロール、ポリシー)
ar-samlSAML IdPおよびSP
ar-bridge外部IdP連携(ソーシャルログイン、エンタープライズSSO)
ar-asyncバックグラウンドジョブ(鍵ローテーション、クリーンアップ、SCIMsync)

すべてのWorkerは共通ライブラリ ar-lib-core を共有しており、データベース抽象化、リポジトリ、ユーティリティ、Durable Objectの定義を提供します。

データベース抽象化レイヤー

DatabaseAdapterインターフェース

すべてのデータベース操作は DatabaseAdapter インターフェースを通じて行われ、基盤となるストレージエンジンを抽象化します。

interface DatabaseAdapter {
query<T>(sql: string, params?: unknown[]): Promise<T[]>;
queryOne<T>(sql: string, params?: unknown[]): Promise<T | null>;
execute(sql: string, params?: unknown[]): Promise<ExecuteResult>;
transaction<T>(fn: (tx: TransactionContext) => Promise<T>): Promise<T>;
batch(statements: PreparedStatement[]): Promise<ExecuteResult[]>;
isHealthy(): Promise<HealthStatus>;
}

主要な実装はCloudflare D1(サーバーレスSQLite)向けの D1Adapter です。指数バックオフ付きリトライロジックとヘルスチェック監視を備えています。

トランザクションセマンティクス: D1は従来のSQLトランザクションをサポートしていません。代わりに、D1Adapterは transaction() 呼び出し内のすべてのステートメントを収集し、D1バッチとして実行します — all-or-nothing(すべて成功またはすべてロールバック)のセマンティクスを提供します。

BaseRepositoryパターン

すべてのエンティティリポジトリは BaseRepository<T> を継承し、以下を提供します。

  • CRUD操作findByIdcreateupdatedelete
  • ページネーション — カーソルベース、ソート設定可能
  • フィルタリング — 型安全な条件とオペレータサポート(eqinlike 等)
  • ソフトデリートis_active フラグによる(デフォルト動作)
  • SQLインジェクション防止 — 許可リストに対するフィールド名の検証

3データベース分離

Authrimは、データの機密性に応じて3つの独立したD1データベースを使用します。

データベース目的内容
DB_CORE認証コアユーザー(非PII)、クライアント、セッション、トークン、ロール
DB_PII個人データメール、氏名、住所 — 地理的にパーティション分割
DB_ADMINプラットフォーム管理管理者ユーザー、監査ログ、テナント設定

この分離により、PIIを管轄に適したデータベースに保存しつつ、認証操作はDB_COREのみにアクセスすることが保証されます。

PIIパーティションルーター

PIIPartitionRouter は、PIIデータアクセスを正しいデータベースパーティションにルーティングします。各パーティションは個別の DatabaseAdapter インスタンス(異なる地理的リージョンに配置可能)にマッピングされます。

信頼レベル階層

新しいユーザーのPIIをどのパーティションに保存するかを決定する際、ルーターは信頼階層(信頼度の高い順)で評価します。

優先度方法信頼レベル説明
1テナントポリシーテナント固有のパーティション指定
2居住地申告ユーザー自己申告の居住国
3カスタムルール属性ベースのルーティングルール(プラン、ロール等)
4IPルーティングCloudflareジオヘッダー(フォールバックのみ)
5デフォルトパーティション最終手段

パーティション設定

パーティション設定はKV(インメモリキャッシュ、10秒TTL付き)に保存され、管理APIを通じてテナントごとに設定可能です。

  • 利用可能なパーティション — 登録済みデータベースアダプター(例: euusapacdefault
  • テナントオーバーライド — テナントのすべてのユーザーを特定パーティションに強制
  • カスタムルール — 優先順位付きの属性ベース条件
  • IPルーティングトグル — 地理的フォールバックの有効/無効

users_core.pii_partition カラムが各ユーザーのPIIがどのパーティションに格納されているかを追跡し、後続の読み取り時の正しいルーティングを可能にします。

Durable Objectリージョンシャーディング

Durable Objects(DO)は強い一貫性を持つステートフルストレージを提供し、Authrimではセッション、認可コード、チャレンジ、リフレッシュトークンなどに使用されます。リージョンシャーディングにより、これらのDOを複数のシャードと地理的リージョンに分散させます。

なぜリージョンシャーディングが必要か

単一のDurable Objectインスタンスは約50〜100リクエスト/秒を処理できます。数千の同時認証フローを処理するプラットフォームでは、リソースタイプごとに単一のDOではボトルネックになります。リージョンシャーディングは以下により解決します。

  1. 水平スケーリング — N個のシャードにわたる負荷分散
  2. 地理的局所性locationHintによるユーザー近接配置
  3. 予測可能なルーティング — リソースIDにシャード情報を埋め込み、ルックアップなしでルーティング

シャード設定

シャードキーアルゴリズム

Authrimは**FNV-1a(32ビット)**ハッシュを使用してシャード割り当てを決定します。

shardIndex = fnv1a32(shardKey) % totalShards

shardKey はリソースタイプによって異なります。

  • セッション: ランダムなセキュアID(均一分布)
  • AuthCode / RefreshToken: userId:clientId(ユーザー・クライアントペアで共置)
  • PAR / DeviceCode / CIBA / DPoP: clientId
  • チャレンジ: ランダムID

リージョンIDフォーマット

すべてのリージョンシャーディングされたリソースIDには、ルーティング情報が埋め込まれます。

g{generation}:{region}:{shard}:{prefix}_{randomPart}

例:

  • g1:apac:3:ses_X7g9kPq2Lm4R — APACリージョン、シャード3、世代1のセッション
  • g1:enam:1:acd_9f8a2b1c — US Eastリージョン、シャード1の認可コード

対応するDOインスタンス名は以下の形式です。

{tenantId}:{region}:{typeAbbrev}:{shard}

例: default:apac:ses:3

リージョン分布

シャードは、パーセンテージ分布に基づいて地理的リージョンに分割されます。デフォルト設定(合計4シャード):

リージョン割合シャード数範囲
enam(US East)50%20–1
weur(West Europe)25%12
apac(Asia Pacific)25%13

calculateRegionRanges() 関数がパーセンテージを具体的なシャード範囲に変換し、すべてのシャードがカバーされることを保証します。

配置と共置

locationHintによる配置

DOスタブを作成する際、Authrimは locationHint をCloudflareに渡します。

namespace.get(id, { locationHint: 'apac' });

このヒントは、指定されたDO IDに対する最初の get() 呼び出しでのみ有効です — CloudflareがDOを物理的にどこに配置するかを決定します。以降の呼び出しは、すでに配置されたインスタンスにルーティングされます。

共置グループ(Colocation Groups)

同じシャードキーを同じシャードにルーティングする必要があるDOは、同一のシャード数を持つ必要があります。Authrimはこれを強制するために共置グループを定義しています。

グループシャード数メンバー理由
user-client4AuthCode、RefreshToken同じ userId:clientId キー
random-high-rps4Revocation高スループット
random-medium-rps4Session、Challenge中スループット
client-based4PAR、DeviceCode、CIBA、DPoP同じ clientId キー
vc4CredOffer、VPRequestVerifiable Credentials

共置グループ内でシャード数が不一致の場合、間欠的な認証失敗が発生します — ユーザーのAuthCodeとRefreshTokenが異なるシャードに配置され、コード交換フローが破綻します。

マイグレーションとルーティング

世代ベースのマイグレーション

シャード設定が変更される場合(例: 4シャードから32シャードへのスケール)、Authrimは世代ベースのアプローチを使用します。

  1. 現在の世代設定が previousGenerations にアーカイブされる
  2. 更新されたシャード数と分布で新しい世代が作成される
  3. 新しいリソースは新しい世代を使用する
  4. 既存のリソースは元の世代へのルーティングを継続する(情報がIDに埋め込まれているため)

これにより、データマイグレーションは不要です — 異なるシャード設定を持つ古いリソースと新しいリソースが共存します。最大5つの過去世代が保持されます。

リソース作成フロー

1. ランダムIDを生成 / シャードキーを計算
2. KVからRegionShardConfigを取得(10秒キャッシュ)
3. 計算: shardIndex = fnv1a32(shardKey) % totalShards
4. シャード範囲からリージョンを解決
5. リソースID作成: g{gen}:{region}:{shard}:{prefix}_{random}
6. DOインスタンス名を構築: {tenant}:{region}:{type}:{shard}
7. locationHint付きでDOスタブを取得
8. DOにリクエストを送信

既存リソースアクセスフロー

1. リソースIDを解析 → generation、region、shardを抽出
2. 解析情報からDOインスタンス名を構築
3. locationHint付きでDOスタブを取得(既存の配置先にルーティング)
4. DOにリクエストを送信

既存リソースへのアクセスには設定の参照は不要です — すべてのルーティング情報がID自体に埋め込まれています。

キャッシュ戦略

Authrimは、データベース読み取りを最小化するために3層キャッシュ戦略を使用します。

block-beta
    columns 1
    kv["KVキャッシュ(グローバル、~60秒)
JWKS、OIDCメタデータ、設定"] do["DOインメモリ(シャード単位)
セッション、トークン、コード"] d1["D1データベース(永続)
信頼できるソース"]
  • KV: 結果整合性を持つグローバルKey-Valueストア。設定、公開鍵、読み取り頻度の高いデータに使用。
  • DOインメモリ: 各Durable Objectがインメモリ状態を維持。シャード内で強い一貫性のある読み取りを提供。
  • D1: 永続ストアであり信頼できるソース。すべての書き込みはD1へ、読み取りは可能な限りキャッシュから提供。

設定キャッシュ(リージョンシャード設定、パーティション設定)は、鮮度とパフォーマンスのバランスを取るために10秒のTTLを使用します。

次のステップ