Token导航 LogoToken导航TokenDH.com
研究检索敏感数据github未标认证来源可访问许可证需确认审计异常

dotnet-blazor-authdotnet blazor 身份验证

Agent Skill

用于辅助安全审计、权限检查、凭据风险、认证流程和常见漏洞排查。它适合让 Agent 梳理敏感配置、检查依赖风险、分析鉴权逻辑或生成安全复核清单。使用时不能把工具输出直接当最终结论,涉及密钥、令牌、用户数据或生产系统时,应先确认最小权限、脱敏方式和操作边界。

总安装

441

周安装

18

GitHub Stars

16

下载量

143
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:dotnet-blazor-auth(dotnet blazor 身份验证)
来源仓库:https://github.com/wshaddix/dotnet-skills
仓库路径:skills/dotnet-blazor-auth
安装命令:
npx skills add https://github.com/wshaddix/dotnet-skills --skill dotnet-blazor-auth
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/wshaddix/dotnet-skills --skill dotnet-blazor-auth

简介

dotnet-blazor-auth 覆盖 Blazor 全托管模型的认证授权实现模式。

  • 适用于需要用户身份验证、角色管理和外部身份提供者的场景。
  • 提供 AuthorizeView 组件和 Identity UI 脚手架的使用指导。
  • 需区分 Server/WebAssembly 不同的令牌处理机制。
  • 涉及密钥管理时应遵循最小权限原则和安全存储规范。

SKILL.md

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 boundary: This skill owns Blazor-specific auth UI patterns -- AuthorizeView, CascadingAuthenticationState, Identity UI scaffolding, client-side token handling, and per-hosting-model auth flow configuration. API-level auth (JWT, OAuth/OIDC, passkeys, CORS, rate limiting) -- see [skill:dotnet-api-security].

Out of scope: JWT token generation and validation -- see [skill:dotnet-api-security]. OWASP security principles -- 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.


Auth Flow per Hosting Model

Authentication patterns differ significantly across Blazor hosting models:

ConcernInteractiveServerInteractiveWebAssemblyInteractiveAutoStatic SSRHybrid
Auth mechanismCookie-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 accessDirect HttpContext accessAuthenticationStateProviderVaries by phaseHttpContextPlatform auth APIs
Token storageNot needed (cookie)localStorage or sessionStorageTransition from cookie to tokenNot needed (cookie)Secure storage (Keychain, etc.)
Refresh handlingCircuit reconnectionToken refresh via interceptorAutomaticStandard cookie renewalPlatform-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.

// Program.cs
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.LoginPath = "/Account/Login";
        options.AccessDeniedPath = "/Account/AccessDenied";
    });

builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthorization();

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:

// Client Program.cs (WASM)
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");
});
// Attach tokens to API calls using BaseAddressAuthorizationMessageHandler
// (auto-attaches tokens for requests to the app's base address)
builder.Services.AddHttpClient("API", client =>
    client.BaseAddress = new Uri("https://api.example.com"))
    .AddHttpMessageHandler(sp =>
        sp.GetRequiredService<AuthorizationMessageHandler>()
            .ConfigureHandler(
                authorizedUrls: ["https://api.example.com"],
                scopes: ["api"]));

builder.Services.AddScoped(sp =>
    sp.GetRequiredService<IHttpClientFactory>().CreateClient("API"));

InteractiveAuto Auth

Auto mode starts as InteractiveServer (cookie auth), then transitions to WASM (token auth). Handle both:

// Server Program.cs
builder.Services.AddAuthentication()
    .AddCookie()
    .AddJwtBearer(); // For WASM API calls after transition

builder.Services.AddCascadingAuthenticationState();

Hybrid (MAUI) Auth

// Register platform-specific auth
builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<AuthenticationStateProvider, MauiAuthStateProvider>();

// Custom provider using secure storage
public class MauiAuthStateProvider : AuthenticationStateProvider
{
    public override async Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var token = await SecureStorage.Default.GetAsync("auth_token");
        if (string.IsNullOrEmpty(token))
        {
            return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
        }

        var claims = ParseClaimsFromJwt(token);
        var identity = new ClaimsIdentity(claims, "jwt");
        return new AuthenticationState(new ClaimsPrincipal(identity));
    }
}

AuthorizeView

AuthorizeView conditionally renders content based on the user's authentication and authorization state.

Basic Usage

<AuthorizeView>
    <Authorized>
        <p>Welcome, @context.User.Identity?.Name!</p>
        <a href="/Account/Logout">Log out</a>
    </Authorized>
    <NotAuthorized>
        <a href="/Account/Login">Log in</a>
    </NotAuthorized>
    <Authorizing>
        <p>Checking authentication...</p>
    </Authorizing>
</AuthorizeView>

Role-Based

