認証・権限
一言でいうと
「誰が」「何を」「どこまで」できるかを決めるモジュール。認証は JWT ベース、権限モデルは Discord のロール方式(1ユーザーに複数ロールを割り当て、ロールごとに権限を付与)を採用している。認可判定そのもののアルゴリズムと primitives(ResourceType × Action × Scope)の詳細は 認可モデル にまとめてあるので、このページはモジュールの構造に絞る。
主要ドメイン概念
| 概念 | 役割 |
|---|---|
DynamicRole | テナントごとに定義できるロール。position(階層順位)を持つ |
UserRole | ユーザー ↔ ロールの多対多割り当て(Discord 方式:1人が複数ロールを持てる) |
PermissionRule | 権限の最小単位。ResourceType + Action + Scope の3値からなる sealed class(GeneralRule 等) |
RolePermission | ロール ↔ PermissionRule の割り当て |
AuthContext / AuthenticatedUserContext | リクエストごとの認証済みユーザー・テナント文脈 |
Backend 構造
core/auth/ は role の概念も内包している(domain/model/DynamicRole.kt 等はここにあり、別モジュールに role は存在しない)。
api/controller/:AuthController(ログイン/ログアウト)、AuthSetupController/BuiltInAuthController(初期セットアップ・組み込み認証)、RoleController/RolePermissionController/UserRoleController(ロール・権限・割り当て CRUD)、PermissionController、PlatformAdminController(運営者向け横断操作)、MyTenantsController、ResourceResolverController、DemoAuthControllerdomain/service/AuthorizationService: 権限・ロール管理の中心サービス("Centralized authorization service")。AuthorizationCacheでキャッシュし、CacheEvictionServiceが変更時に無効化するdomain/service/RoleHierarchyService: ロールの階層順位(position)を扱う。「自分より上位のロールは操作できない」といったガードの土台domain/service/UserRoleService: ユーザーへのロール割り当て・同期("following Discord's model where users can have multiple roles"、syncRolesForUser/syncMembersForRoleは差分計算してから適用する Discord 方式の同期)infrastructure/jwt/:JwtClaimsExtractor、TenantAwareJwtAuthenticationConverter(JWT からテナント文脈付きの認証情報へ変換)infrastructure/security/: Spring Security 設定domain/model/PermissionRule.kt:ResourceType+Action+Scopeの3値からなる sealed class。「文字列処理は一切ビジネスロジックで行わない」とコメントされており、DB 文字列表現への変換は Mapper 層に閉じている
Frontend 構造
backend の auth(role を含む)は frontend では auth と role の2モジュールに分かれている。
app/modules/auth/:composables/useDesktopAuth.ts(Tauri デスクトップの認証)、useDesktopSessionGuard.ts、usePlatformAdmin.ts、useSetup.ts(初期セットアップ)、repositories/AuthSetupRepository.tsapp/modules/role/:composables/useRoles.ts・useRoleForm.ts・useRoleHierarchy.ts・useRolePermissions.ts(ロール CRUD・階層・権限編集の UI ロジック)
他モジュールとの辺
- 全モジュール:
@PreAuthorize+AuthorizationServiceによるチェックはほぼ全 Controller が通る(認可モデル 参照) membership/tenant(frontendtenant): テナントメンバーシップ・招待は別モジュール。ロール割り当ての対象になるユーザーはここから来るoffice(WOPI):WopiAccessTokenAuthenticationのようにモジュール固有の認証方式がauthのAuthentication実装として追加されることがある(SandboxRenderAuthentication・ServiceAccountAuthentication・MediaAccessAuthenticationなど多数)rolesync: 外部システムとのロール同期(RoleSyncResultモデルはこのauth内にある)
テナント・主キーの指定はエンドポイントの種類ごとに規約が固定されている(ルート CLAUDE.md 参照):in-tenant エンドポイントは X-Tenant-Id ヘッダー(TenantContextFilter が RLS context を設定)、platform-admin の横断エンドポイントは /tenants/{tenantId}/ パス変数。query param でテナントを渡すのはどちらの規約にも当てはまらない逸脱として禁止されている。新しい認可判定を書く前に、同種 Controller が @PathVariable と @RequestHeader のどちらでテナントを取っているかを確認してから合わせること。