| name | dotnet-blazor-auth |
| description | Implements Blazor auth flows -- login/logout, AuthorizeView, Identity UI, OIDC. |
| allowed-tools | ["Read","Grep","Glob","Bash","Write","Edit"] |
dotnet-blazor-auth
Authentication and authorization across all Blazor hosting models. Covers AuthorizeView, CascadingAuthenticationState,
Identity UI scaffolding, role/policy-based authorization, per-hosting-model auth flow differences (cookie vs token), and
external identity providers.
Scope
- Auth flow per Blazor hosting model (Server, WASM, Auto, SSR, Hybrid)
- AuthorizeView and CascadingAuthenticationState patterns
- Identity UI scaffolding and customization
- Role/policy-based authorization in Blazor
- Client-side token handling and external identity providers
- Explicit login/logout/auth UI implementation tasks for Blazor apps
Out of scope
- JWT token generation and validation -- see [skill:dotnet-api-security]
- OWASP security principles -- see [skill:dotnet-security-owasp]
- CSRF/XSS/CSP/rate-limiting hardening without auth-flow work -- see [skill:dotnet-security-owasp]
- Hardening-only reviews of existing login pages without auth-flow implementation changes -- see
[skill:dotnet-security-owasp]
- bUnit testing of auth components -- see [skill:dotnet-blazor-testing]
- E2E auth testing -- see [skill:dotnet-playwright]
- UI framework selection -- see [skill:dotnet-ui-chooser]
Cross-references: [skill:dotnet-api-security] for API-level auth, [skill:dotnet-security-owasp] for OWASP principles,
[skill:dotnet-blazor-patterns] for hosting models, [skill:dotnet-blazor-components] for component architecture,
[skill:dotnet-blazor-testing] for bUnit testing, [skill:dotnet-playwright] for E2E testing, [skill:dotnet-ui-chooser]
for framework selection.
Routing note: do not load this skill for OWASP hardening reviews unless the task explicitly includes Blazor auth flow/UI
implementation.
Auth Flow per Hosting Model
Authentication patterns differ significantly across Blazor hosting models:
| Concern | InteractiveServer | InteractiveWebAssembly | InteractiveAuto | Static SSR | Hybrid |
|---|
| Auth mechanism | Cookie-based (server-side) | Token-based (JWT/OIDC) | Cookie (Server phase), Token (WASM phase) | Cookie-based (standard ASP.NET Core) | Platform-native or cookie |
| User state access | Direct HttpContext access | AuthenticationStateProvider | Varies by phase | HttpContext | Platform auth APIs |
| Token storage | Not needed (cookie) | localStorage or sessionStorage | Transition from cookie to token | Not needed (cookie) | Secure storage (Keychain, etc.) |
| Refresh handling | Circuit reconnection | Token refresh via interceptor | Automatic | Standard cookie renewal | Platform-specific |
InteractiveServer Auth
Server-side Blazor uses cookie authentication. The user authenticates via a standard ASP.NET Core login flow, and the
cookie is sent with the initial HTTP request that establishes the SignalR circuit.
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Account/Login";
options.AccessDeniedPath = "/Account/AccessDenied";
});
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthorization();
```text
**Gotcha:** `HttpContext` is available during the initial HTTP request but is `null` inside interactive components after
the SignalR circuit is established. Do not access `HttpContext` in interactive component lifecycle methods. Use
`AuthenticationStateProvider` instead.
### InteractiveWebAssembly Auth
WASM runs in the browser. Cookie auth works for same-origin APIs (and Backend-for-Frontend / BFF patterns), but
token-based auth (OIDC/JWT) is the standard approach for cross-origin APIs and delegated access scenarios:
```csharp
builder.Services.AddOidcAuthentication(options =>
{
options.ProviderOptions.Authority = "https://login.example.com";
options.ProviderOptions.ClientId = "blazor-wasm-client";
options.ProviderOptions.ResponseType = "code";
options.ProviderOptions.DefaultScopes.Add("api");
});
```text
```csharp
builder.Services.AddHttpClient("API", client =>
client.BaseAddress = new Uri("https://api.example.com"))
.AddHttpMessageHandler(sp =>
sp.GetRequiredService<AuthorizationMessageHandler>()
.ConfigureHandler(
authorizedUrls: [],
scopes: []));
builder.Services.AddScoped(sp =>
sp.GetRequiredService<IHttpClientFactory>().CreateClient());
```text
;
builder.Services.AddCascadingAuthenticationState();
```text
```csharp
builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<AuthenticationStateProvider, MauiAuthStateProvider>();
:
{
{
token = SecureStorage.Default.GetAsync();
(.IsNullOrEmpty(token))
{
AuthenticationState( ClaimsPrincipal( ClaimsIdentity()));
}
claims = ParseClaimsFromJwt(token);
identity = ClaimsIdentity(claims, );
AuthenticationState( ClaimsPrincipal(identity));
}
}
```text
---
`AuthorizeView` conditionally renders content based the users built- storage
mechanisms PKCE.
**Do forget `AddCascadingAuthenticationState()`.** Without it, `[CascadingParameter] Task<AuthenticationState>`
always `` components, silently breaking auth checks.
**Do use `AddIdentity` `AddDefaultIdentity` together.** `AddDefaultIdentity` includes UI scaffolding;
`AddIdentity` does . Choose one based whether you want the Identity UI pages.
---
- .NET + (Blazor Web App render modes, `AddCascadingAuthenticationState` service registration)
- `Microsoft.AspNetCore.Identity.EntityFrameworkCore` Identity EF Core
- `Microsoft.AspNetCore.Identity.UI` Identity UI scaffolding
- `Microsoft.AspNetCore.Authentication.MicrosoftAccount` / `.Google` external providers
- `Microsoft.Authentication.WebAssembly.Msal`