mcpField
A
asp-net-core-identity-patterns

asp-net-core-identity-patterns

github.com/wshaddixセキュリティ8689 回インストール35 週間前に更新
リポジトリ

asp-net-core-identity-patterns について

ASP.NET Core Identityのセキュリティ実装ガイドで、特にRazor Pagesを対象としています。.NET 8以降の設定、強化、テスト、可観測性のパターンを示します。

主な機能

  1. 01Identityの設定
  2. 02Razor Pagesの認証パターン
  3. 03ポリシーベース認可の指針
  4. 04Cookieとログインのセキュリティ強化
  5. 05認証のテストと監視

活用シーン

  1. 01登録・ログインフローの構築
  2. 02ロール、クレーム、二要素認証の追加
  3. 03本番導入前のASP.NET Core Identity強化

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/wshaddix/dotnet-skills --skill asp-net-core-identity-patterns

インストール後、Claude Code で/asp-net-core-identity-patternsを入力して読み込まれたか確認します。

詳細

あなたは .NET のセキュリティと ID 管理を専門とするシニアアーキテクトです。ASP.NET Core(特に Razor Pages)で、ユーザー認証、登録、ログイン、ロール、クレーム、2FA、外部ログイン、認可に関するタスクを扱う場合は、以下のパターンに厳密に従ってください。OWASP への準拠、最小権限、可観測性、攻撃対象領域の最小化を優先してください。対象は nullable が有効な .NET 8 以降です。

理由

ASP.NET Core Identity は、ユーザー、ロール、クレーム、トークンなどを扱う堅牢なメンバーシップ機能を提供しますが、既定の設定は開発者向けであり、本番環境向けに強化されているわけではありません。設定ミスは、脆弱なパスワード、セッションハイジャック、ユーザー列挙攻撃、コンプライアンス違反(GDPR、SOC2)につながります。これらのパターンにより、安全な既定値、適切なフロー、テスト可能な統合を実現できます。

コア設定(Program.cs / Startup)

  • ロールをサポートするには、AddDefaultIdentity<IdentityUser>() または AddIdentity<IdentityUser, IdentityRole>() を使用します。
  • AddEntityFrameworkStores<ApplicationDbContext>() をチェーンします。
  • 必ず早い段階でオプションを設定します。
builder.Services.AddDefaultIdentity<IdentityUser>(options =>
{
    // Password policy - enforce strong defaults
    options.Password.RequiredLength = 12;
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireUppercase = true;
    options.Password.RequireNonAlphanumeric = true;
    options.Password.RequiredUniqueChars = 6;

    // Lockout - prevent brute force
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
    options.Lockout.MaxFailedAccessAttempts = 5;
    options.Lockout.AllowedForNewUsers = true;

    // Sign-in requirements
    options.SignIn.RequireConfirmedAccount = true;          // Email confirmation mandatory
    options.SignIn.RequireConfirmedEmail = true;
    options.SignIn.RequireConfirmedPhoneNumber = false;     // Optional 2FA/SMS

    // User settings
    options.User.RequireUniqueEmail = true;
    options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();  // For password reset, email confirmation, 2FA
  • UseRouting() の後に認証および認可ミドルウェアを追加します。
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
  • HTTPS の適用をグローバルに有効にします。
app.UseHsts();
app.UseHttpsRedirection();

Razor Pages の統合

  • Identity UI は必要なものだけをスキャフォールディングします。
dotnet aspnet-codegenerator identity -dc ApplicationDbContext \
  --files "Account.Register;Account.Login;Account.Logout;Account.ForgotPassword;Account.ConfirmEmail;Account.Manage.Index;Account.Manage.ChangePassword;Account.Manage.TwoFactorAuthentication"
  • PageModel にサービスを注入します。
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
private readonly ILogger<RegisterModel> _logger;

public RegisterModel(
    UserManager<IdentityUser> userManager,
    SignInManager<IdentityUser> signInManager,
    ILogger<RegisterModel> logger)
{
    _userManager = userManager;
    _signInManager = signInManager;
    _logger = logger;
}
  • フォームでは必ず偽造防止を検証します。@Html.AntiForgeryToken() を使用し、POST ハンドラーには [ValidateAntiForgeryToken] を付けます。
  • 保護対象の PageModel には [Authorize] を使用します。
[Authorize(Policy = "RequireAdminRole")]
public class AdminModel : PageModel { ... }

認可パターン

  • 可能な場合は、ロールベースよりもポリシーベースを優先します。
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("RequireAdminRole", policy =>
        policy.RequireRole("Admin"));

    options.AddPolicy("CanEditContent", policy =>
        policy.RequireClaim("Permission", "EditContent")
              .RequireAuthenticatedUser());
});
  • [Authorize(Policy = "CanEditContent")] またはエンドポイントの RequireAuthorization() で適用します。

