diff --git a/specs/063-entra-signin/tasks.md b/specs/063-entra-signin/tasks.md new file mode 100644 index 0000000..02d7552 --- /dev/null +++ b/specs/063-entra-signin/tasks.md @@ -0,0 +1,80 @@ +## Tasks: 063 — Entra Sign-in (Tenant Panel) v1 + +**Feature Branch**: `063-entra-signin` +**Created**: 2026-01-26 +**Status**: Draft (v1) +**Spec**: [specs/063-entra-signin/spec.md](specs/063-entra-signin/spec.md) +**Plan**: [specs/063-entra-signin/plan.md](specs/063-entra-signin/plan.md) + +--- + +### Phase 1: Setup & Core Authentication Flow + +* **Task 063.01**: Install and configure Laravel Socialite and Socialite Providers for Azure AD. + * Add `laravel/socialite` and `socialiteproviders/microsoft-azure-active-directory` to `composer.json`. + * Configure `config/services.php` for `azure` provider with `client_id`, `client_secret`, `redirect`. + * Update `.env.example` with placeholder variables (`AZURE_CLIENT_ID`, etc.). +* **Task 063.02**: Implement `SocialiteController` to handle redirect and callback. + * Create `app/Http/Controllers/Auth/AzureLoginController.php`. + * Define `redirect()` method to initiate Entra OIDC flow. + * Define `callback()` method to process Entra response. +* **Task 063.03**: Define authentication routes. + * Add routes to `routes/web.php` for `/auth/entra/redirect` and `/auth/entra/callback`. +* **Task 063.04**: Database migration for `users` table. + * Create migration to add `entra_tenant_id` (`uuid` or `string(36)`) and `entra_object_id` (`uuid` or `string(36)`) columns to `users` table. + * Add unique index `unique(['entra_tenant_id', 'entra_object_id'])`. + * Ensure `name` and `email` columns are compatible with Entra claims. +* **Task 063.05**: Implement user upsert logic in callback. + * In `callback()` method, use `User::updateOrCreate` based on `(entra_tenant_id, entra_object_id)`. + * Populate `name`, `email` from claims. + * Generate and regenerate session. +* **Task 063.06**: Handle OIDC failure safely (logging and redirect). + * Implement error handling in `callback()` for missing `tid`/`oid` claims. + * Redirect to `/admin/login` with generic error. + * Log `auth.entra.login` events with `success: false`, `reason_code`, `correlation_id` (no tokens/claims). + +### Phase 2: Filament Panel Integration & UX + +* **Task 063.07**: Override Filament login page for `/admin` panel. + * Create a custom Filament login page that replaces the default email/password form with a "Sign in with Microsoft" button. + * Link the button to `/auth/entra/redirect` route. +* **Task 063.08**: Implement `NoAccessPage`. + * Create a Filament page at `/admin/no-access` for users with 0 tenant memberships. + * Ensure it renders Filament UI and provides a user-friendly message. +* **Task 063.09**: Implement `TenantChooserPage`. + * Create a Filament page at `/admin/choose-tenant` for users with N > 1 tenant memberships. + * Display a list of available tenants, allowing the user to select one. + * Implement logic to redirect to the chosen tenant's dashboard. +* **Task 063.10**: Implement post-login routing logic. + * In `callback()` method, after successful user upsert and session regeneration: + * Retrieve user's tenant memberships. + * Implement conditional redirects: 0 memberships to `/admin/no-access`, 1 to tenant dashboard, N to `/admin/choose-tenant`. +* **Task 063.11**: Implement disabled user login blocking. + * In `callback()` method, after user upsert, check if the user is disabled/soft-deleted. + * If disabled, block login, redirect to `/admin/login` with generic error. + * Log `auth.entra.login` with `reason_code: user_disabled`. + +### Phase 3: Testing + +* **Task 063.12**: Write Unit Tests for core logic. + * Test `SocialiteController`'s `callback()` method logic (claim validation, upsert, disabled user check). + * Test `User` model methods related to Entra ID and tenant relationships. +* **Task 063.13**: Write Feature Tests for acceptance criteria. + * `AdminLoginIsEntraOnlyTest`. + * `EntraCallbackUpsertByTidOidTest`. + * `PostLoginRoutingByMembershipTest` (covering 0, 1, N memberships). + * `OidcFailureRedirectsSafelyTest`. + * `SessionSeparationSmokeTest`. + * `DisabledUserLoginIsBlockedTest`. +* **Task 063.14**: Write Browser Tests for end-to-end flows. + * Verify successful Entra login and redirection. + * Verify `TenantChooserPage` functionality. +* **Task 063.15**: Run `pint` for code style. + +### Phase 4: Documentation & Deployment + +* **Task 063.16**: Update documentation (README or in-app help) if needed. +* **Task 063.17**: Verify deployment considerations. + * Confirm environment variables are managed. + * Ensure `php artisan filament:assets` is in deployment pipeline. + * Update Dokploy config if necessary for new routes/pages.