<AuthorizeView Roles="Admin,Manager">
    <Authorized>
        <AdminDashboard />
    </Authorized>
    <NotAuthorized>
        <p>You do not have access to the admin dashboard.</p>
    </NotAuthorized>
</AuthorizeView>

Policy-Based

<AuthorizeView Policy="CanEditProducts">
    <Authorized>
        <button @onclick="EditProduct">Edit</button>
    </Authorized>
</AuthorizeView>
// Register policy in Program.cs
builder.Services.AddAuthorizationBuilder()
    .AddPolicy("CanEditProducts", policy =>
        policy.RequireClaim("permission", "products.edit"));

CascadingAuthenticationState

CascadingAuthenticationState provides the current AuthenticationState as a cascading parameter to all descendant components.

Setup

// Program.cs -- register cascading auth state
builder.Services.AddCascadingAuthenticationState();

This replaces wrapping the entire app in <CascadingAuthenticationState> (the older pattern). The service-based registration (.NET 8+) is preferred.

Consuming Auth State in Components

@code {
    [CascadingParameter]
    private Task<AuthenticationState>? AuthState { get; set; }

    private string? userName;

    protected override async Task OnInitializedAsync()
    {
        if (AuthState is not null)
        {
            var state = await AuthState;
            userName = state.User.Identity?.Name;
        }
    }
}

Accessing Claims

var state = await AuthState;
var user = state.User;

// Check authentication
if (user.Identity?.IsAuthenticated == true)
{
    var email = user.FindFirst(ClaimTypes.Email)?.Value;
    var roles = user.FindAll(ClaimTypes.Role).Select(c => c.Value);
    var isAdmin = user.IsInRole("Admin");
}

Identity UI Scaffolding

ASP.NET Core Identity provides a complete authentication system with registration, login, email confirmation, password reset, and two-factor authentication.

Adding Identity to a Blazor Web App

# Add Identity scaffolding
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add package Microsoft.AspNetCore.Identity.UI
// Program.cs
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));

builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.Password.RequireDigit = true;
    options.Password.RequiredLength = 8;
    options.Password.RequireNonAlphanumeric = true;
    options.SignIn.RequireConfirmedAccount = true;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

Scaffolding Identity Pages

# Scaffold individual Identity pages for customization
dotnet aspnet-codegenerator identity -dc ApplicationDbContext --files "Account.Login;Account.Register;Account.Logout"

Custom Identity UI with Blazor Components

For a fully Blazor-native auth experience, create Blazor components that call Identity APIs:

@page "/Account/Login"
@inject SignInManager<ApplicationUser> SignInManager
@inject NavigationManager Navigation

<EditForm Model="loginModel" OnValidSubmit="HandleLogin" FormName="login" Enhance>
    <DataAnnotationsValidator />
    <ValidationSummary />

    <div>
        <InputText @bind-Value="loginModel.Email" placeholder="Email" />
    </div>
    <div>
        <InputText @bind-Value="loginModel.Password" type="password" placeholder="Password" />
    </div>
    <div>
        <InputCheckbox @bind-Value="loginModel.RememberMe" /> Remember me
    </div>

    <button type="submit">Log in</button>
</EditForm>

@if (!string.IsNullOrEmpty(errorMessage))
{
    <p class="text-danger">@errorMessage</p>
}

@code {
    [SupplyParameterFromForm]
    private LoginModel loginModel { get; set; } = new();

    private string? errorMessage;

    private async Task HandleLogin()
    {
        var result = await SignInManager.PasswordSignInAsync(
            loginModel.Email, loginModel.Password,
            loginModel.RememberMe, lockoutOnFailure: true);

        if (result.Succeeded)
        {
            Navigation.NavigateTo("/", forceLoad: true);
        }
        else if (result.RequiresTwoFactor)
        {
            Navigation.NavigateTo("/Account/LoginWith2fa");
        }
        else if (result.IsLockedOut)
        {
            errorMessage = "Account is locked. Try again later.";
        }
        else
        {
            errorMessage = "Invalid login attempt.";
        }
    }
}

Gotcha: SignInManager uses HttpContext to set cookies. In Interactive render modes, HttpContext is not available after the circuit is established. Login/logout pages must use Static SSR (no @rendermode) so they have access to HttpContext for cookie operations.


Role and Policy-Based Authorization

Page-Level Authorization

@page "/admin"
@attribute [Authorize(Roles = "Admin")]

<h1>Admin Panel</h1>
@page "/products/manage"
@attribute [Authorize(Policy = "ProductManager")]

<h1>Manage Products</h1>

Defining Policies

builder.Services.AddAuthorizationBuilder()
    .AddPolicy("ProductManager", policy =>
        policy.RequireRole("Admin", "ProductManager"))
    .AddPolicy("CanDeleteOrders", policy =>
        policy.RequireClaim("permission", "orders.delete")
              .RequireAuthenticatedUser())
    .AddPolicy("MinimumAge", policy =>
        policy.AddRequirements(new MinimumAgeRequirement(18)));

