Loading...
Loading...
Add authentication and authorization to a Blazor Web App, accounting for the app's render mode. USE WHEN the user needs [Authorize] on pages, AuthorizeView, role or policy-based access, login/logout Identity pages, or AuthenticationStateProvider. Also USE WHEN auth state is null after WebAssembly loads, SignInManager throws in an interactive component, <NotAuthorized> content never renders in static SSR, or HttpContext.User is null in an interactive component. DO NOT USE for general component authoring (see author-component), for prerendering concerns unrelated to auth (see support-prerendering), or for managing non-auth cascading state (see coordinate-components).
npx skill4agent add dotnet/skills configure-authAGENTS.md// Program.cs (server project)
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthorization();builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = IdentityConstants.ApplicationScheme;
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies();
builder.Services.AddIdentityCore<ApplicationUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddSignInManager()
.AddDefaultTokenProviders();App.razorAuthorizeRouteView<!DOCTYPE html>
<html>
<head>
<HeadOutlet @rendermode="RenderModeForPage" />
</head>
<body>
<Routes @rendermode="RenderModeForPage" />
<script src="_framework/blazor.web.js"></script>
</body>
</html>
@code {
[CascadingParameter]
public HttpContext HttpContext { get; set; } = default!;
private IComponentRenderMode? RenderModeForPage =>
HttpContext.AcceptsInteractiveRouting()
? InteractiveServer // replace with the app's render mode
: null;
}Routes.razorAuthorizeRouteView<Router AppAssembly="typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="routeData"
DefaultLayout="typeof(Layout.MainLayout)">
<NotAuthorized>
@if (context.User.Identity?.IsAuthenticated != true)
{
<RedirectToLogin />
}
else
{
<p>You are not authorized to access this resource.</p>
}
</NotAuthorized>
</AuthorizeRouteView>
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
</Router>@page "/admin"
@attribute [Authorize]@attribute [Authorize(Roles = "Admin")]
@attribute [Authorize(Policy = "RequireManager")]<AuthorizeView>
<Authorized>Welcome, @context.User.Identity?.Name!</Authorized>
<NotAuthorized><a href="Account/Login">Log in</a></NotAuthorized>
</AuthorizeView><AuthorizeView Roles="Admin,Manager">
<Authorized>Admin content here</Authorized>
</AuthorizeView>[CascadingParameter]
private Task<AuthenticationState>? AuthState { get; set; }
protected override async Task OnInitializedAsync()
{
if (AuthState is not null)
{
var state = await AuthState;
var isAdmin = state.User.IsInRole("Admin");
}
}SignInManagerUserManagerHttpContext@page "/Account/Login"
@attribute [ExcludeFromInteractiveRouting]HttpContextApp.razorAcceptsInteractiveRouting()null@rendermode[ExcludeFromInteractiveRouting]HttpContextProgram.csbuilder.Services.AddAuthenticationStateSerialization();.Client/Program.csbuilder.Services.AddAuthenticationStateDeserialization();Task<AuthenticationState>AddAuthenticationStateSerializationbuilder.Services.AddAuthenticationStateSerialization(options =>
options.SerializeAllClaims = true);| Render mode | HttpContext.User | SignInManager | Auth state source | Key requirement |
|---|---|---|---|---|
| Static SSR | Available | Works | Server pipeline | Use middleware for redirects, |
| Server (interactive) | NOT available | Throws | | Use |
| WebAssembly | NOT available | Throws | Serialized from server | |
| Auto | NOT available after WASM | Throws | Serialized from server | Same as WebAssembly; register in both Program.cs files |
| Mistake | Symptom | Fix |
|---|---|---|
Using | Null or stale claims | Use |
| | Move to static SSR page with |
Missing | Anonymous user after WASM loads | Add to server Program.cs; add |
| Content never shown | Static SSR uses middleware pipeline; redirect via |
Global interactivity without | Identity pages crash | Add |
Missing | | Register in Program.cs (Step 2) |