dotnet/skills

configure-auth

Add authentication and authorization to a Blazor Web App, accounting for the app's render mode.

Zobacz źródło
Oryginalny dokument Skill

Treść z repozytorium z zachowaniem nagłówków, przykładów, kodu, tabel, linków i obrazów.

Configure Auth

Step 1 — Read AGENTS.md

Read AGENTS.md at the workspace root for the project's interactivity mode and scope before making changes.

Step 2 — Register auth services in Program.cs

csharp
// Program.cs (server project)
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthorization();

For ASP.NET Core Identity add the Identity services:

csharp
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = IdentityConstants.ApplicationScheme;
    options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies();

builder.Services.AddIdentityCore<ApplicationUser>()
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddSignInManager()
    .AddDefaultTokenProviders();

Step 3 — Wire App.razor for auth and render mode

The App.razor component must use AuthorizeRouteView and conditionally apply the render mode so that pages excluded from interactive routing render statically.

razor
<!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;
}

In Routes.razor (or wherever the router lives), use AuthorizeRouteView:

razor
<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>

Step 4 — Protect pages and components

[Authorize] attribute on pages

razor
@page "/admin"
@attribute [Authorize]

With roles or policies:

razor
@attribute [Authorize(Roles = "Admin")]
@attribute [Authorize(Policy = "RequireManager")]

AuthorizeView for conditional UI

razor
<AuthorizeView>
    <Authorized>Welcome, @context.User.Identity?.Name!</Authorized>
    <NotAuthorized><a href="Account/Login">Log in</a></NotAuthorized>
</AuthorizeView>

Role/policy variants:

razor
<AuthorizeView Roles="Admin,Manager">
    <Authorized>Admin content here</Authorized>
</AuthorizeView>

Access auth state in code

csharp
[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");
    }
}

Step 5 — Identity pages must stay static SSR

SignInManager and UserManager use HttpContext internally and throw in interactive components. Identity pages (login, register, manage) must render as static SSR.

In a globally interactive app, mark every Identity page:

razor
@page "/Account/Login"
@attribute [ExcludeFromInteractiveRouting]

This forces a full-page navigation (exits the interactive circuit) so the page renders through the static SSR pipeline with a real HttpContext.

App.razor must use AcceptsInteractiveRouting() (Step 3) to return null for these pages — otherwise the framework still tries to render them interactively.

In a per-page app, Identity pages are static by default (no @rendermode directive), so [ExcludeFromInteractiveRouting] is not needed.

Step 6 — Auth state in WebAssembly / Auto mode

WebAssembly components run in the browser and have no HttpContext. Auth state must be serialized from the server during prerendering and deserialized on the client.

Server `Program.cs`:

csharp
builder.Services.AddAuthenticationStateSerialization();

Client `.Client/Program.cs`:

csharp
builder.Services.AddAuthenticationStateDeserialization();

Without these calls, Task<AuthenticationState> resolves to an anonymous user after WebAssembly takes over from prerendering.

AddAuthenticationStateSerialization accepts options to include role and claim data:

csharp
builder.Services.AddAuthenticationStateSerialization(options =>
    options.SerializeAllClaims = true);

Render Mode × Auth Matrix

Render modeHttpContext.UserSignInManagerAuth state sourceKey requirement
Static SSRAvailableWorksServer pipelineUse middleware for redirects, <NotAuthorized> does NOT render
Server (interactive)NOT availableThrowsCascadingAuthenticationStateUse [Authorize] + AuthorizeView, not HttpContext
WebAssemblyNOT availableThrowsSerialized from serverAddAuthenticationStateSerialization / Deserialization
AutoNOT available after WASMThrowsSerialized from serverSame as WebAssembly; register in both Program.cs files

Common Mistakes

MistakeSymptomFix
Using HttpContext.User in interactive componentNull or stale claimsUse [CascadingParameter] Task<AuthenticationState>
SignInManager in interactive componentInvalidOperationExceptionMove to static SSR page with [ExcludeFromInteractiveRouting]
Missing AddAuthenticationStateSerializationAnonymous user after WASM loadsAdd to server Program.cs; add Deserialization to client Program.cs
<NotAuthorized> in static SSR layoutContent never shownStatic SSR uses middleware pipeline; redirect via LoginPath or RedirectToLogin component
Global interactivity without AcceptsInteractiveRoutingIdentity pages crashAdd AcceptsInteractiveRouting() check in App.razor (Step 3)
Missing AddCascadingAuthenticationState()Task<AuthenticationState> is nullRegister in Program.cs (Step 2)
z tego samego repozytorium

Więcej Skills

Wszystkie Skills
dotnet
Społeczność

test-value-evidence

- Assess tests for an identified code or test change, feature, PR or commit. USE FOR: review changed behavior or regression tests, prove pre-fix/missing behavior is detected, revision-bound red-green evidence. Polyglot. DO NOT USE without an identified change: hypothetical mutations or general suite blind spots (test-gap-analysis). Also exclude per-test readiness/A-F grades (grade-tests), coverage (coverage-analysis), new suites (code-testing), or mutation engines.

instalacje
3
GitHub Stars
5,6 tys.
Aktualizacja
13 paź
dotnet
Społeczność

agentic-workflows

Route gh-aw workflow design/create/debug/upgrade requests to the right prompts.

instalacje
2
GitHub Stars
5,6 tys.
Aktualizacja
11 paź
dotnet
Społeczność

analyzing-dotnet-performance

- Scans .NET code for ~50 performance anti-patterns across async, memory, strings, collections, LINQ, regex, serialization, and I/O with tiered severity classification. Use when analyzing .NET code for optimization opportunities, reviewing hot paths, or auditing allocation-heavy patterns.

instalacje
2
GitHub Stars
5,6 tys.
Aktualizacja
11 paź
dotnet
Społeczność

android-tombstone-symbolication

Symbolicate the .NET runtime frames in an Android tombstone file. Extracts BuildIds and PC offsets from the native backtrace, downloads debug symbols from the Microsoft symbol server, and runs llvm-symbolizer to produce function names with source file and line numbers. USE FOR triaging a .NET MAUI or Mono Android app crash from a tombstone, resolving native backtrace frames in libmonosgen-2.0.so or libcoreclr.so to .NET runtime source code, or investigating SIGABRT, SIGSEGV, or other native sign

instalacje
2
GitHub Stars
5,6 tys.
Aktualizacja
11 paź