Custom Authorization Handler

public sealed class MinimumAgeRequirement(int minimumAge) : IAuthorizationRequirement
{
    public int MinimumAge { get; } = minimumAge;
}

public sealed class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        MinimumAgeRequirement requirement)
    {
        var dateOfBirthClaim = context.User.FindFirst("date_of_birth");
        if (dateOfBirthClaim is not null
            && DateOnly.TryParse(dateOfBirthClaim.Value, out var dob))
        {
            var age = DateOnly.FromDateTime(DateTime.UtcNow).Year - dob.Year;
            if (age >= requirement.MinimumAge)
            {
                context.Succeed(requirement);
            }
        }
        return Task.CompletedTask;
    }
}

// Register
builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();

Procedural Authorization in Components

@inject IAuthorizationService AuthorizationService

@code {
    [CascadingParameter]
    private Task<AuthenticationState>? AuthState { get; set; }

    private bool canEdit;

    protected override async Task OnInitializedAsync()
    {
        if (AuthState is not null)
        {
            var state = await AuthState;
            var result = await AuthorizationService.AuthorizeAsync(
                state.User, "CanEditProducts");
            canEdit = result.Succeeded;
        }
    }
}

External Identity Providers

Adding External Providers

builder.Services.AddAuthentication()
    .AddMicrosoftAccount(options =>
    {
        options.ClientId = builder.Configuration["Auth:Microsoft:ClientId"]!;
        options.ClientSecret = builder.Configuration["Auth:Microsoft:ClientSecret"]!;
    })
    .AddGoogle(options =>
    {
        options.ClientId = builder.Configuration["Auth:Google:ClientId"]!;
        options.ClientSecret = builder.Configuration["Auth:Google:ClientSecret"]!;
    });

External Login Flow per Hosting Model

Hosting ModelFlowNotes
InteractiveServer / Static SSRStandard OAuth redirect (server-side)Cookie stored after callback
InteractiveWebAssemblyOIDC with PKCE (client-side)Token stored in browser
Hybrid (MAUI)WebAuthenticator or MSALPlatform-specific secure storage

For WASM, configure the OIDC provider in the client project:

// Client Program.cs
builder.Services.AddOidcAuthentication(options =>
{
    options.ProviderOptions.Authority = "https://login.microsoftonline.com/{tenant}";
    options.ProviderOptions.ClientId = "{client-id}";
    options.ProviderOptions.ResponseType = "code";
});

For MAUI Hybrid:

var result = await WebAuthenticator.Default.AuthenticateAsync(
    new Uri("https://login.example.com/authorize"),
    new Uri("myapp://callback"));
var token = result.AccessToken;

Agent Gotchas

  1. Do not access HttpContext in interactive components. HttpContext is only available during the initial HTTP request. After the SignalR circuit is established (InteractiveServer) or the WASM runtime loads, it is null. Use AuthenticationStateProvider or CascadingAuthenticationState instead.
  2. Do not rely on cookies for cross-origin or delegated API access in WASM. Use OIDC/JWT with AuthorizationMessageHandler for cross-origin APIs. Same-origin and Backend-for-Frontend (BFF) cookie auth remains valid for WASM apps.
  3. Do not render login/logout pages in Interactive mode. SignInManager requires HttpContext to set/clear cookies. Login and logout pages must use Static SSR render mode.
  4. Do not store tokens in localStorage without considering XSS. If the app is vulnerable to XSS, tokens in localStorage can be stolen. Use sessionStorage (cleared on tab close) or the OIDC library's built-in storage mechanisms with PKCE.
  5. Do not forget AddCascadingAuthenticationState(). Without it, [CascadingParameter] Task<AuthenticationState> is always null in components, silently breaking auth checks.
  6. Do not use AddIdentity and AddDefaultIdentity together. AddDefaultIdentity includes UI scaffolding; AddIdentity does not. Choose one based on whether you want the default Identity UI pages.

Prerequisites

  • .NET 8.0+ (Blazor Web App with render modes, AddCascadingAuthenticationState service registration)
  • Microsoft.AspNetCore.Identity.EntityFrameworkCore for Identity with EF Core
  • Microsoft.AspNetCore.Identity.UI for default Identity UI scaffolding
  • Microsoft.AspNetCore.Authentication.MicrosoftAccount / .Google for external providers
  • Microsoft.Authentication.WebAssembly.Msal for WASM with Microsoft Identity (Azure AD/Entra)

References

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

38.95%
按下载量换算56

Claude

31.24%
按下载量换算45

Cursor

17.52%
按下载量换算25

Gemini CLI

9.97%
按下载量换算14

安全审计

Gen Agent Trust Hub

通过

Socket

未通过

Snyk

通过

权限和风险

敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills