|
| 1 | +--- |
| 2 | +name: implement-auth0-authentication |
| 3 | +description: 'Add Auth0 authentication and authorization to a Blazor Server or Blazor Web App with interactive server components. Includes role-based authorization, claims transformation, user profile page, and admin user management via Auth0 Management API. Prompts for Auth0 tenant credentials, client secrets, callback URLs, role claim namespace, and Management API M2M application. Use for implementing OAuth 2.0 OIDC login, role management, user administration, and secure Blazor authentication with Auth0.' |
| 4 | +argument-hint: '[optional: path to Blazor project directory]' |
| 5 | +--- |
| 6 | + |
| 7 | +# Implement Auth0 Authentication for Blazor |
| 8 | + |
| 9 | +Adds complete Auth0 authentication and authorization infrastructure to a Blazor Server or Blazor Web App with interactive server components, including role-based access control, a profile page, and optional admin user management. |
| 10 | + |
| 11 | +## When to Use |
| 12 | + |
| 13 | +- Adding Auth0 authentication to a new or existing Blazor Server or Blazor Web App |
| 14 | +- Implementing OAuth 2.0 OIDC login/logout with Auth0 |
| 15 | +- Setting up role-based authorization mapped from Auth0 claims |
| 16 | +- Creating a user profile page that displays claims and roles |
| 17 | +- Building admin pages that manage Auth0 users and roles via the Management API |
| 18 | +- Migrating from local cookie-only auth to Auth0 OIDC |
| 19 | +- Hardening login/logout flows with antiforgery and local-return-url validation |
| 20 | + |
| 21 | +## Prerequisites |
| 22 | + |
| 23 | +Before starting, ensure you have: |
| 24 | + |
| 25 | +1. **Auth0 Account**: Active Auth0 tenant |
| 26 | +2. **Web Application Configured in Auth0**: |
| 27 | + - Application Type: Regular Web Application |
| 28 | + - Allowed Callback URLs configured (for example `https://localhost:5001/callback`) |
| 29 | + - Allowed Logout URLs configured (for example `https://localhost:5001/`) |
| 30 | + - Domain, Client ID, and Client Secret available |
| 31 | +3. **Auth0 Management API M2M Application** (for admin user management features): |
| 32 | + - Application Type: Machine to Machine |
| 33 | + - Authorized for Auth0 Management API |
| 34 | + - Scopes granted: `read:users`, `update:users`, `read:roles`, `read:users_app_metadata`, `update:users_app_metadata` |
| 35 | + - Client ID, Client Secret, Domain, and Audience available |
| 36 | +4. **Role Configuration in Auth0**: |
| 37 | + - Roles created (for example `Admin`, `User`) |
| 38 | + - Auth0 Action or Rule configured to add roles to the ID token with a custom namespace such as `https://yourapp.com/roles` |
| 39 | + |
| 40 | +## What This Skill Does |
| 41 | + |
| 42 | +1. **Gathers Auth0 configuration** from the user (see [Configuration Prompts](./references/configuration-prompts.md)) |
| 43 | +2. **Adds or updates Auth0 packages**: |
| 44 | + - `Auth0.AspNetCore.Authentication` |
| 45 | + - `Auth0.ManagementApi` (if admin user management is requested) |
| 46 | + - If the repo uses Central Package Management, update `Directory.Packages.props` instead of adding versions in individual project files |
| 47 | +3. **Configures authentication** in `Program.cs` with `AddAuth0WebAppAuthentication` |
| 48 | +4. **Creates Auth infrastructure**: |
| 49 | + - `Auth/Auth0Options.cs` — configuration model |
| 50 | + - `Auth/Auth0ClaimsTransformation.cs` — maps Auth0 roles to ASP.NET Core `ClaimTypes.Role` |
| 51 | + - `Auth/AuthorizationRoles.cs` — role constants (`Admin`, `User`) |
| 52 | + - `Auth/AuthorizationPolicies.cs` — policy constants (`AdminPolicy`, `UserPolicy`) |
| 53 | +5. **Maps explicit login/logout endpoints**: |
| 54 | + - `GET /account/login` validates the `returnUrl` before calling the Auth0 challenge |
| 55 | + - `POST /account/logout` uses antiforgery and signs out of both Auth0 and the local cookie |
| 56 | + - `/callback` remains handled by the Auth0 SDK |
| 57 | +6. **Creates login/logout UI components**: |
| 58 | + - `Components/Layout/LoginDisplay.razor` — login/logout buttons with user greeting |
| 59 | + - `Components/Layout/LoginComponent.razor` — minimal login/logout form |
| 60 | +7. **Creates a user profile page**: |
| 61 | + - `Components/User/Profile.razor` — displays claims, roles, profile picture, and email |
| 62 | +8. **Creates admin user management** (optional): |
| 63 | + - `Features/Admin/Users/Auth0ManagementOptions.cs` |
| 64 | + - `Features/Admin/Users/UserManagementExtensions.cs` |
| 65 | + - `Features/Admin/Users/UserManagementService.cs` |
| 66 | + - `Domain/Features/Admin/Abstractions/IUserManagementService.cs` |
| 67 | + - `Domain/Features/Admin/Models/AdminUserSummary.cs` |
| 68 | + - `Domain/Features/Admin/Models/RoleAssignment.cs` |
| 69 | + - `Components/Pages/Admin/Users.razor` |
| 70 | + - `Components/Admin/Users/EditUserRolesModal.razor` |
| 71 | + - `Components/Admin/Users/UserListTable.razor` |
| 72 | + - `Components/Admin/Users/RoleBadge.razor` |
| 73 | + - `Components/Admin/Users/UserAuditLogPanel.razor` (optional) |
| 74 | +9. **Configures `appsettings.json` placeholders and user secrets** for sensitive values |
| 75 | +10. **Adds cascading authentication state, middleware, and verification guidance** |
| 76 | + |
| 77 | +## Procedure |
| 78 | + |
| 79 | +### Step 1: Gather Configuration |
| 80 | + |
| 81 | +Prompt the user for the required values before making changes. Use [Configuration Prompts](./references/configuration-prompts.md). |
| 82 | + |
| 83 | +**Auth0 Web Application (OIDC):** |
| 84 | +- `Auth0:Domain` |
| 85 | +- `Auth0:ClientId` |
| 86 | +- `Auth0:ClientSecret` |
| 87 | +- `Auth0:RoleClaimNamespace` |
| 88 | + |
| 89 | +**Auth0 Management API M2M Application (optional):** |
| 90 | +- `Auth0Management:ClientId` |
| 91 | +- `Auth0Management:ClientSecret` |
| 92 | +- `Auth0Management:Domain` |
| 93 | +- `Auth0Management:Audience` |
| 94 | + |
| 95 | +**Callback and Logout URLs:** |
| 96 | +- Callback URL (for example `https://localhost:5001/callback`) |
| 97 | +- Logout URL (for example `https://localhost:5001/`) |
| 98 | + |
| 99 | +**Feature Selection:** |
| 100 | +- Whether to include admin user management pages |
| 101 | +- Whether to create a user profile page |
| 102 | + |
| 103 | +### Step 2: Add the Required Packages |
| 104 | + |
| 105 | +If the repo does **not** use Central Package Management: |
| 106 | + |
| 107 | +```bash |
| 108 | +dotnet add package Auth0.AspNetCore.Authentication |
| 109 | +``` |
| 110 | + |
| 111 | +If admin user management is requested: |
| 112 | + |
| 113 | +```bash |
| 114 | +dotnet add package Auth0.ManagementApi |
| 115 | +``` |
| 116 | + |
| 117 | +If the repo **does** use Central Package Management, update `Directory.Packages.props` instead of setting package versions in project files. |
| 118 | + |
| 119 | +### Step 3: Create Auth Infrastructure |
| 120 | + |
| 121 | +Create the following files in the `Auth/` folder if they do not already exist: |
| 122 | + |
| 123 | +- `Auth/Auth0Options.cs` |
| 124 | +- `Auth/Auth0ClaimsTransformation.cs` |
| 125 | +- `Auth/AuthorizationRoles.cs` |
| 126 | +- `Auth/AuthorizationPolicies.cs` |
| 127 | + |
| 128 | +See [Auth0 Implementation](./references/auth-implementation.md) for the current code patterns. |
| 129 | + |
| 130 | +### Step 4: Configure Authentication in Program.cs |
| 131 | + |
| 132 | +Add the Auth0 authentication configuration shown in [Program.cs Configuration](./references/program-configuration.md), including: |
| 133 | + |
| 134 | +- Cookie auth in `Testing` |
| 135 | +- `AddAuth0WebAppAuthentication` for non-test environments |
| 136 | +- `IClaimsTransformation` registration |
| 137 | +- Authorization policy registration |
| 138 | +- `AddCascadingAuthenticationState()` |
| 139 | +- Explicit `UseAuthentication()`, `UseAuthorization()`, and `UseAntiforgery()` middleware |
| 140 | + |
| 141 | +### Step 5: Map Secure Login/Logout Endpoints |
| 142 | + |
| 143 | +Create the endpoint pattern documented in [Program.cs Configuration](./references/program-configuration.md): |
| 144 | + |
| 145 | +- `GET /account/login` accepts `returnUrl`, rejects non-local redirect targets, and challenges the Auth0 scheme |
| 146 | +- `POST /account/logout` requires authorization, includes antiforgery, and signs out of both Auth0 and the cookie scheme |
| 147 | +- In `Testing`, add a lightweight `/test/login` endpoint so E2E tests do not depend on Auth0 |
| 148 | + |
| 149 | +### Step 6: Create Login/Logout UI Components |
| 150 | + |
| 151 | +Use the secure UI patterns in [Auth0 Implementation](./references/auth-implementation.md): |
| 152 | + |
| 153 | +- `Components/Layout/LoginDisplay.razor` |
| 154 | +- `Components/Layout/LoginComponent.razor` |
| 155 | + |
| 156 | +Prefer base-relative `returnUrl` values so they pass local-url validation. |
| 157 | + |
| 158 | +### Step 7: Create the User Profile Page |
| 159 | + |
| 160 | +If requested, add `Components/User/Profile.razor` using the example in [Auth0 Implementation](./references/auth-implementation.md). |
| 161 | + |
| 162 | +### Step 8: Create Admin User Management |
| 163 | + |
| 164 | +If admin user management was requested, create: |
| 165 | + |
| 166 | +- `Domain/Features/Admin/Abstractions/IUserManagementService.cs` |
| 167 | +- `Domain/Features/Admin/Models/AdminUserSummary.cs` |
| 168 | +- `Domain/Features/Admin/Models/RoleAssignment.cs` |
| 169 | +- `Features/Admin/Users/Auth0ManagementOptions.cs` |
| 170 | +- `Features/Admin/Users/UserManagementExtensions.cs` |
| 171 | +- `Features/Admin/Users/UserManagementService.cs` |
| 172 | +- Admin UI components under `Components/Pages/Admin/Users.razor` and `Components/Admin/Users/` |
| 173 | + |
| 174 | +The current reference implementation targets **Auth0.ManagementApi v8** and uses: |
| 175 | + |
| 176 | +- `IManagementApiClient` |
| 177 | +- `ManagementClient` |
| 178 | +- `ManagementClientOptions` |
| 179 | +- `ClientCredentialsTokenProvider` |
| 180 | +- `Auth0.ManagementApi.Users` request/response types |
| 181 | + |
| 182 | +See [Admin User Management](./references/admin-user-management.md). |
| 183 | + |
| 184 | +### Step 9: Configure appsettings and User Secrets |
| 185 | + |
| 186 | +Add placeholder configuration to `appsettings.json`: |
| 187 | + |
| 188 | +```json |
| 189 | +{ |
| 190 | + "Auth0": { |
| 191 | + "Domain": "", |
| 192 | + "ClientId": "", |
| 193 | + "ClientSecret": "", |
| 194 | + "RoleClaimNamespace": "" |
| 195 | + }, |
| 196 | + "Auth0Management": { |
| 197 | + "ClientId": "", |
| 198 | + "ClientSecret": "", |
| 199 | + "Domain": "", |
| 200 | + "Audience": "" |
| 201 | + } |
| 202 | +} |
| 203 | +``` |
| 204 | + |
| 205 | +Store secrets with `dotnet user-secrets` during development. Use Azure Key Vault, environment variables, or another secure secret store in production. |
| 206 | + |
| 207 | +### Step 10: Verify the Integration |
| 208 | + |
| 209 | +1. Ensure `UseAuthentication()`, `UseAuthorization()`, and `UseAntiforgery()` are present in the middleware pipeline |
| 210 | +2. Ensure `AddCascadingAuthenticationState()` is registered |
| 211 | +3. Verify Auth0 callback and logout URLs match the deployed app URLs |
| 212 | +4. Test login/logout flows |
| 213 | +5. Verify role claims are mapped correctly on the profile page |
| 214 | +6. If admin features are enabled, verify user list and role assignment flows |
| 215 | + |
| 216 | +## Post-Implementation Testing |
| 217 | + |
| 218 | +### Test Login Flow |
| 219 | + |
| 220 | +1. Navigate to the application |
| 221 | +2. Click **Log in** and verify the app redirects to Auth0 Universal Login |
| 222 | +3. Authenticate with Auth0 credentials |
| 223 | +4. Verify the app returns to the requested local page |
| 224 | +5. Verify the user name appears in navigation |
| 225 | + |
| 226 | +### Test Role Mapping |
| 227 | + |
| 228 | +1. Log in with a user that has roles assigned in Auth0 |
| 229 | +2. Navigate to `/profile` |
| 230 | +3. Verify roles appear under **Roles & Permissions** |
| 231 | +4. Verify the standard role claim type contains the mapped roles |
| 232 | + |
| 233 | +### Test Authorization |
| 234 | + |
| 235 | +1. Log in with a non-admin user |
| 236 | +2. Attempt to access `/admin/users` and verify access is denied |
| 237 | +3. Log in with an admin user |
| 238 | +4. Verify `/admin/users` loads successfully |
| 239 | + |
| 240 | +### Test Admin User Management |
| 241 | + |
| 242 | +1. Log in as an admin |
| 243 | +2. Navigate to `/admin/users` |
| 244 | +3. Verify the user list loads |
| 245 | +4. Open the role editor for a user |
| 246 | +5. Assign and remove roles |
| 247 | +6. Verify changes persist in Auth0 |
| 248 | + |
| 249 | +## Troubleshooting |
| 250 | + |
| 251 | +### Roles Not Appearing |
| 252 | + |
| 253 | +- **Cause**: `Auth0:RoleClaimNamespace` does not match the namespace in the Auth0 Action or Rule |
| 254 | +- **Fix**: Update `Auth0:RoleClaimNamespace` to match exactly |
| 255 | +- **Fallback**: `Auth0ClaimsTransformation` also checks the standard `roles` claim and auto-detects namespaced claims ending in `/roles` |
| 256 | + |
| 257 | +### Login Redirects to the Wrong Page |
| 258 | + |
| 259 | +- **Cause**: The UI passed an absolute URL or another non-local redirect target |
| 260 | +- **Fix**: Generate a base-relative `returnUrl` and keep the local-URL validation in the login endpoint |
| 261 | + |
| 262 | +### Management API Calls Fail |
| 263 | + |
| 264 | +- **Cause**: The M2M app is missing scopes or has the wrong audience/domain |
| 265 | +- **Fix**: Re-check the Auth0 Management API authorization settings and the `Auth0Management` configuration section |
| 266 | + |
| 267 | +### 401 or Token Errors from the Management API |
| 268 | + |
| 269 | +- **Cause**: `ClientCredentialsTokenProvider` is misconfigured, the secret is wrong, or the audience/domain does not match the tenant |
| 270 | +- **Fix**: Verify `AddUserManagement()` registers `ManagementClient` with the correct domain, client ID, client secret, and audience |
| 271 | + |
| 272 | +## Architecture Decisions |
| 273 | + |
| 274 | +1. **Role Claim Mapping**: Use `IClaimsTransformation` to map Auth0 role claims to `ClaimTypes.Role` so ASP.NET Core policies and `RequireRole()` work normally. |
| 275 | +2. **Multi-Pass Role Detection**: Check the configured namespace first, then `roles`, then any namespaced claim ending in `/roles`. |
| 276 | +3. **Auth0.ManagementApi v8**: Prefer `IManagementApiClient` plus `ClientCredentialsTokenProvider` over manual token-fetch code. |
| 277 | +4. **Result-Based Error Handling**: Return `Result<T>` or `Result<bool>` for expected failures instead of relying on exception-driven flow. |
| 278 | +5. **Cache Strategy**: Cache role lookup data in `IMemoryCache` and user/list responses in `IDistributedCache` when those dependencies exist. |
| 279 | +6. **Testing Mode**: Use cookie auth plus a testing-only login endpoint so E2E runs do not depend on Auth0. |
| 280 | + |
| 281 | +## References |
| 282 | + |
| 283 | +- [Auth0 ASP.NET Core SDK Documentation](https://auth0.com/docs/quickstart/webapp/aspnet-core) |
| 284 | +- [Auth0 Management API Documentation](https://auth0.com/docs/api/management/v2) |
| 285 | +- [Auth0 Actions (Custom Claims)](https://auth0.com/docs/customize/actions) |
| 286 | +- [ASP.NET Core Authorization](https://learn.microsoft.com/aspnet/core/security/authorization/introduction) |
| 287 | + |
| 288 | +## Additional Files |
| 289 | + |
| 290 | +- [Configuration Prompts](./references/configuration-prompts.md) |
| 291 | +- [Program.cs Configuration](./references/program-configuration.md) |
| 292 | +- [Auth0 Implementation](./references/auth-implementation.md) |
| 293 | +- [Admin User Management](./references/admin-user-management.md) |
0 commit comments