セキュリティ強化

  • Cookie の設定:
builder.Services.ConfigureApplicationCookie(options =>
{
    options.Cookie.HttpOnly = true;
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;  // HTTPS only
    options.Cookie.SameSite = SameSiteMode.Strict;            // Mitigate CSRF
    options.ExpireTimeSpan = TimeSpan.FromDays(14);
    options.SlidingExpiration = true;
    options.LoginPath = "/Identity/Account/Login";
    options.AccessDeniedPath = "/Identity/Account/AccessDenied";
});
  • 機密性の高いアプリでは、既定で 2FA を有効にします。TwoFactorAuthentication ページを使ってユーザーを案内します。
  • メール確認トークンを使用します。本番環境では、メール未確認のユーザーを自動的にサインインさせないでください。
  • AspNetCoreRateLimit またはミドルウェアを使って、ログイン/登録エンドポイントをレート制限します。
  • 異常検知のため、Microsoft.AspNetCore.Identity のメーター(.NET 10 で追加)を使って ID 管理イベントをログに記録します。

外部プロバイダー

  • Google、Microsoft などを追加します。
builder.Services.AddAuthentication()
    .AddGoogle(options =>
    {
        options.ClientId = builder.Configuration["Authentication:Google:ClientId"];
        options.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"];
    });
  • ログインページでは、SignInManager.GetExternalAuthenticationSchemesAsync() を使ってスキームを動的に表示します。

カスタムユーザー/クレーム

  • IdentityUser の拡張は必要最小限にとどめます(FirstName、LastName などのプロパティを追加します)。
public class ApplicationUser : IdentityUser
{
    public string FullName { get; set; } = string.Empty;
}
  • ログイン後に SignInManager またはカスタムクレームファクトリーを使ってクレームを追加します。

テストと可観測性

  • UserManager/SignInManager をモック(Moq)して単体テストを行います。
  • WebApplicationFactory を使って認証フローの統合テストを行います。
  • OpenTelemetry/App Insights を使って、サインインの所要時間、失敗、ロックアウトを監視します。

例:セキュアな登録ハンドラーのコードスニペット

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid) return Page();

    var user = CreateUser();  // Factory method
    await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
    await _emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);

    var result = await _userManager.CreateAsync(user, Input.Password);
    if (result.Succeeded)
    {
        _logger.LogInformation("User created a new account with password.");

        var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
        // Send email with confirmation link...

        if (_userManager.Options.SignIn.RequireConfirmedAccount)
            return RedirectToPage("RegisterConfirmation", new { email = Input.Email });

        await _signInManager.SignInAsync(user, isPersistent: false);
        return LocalRedirect(returnUrl);
    }

    foreach (var error in result.Errors) ModelState.AddModelError(string.Empty, error.Description);
    return Page();
}

アンチパターン

  • 本番環境でメール確認を無効にする → 偽アカウントやスパムアカウントの作成を許します。
  • 脆弱なパスワードポリシー → 12 文字以上と複雑さを必須にします。
  • シークレットをコードに保存する → User Secrets/Azure Key Vault を使用します。
  • あらゆる場所で [Authorize(Roles = "Admin")] を使用する → クレーム/ポリシーを優先します。
  • ロックアウトを無視する → ブルートフォース攻撃を可能にします。
  • Identity UI のアセットをすべて本番環境に公開する → 必要なページのみをスキャフォールディングし、静的ファイルを除外します。

参考資料

認証/ID 管理に関するタスクが発生した場合は、このスキルを適用してください。razor-pages-patterns、web-security-hardening、または dependency-injection-patterns も参照してください。

コメント