asp-net-core-identity-patterns について
ASP.NET Core Identityのセキュリティ実装ガイドで、特にRazor Pagesを対象としています。.NET 8以降の設定、強化、テスト、可観測性のパターンを示します。
主な機能
- 01Identityの設定
- 02Razor Pagesの認証パターン
- 03ポリシーベース認可の指針
- 04Cookieとログインのセキュリティ強化
- 05認証のテストと監視
活用シーン
- 01登録・ログインフローの構築
- 02ロール、クレーム、二要素認証の追加
- 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 のアセットをすべて本番環境に公開する → 必要なページのみをスキャフォールディングし、静的ファイルを除外します。
参考資料
- Microsoft Docs: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity
- OWASP .NET Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/DotNet_Security_Cheat_Sheet.html
- .NET 10 Identity メトリクス:Microsoft.AspNetCore.Identity メーターのドキュメント
認証/ID 管理に関するタスクが発生した場合は、このスキルを適用してください。razor-pages-patterns、web-security-hardening、または dependency-injection-patterns も参照してください。
コメント
Markdown 対応