Skip to main content
skill CX Codex

configure-auth — Claude Code skill: what it does, how to install

Adds authentication and authorization to a Blazor Web App based on its render mode. It prevents runtime crashes with Identity and interactive routing.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add dotnet/skills --skill configure-auth -a claude-code
Open on GitHub

What configure-auth does

The skill directs coding agents on implementing auth workflows in Blazor Web App projects. It starts by checking AGENTS.md at the workspace root to inspect the interactivity scope. Then it configures cascading auth state, registers ASP.NET Core Identity in Program.cs, and wires AuthorizeRouteView inside routing components.

A major pain point in Blazor stems from render modes. SignInManager and UserManager rely on HttpContext and throw exceptions when executed inside interactive server or client components. The skill resolves this by keeping login and register pages on static SSR and adding [ExcludeFromInteractiveRouting] in globally interactive setups.

For WebAssembly and Auto interactivity, it configures AddAuthenticationStateSerialization on the server and client-side deserialization. Skipping these calls drops authenticated users to an anonymous state once WebAssembly takes over.

What it helps with

  • register ASP.NET Core Identity and cascading auth state in Blazor
  • resolve SignInManager crashes inside interactive components
  • serialize user authentication state from server to WebAssembly
  • restrict page access via [Authorize] and conditional AuthorizeView markup

Example prompts for the agent

  • Configure ASP.NET Core Identity auth for this globally interactive Blazor Web App
  • Fix the InvalidOperationException from SignInManager on the Account/Login page
  • Set up auth state serialization between server and client for WebAssembly render mode

How to install configure-auth

1Skills CLI (Vercel)

npx skills add dotnet/skills --skill configure-auth -a claude-code

2Manually: put the files in place

~/.claude/skills/configure-auth/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/configure-auth/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about configure-auth

How do I install configure-auth in Claude Code?

Run npx skills add dotnet/skills --skill configure-auth -a claude-code in your terminal.

What does configure-auth do?

It provides step-by-step guidance for configuring authentication and authorization in Blazor Web Apps. It handles service registration, component protection with [Authorize], and render mode edge cases.

Why does SignInManager fail in interactive Blazor components?

SignInManager requires an active HttpContext to issue cookies, which is unavailable in interactive circuits. The skill ensures login pages render via static SSR using [ExcludeFromInteractiveRouting].

Source text

SKILL.md · MIT
---
license: MIT
name: configure-auth
description: >
  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).
---

# 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 mode | HttpContext.User | SignInManager | Auth state source | Key requirement |
|---|---|---|---|---|
| Static SSR | Available | Works | Server pipeline | Use middleware for redirects, `<NotAuthorized>` does NOT render |
| Server (interactive) | NOT available | Throws | `CascadingAuthenticationState` | Use `[Authorize]` + `AuthorizeView`, not `HttpContext` |
| WebAssembly | NOT available | Throws | Serialized from server | `AddAuthenticationStateSerialization` / `Deserialization` |
| Auto | NOT available after WASM | Throws | Serialized from server | Same as WebAssembly; register in **both** Program.cs files |

## Common Mistakes

| Mistake | Symptom | Fix |
|---------|---------|-----|
| Using `HttpContext.User` in interactive component | Null or stale claims | Use `[CascadingParameter] Task<AuthenticationState>` |
| `SignInManager` in interactive component | `InvalidOperationException` | Move to static SSR page with `[ExcludeFromInteractiveRouting]` |
| Missing `AddAuthenticationStateSerialization` | Anonymous user after WASM loads | Add to server Program.cs; add `Deserialization` to client Program.cs |
| `<NotAuthorized>` in static SSR layout | Content never shown | Static SSR uses middleware pipeline; redirect via `LoginPath` or `RedirectToLogin` component |
| Global interactivity without `AcceptsInteractiveRouting` | Identity pages crash | Add `AcceptsInteractiveRouting()` check in App.razor (Step 3) |
| Missing `AddCascadingAuthenticationState()` | `Task<AuthenticationState>` is null | Register in Program.cs (Step 2) |

© dotnet · MIT · dotnet/skills

Similar skills

All skills for Security →

From the same set101

android-tombstone-symbolication Turns native backtrace frames from an Android tombstone into function names, source files and line numbers for .NET apps. CX Codex +1 3,300installs migrate-static-to-wrapper Replaces static calls in C# with injected abstractions: DateTime.UtcNow becomes TimeProvider.GetUtcNow(), File.* becomes IFileSystem. Runs on one file, project, or namespace at a time. CX Codex +1 3,300installs template-instantiation Creates .NET projects using dotnet new while matching workspace CPM settings and target frameworks. Generates clean scaffolding without version mismatch. CX Codex +1 3,300installs template-discovery Finds suitable dotnet new templates from a project description, then checks parameters and expected output before files are created. CX Codex +1 3,300installs apple-crash-symbolication Turns raw addresses in an .ips crash log into function names, source files and line numbers for .NET. Useful when a MAUI or Mono app dies on iOS, tvOS, macOS or Mac Catalyst. CX Codex +1 3,100installs system-text-json-net11 A skill that tells the agent how to use three new System.Text.Json APIs in .NET 11 instead of writing the old workarounds. CX Codex +1 3,100installs maui-safe-area Safe area and edge-to-edge layout guidance for .NET 10+. Solves system bar overlaps and keyboard padding across Android, iOS, and Mac Catalyst. CX Codex +1 3,200installs maui-shell-navigation Set up Shell navigation in a .NET MAUI app, including tabs, flyout menus, and page transitions. Use it when routes or navigation parameters need attention. CX Codex +1 3,100installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor