ASP.NET Core Identity - Quick Reference

SkillSecurity

ASP.NET Core Identity for authentication, roles, claims, and external providers. Covers Identity setup, customization, and token-based auth.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the ASP.NET Core Identity - Quick Reference skill

What this skill tells your AI

The instructions your AI receives, as published by claude-dev-suite/claude-dev-suite in skills/backend-frameworks/aspnet-identity/SKILL.md and read by ahel’s review.

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: aspnet-core for Identity documentation.

Setup

// Program.cs
builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.Password.RequireDigit = true;
    options.Password.RequiredLength = 12;
    options.Password.RequireNonAlphanumeric = true;
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
    options.Lockout.MaxFailedAccessAttempts = 5;
    options.User.RequireUniqueEmail = true;
})
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();

Custom User Entity

public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; } = default!;
    public string LastName { get; set; } = default!;
    public DateTime CreatedAt { get; set; }
}

Registration & Login

public class AuthService
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;

    public async Task<IdentityResult> RegisterAsync(RegisterRequest request)
    {
        var user = new ApplicationUser
        {
            UserName = request.Email,
            Email = request.Email,
            FirstName = request.FirstName,
            LastName = request.LastName,
        };
        return await _userManager.CreateAsync(user, request.Password);
    }

    public async Task<SignInResult> LoginAsync(LoginRequest request)
    {
        return await _signInManager.PasswordSignInAsync(
            request.Email, request.Password, request.RememberMe, lockoutOnFailure: true);
    }
}

Role-Based Authorization

// Seed roles
using var scope = app.Services.CreateScope();
var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
foreach (var role in new[] { "Admin", "User", "Manager" })
{
    if (!await roleManager.RoleExistsAsync(role))
        await roleManager.CreateAsync(new IdentityRole(role));
}

// Assign role
await _userManager.AddToRoleAsync(user, "Admin");

// Controller
[Authorize(Roles = "Admin")]
public IActionResult AdminPanel() => Ok();

// Policy-based
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("RequireAdmin", policy => policy.RequireRole("Admin"));
    options.AddPolicy("MinAge", policy =>
        policy.RequireClaim("DateOfBirth")
              .RequireAssertion(ctx =>
              {
                  var dob = DateTime.Parse(ctx.User.FindFirst("DateOfBirth")!.Value);
                  return DateTime.Today.Year - dob.Year >= 18;
              }));
});

External Login Providers

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

Anti-Patterns

Anti-PatternWhy It's BadCorrect Approach
Custom password hashingInsecureUse Identity's PasswordHasher<T>
Storing plain-text passwordsSecurity riskIdentity hashes automatically
No account lockoutBrute-force vulnerableEnable lockout options
Roles in JWT claims onlyNot enforced server-sideValidate from store

Quick Troubleshooting

IssueLikely CauseSolution
Login always failsWrong password configCheck PasswordOptions
User not foundCase sensitivityIdentity is case-insensitive by default
Token expiredShort token lifetimeAdjust TokenLifespan
External login redirect failsWrong callback URLCheck provider's redirect URIs

Signals

GitHub stars
33
Forks
8
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
aspnet-identity
Source
github.com/claude-dev-suite/claude-dev-suite