ミドルウェア
Lase が提供するミドルウェアの一覧です。LaseServiceProvider によって自動登録されます。
IdentifyTenant
エイリアス: tenant
テナント API のすべてのルートに適用されます。サブドメインからテナントを識別し、リクエストにテナントオブジェクトをセットします。
動作
- ルートパラメータ
tenantCode(サブドメイン)を取得 Cache::remember("tenant:{code}", 60min)でテナントを取得- テナントが存在しない場合は
404 NotFoundを返す - テナントが緊急停止中(
suspended_atがNULLでない)の場合は403 Forbidden(code: TENANT_SUSPENDED)を返す $request->attributes->set('tenant', $tenant)でテナントをセット- ルートパラメータから
tenantCodeを削除
緊急停止時の遮断
テナント API はすべてこのミドルウェアを通るため、緊急停止の遮断はここで行います。テナントの識別は認証より前に行われるため、この時点では相手が運営かどうかを判定できません。停止中でも調査・復旧ができるよう、RestrictTenantIpAddress と同じ lase.ip_restriction.allowlist の IP からのアクセスは通します。
テナント API 以外の経路は、それぞれ個別に遮断しています。
| 経路 | 遮断箇所 |
|---|---|
| 管理 API(運営) | 遮断しません。停止中のテナントも管理画面から操作できます |
| テナントログイントークンの発行 | Public\AuthController::issueTenantLoginToken |
| MCP | DefaultMcpTenantEligibility |
| キュー・バッチ | HTTP を通らないため Tenant::query()->active() で絞ります。契約は維持されるため、サブスクリプションの更新は停止中も行われます |
コントローラでの使い方
public function index(Request $request)
{
$tenant = $request->attributes->get('tenant');
// または
$tenant = app('tenant'); // アプリ側でバインドしている場合
}Authorize
エイリアス: authorize
ログイン中のユーザーがリクエストされたコンテキスト(admin または tenant)に属するかを検証します。
Route::middleware(['auth', 'authorize:admin'])->group(function () { ... });
Route::middleware(['auth', 'authorize:tenant'])->group(function () { ... });検証ロジックは AuthorizerRegistry に登録された Authorizer が担います。
カスタム Authorizer の登録
AppServiceProvider などで独自の Authorizer を登録できます。
use CodebaseJp\Lase\Auth\AuthorizerRegistry;
public function boot(AuthorizerRegistry $registry): void
{
$registry->register('admin', new MyCustomAdminAuthorizer());
}EnsureTenantPermission
エイリアス: tenant.can
ログイン中のテナントユーザーが、指定した権限(TenantPermission)を持っているかを検証します。持っていない場合は 403 Forbidden を返します。
Route::middleware(['auth', 'authorize:tenant'])->group(function () {
Route::middleware('tenant.can:contract:read')->group(function () {
Route::resource('plans', PlanController::class)->only(['index', 'show']);
});
// 複数指定した場合はいずれかを持っていれば通す
Route::middleware('tenant.can:setting:read,setting:write')->get('setting', [SettingController::class, 'show']);
});注意
- 権限のコンテキストは自分で用意するため、
authorize:tenantとの順序に依存しません(先に走っていれば何もしません)。テナントのメンバーでない場合はauthorize:tenantと同じく403 Forbiddenになります。 - 権限の値は
config('lase.enums.tenant_permission')(アプリ側の Enum)→ Lase のTenantPermissionの順に解決します。どちらにも定義されていない値を指定するとInvalidArgumentExceptionになります。 - 判定は
User::hasTenantPermission()に委譲するため、*(全権限)を持つ役割はすべて通ります。 - 拒否は
Illuminate\Auth\Access\AuthorizationException(未ログインはIlluminate\Auth\AuthenticationException)で投げるため、ポリシーによる拒否と同じ経路でハンドリングされます。
EnsureSenterRegistered
エイリアス: tenant.senter
テナントが Senter に顧客と契約を持つようにしてから通します(SenterService::ensureTenantRegistered())。補えなければ原因をログに残し、503 を返します。契約の画面の API(/api/tenant/senter/*)で、tenant.can のあとに置きます。
Route::middleware(['tenant.can:contract:read', 'tenant.senter'])->group(function () {
Route::get('contract', [SenterController::class, 'getContract']);
});RestrictTenantIpAddress
エイリアス: tenant.restrict_ip
テナント API のすべてのルートに適用されます。テナントごとに許可 IP を設定でき、リスト外からのアクセスを 403 Forbidden で拒否します。
TenantAllowedIpテーブルの CIDR レコードをCache::remember("tenant:{code}:allowed_ips", 60min)で取得- レコードが存在しない場合は制限なし(全 IP 許可)
- CIDR 表記(例:
203.0.113.0/24)と単一 IP の両方に対応 - 拒否時は
403 Forbiddenを返し、警告ログを記録
テナントに TenantAllowedIp レコードを登録することで制限が有効になります。レコードが1件もなければ制限は無効です。
RestrictIpAddress
エイリアス: restrict_ip
config('lase.ip_restriction.enabled') が true の場合に、ホワイトリスト外の IP アドレスからのアクセスを 403 Forbidden で拒否します。
設定
IP_RESTRICTION_ENABLED=true
IP_RESTRICTION_ALLOWLIST=203.0.113.1,203.0.113.2管理画面ルートにのみ適用することを推奨します。
Route::middleware(['restrict_ip'])->group(function () {
// 管理者向けルート
});