Authentication

codewithmukesh/dotnet-claude-kit/skills/authentication

by codewithmukesh23300897f4d1No license754 starsListed Oct 8, 2026Updated Oct 8, 2026Repository updated 2 months ago

Authentication and authorization for ASP.NET Core. Covers JWT bearer tokens, OpenID Connect, ASP.NET Identity, authorization policies, role and claim-based authorization, and API key authentication. Load this skill when implementing login, protecting endpoints, designing authorization rules, or when the user mentions "auth", "JWT", "bearer token", "OIDC", "OpenID Connect", "Identity", "claims", "roles", "authorize", "RequireAuthorization", "API key", or "cookie auth".

Instructions onlySoftware Development
AI-generated overview

Guides ASP.NET Core authentication and authorization, covering JWT bearer tokens, OpenID Connect, Identity, and policies.

What it does
This skill provides reference guidance and code patterns for implementing authentication and authorization in ASP.NET Core. It covers JWT bearer token setup and validation, token generation, policy-based authorization with custom requirements, endpoint protection, OpenID Connect, and accessing the current user. It also lists anti-patterns and a decision guide mapping scenarios to recommended approaches.
When to use it
Use it when implementing login, protecting endpoints, or designing authorization rules in ASP.NET Core. It is also relevant when working with JWT, bearer tokens, OIDC, ASP.NET Identity, claims, roles, API keys, or cookie authentication.
Requirements
No scripts are included; it is instructions only. Following the patterns assumes an ASP.NET Core project and relevant NuGet packages such as Microsoft.IdentityModel.JsonWebTokens, plus configuration values for JWT issuer, audience, and key.

Authentication & Authorization

Core Principles

  1. Use ASP.NET Identity for user management — Don't build your own user store. Identity handles password hashing, lockout, two-factor, email confirmation, and (since .NET 10) built-in passkey/WebAuthn support for passwordless login.
  2. JWT for APIs, cookies for web apps — APIs use Bearer token authentication; Blazor/MVC apps use cookie authentication.
  3. Policy-based authorization over roles — Policies are testable, composable, and more expressive than [Authorize(Roles = "Admin")].
  4. Never store secrets in code — Use user secrets in development, Azure Key Vault / environment variables in production.

Patterns

JWT Bearer Authentication

csharp
// Program.csbuilder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)    .AddJwtBearer(options =>    {        options.TokenValidationParameters = new TokenValidationParameters        {            ValidateIssuer = true,            ValidateAudience = true,            ValidateLifetime = true,            ValidateIssuerSigningKey = true,            ValidIssuer = builder.Configuration["Jwt:Issuer"],            ValidAudience = builder.Configuration["Jwt:Audience"],            IssuerSigningKey = new SymmetricSecurityKey(                Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!)),            ClockSkew = TimeSpan.Zero        };    });
builder.Services.AddAuthorization();

Token Generation

Use JsonWebTokenHandler from Microsoft.IdentityModel.JsonWebTokens — it is the maintained, span-based handler that ASP.NET Core itself validates with. JwtSecurityTokenHandler (System.IdentityModel.Tokens.Jwt) is the legacy stack.

csharp
public sealed class TokenService(IConfiguration config, TimeProvider clock){    private static readonly JsonWebTokenHandler TokenHandler = new();
    public string GenerateToken(User user, IEnumerable<string> roles)    {        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["Jwt:Key"]!));        var now = clock.GetUtcNow();
        var descriptor = new SecurityTokenDescriptor        {            Issuer = config["Jwt:Issuer"],            Audience = config["Jwt:Audience"],            IssuedAt = now.UtcDateTime,            Expires = now.AddHours(1).UtcDateTime,            Claims = new Dictionary<string, object>            {                [JwtRegisteredClaimNames.Sub] = user.Id,                [JwtRegisteredClaimNames.Email] = user.Email!,                [JwtRegisteredClaimNames.Name] = user.UserName!,                ["roles"] = roles.ToArray()            },            SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256)        };
        return TokenHandler.CreateToken(descriptor);    }}

Policy-Based Authorization

csharp
// Define policiesbuilder.Services.AddAuthorizationBuilder()    .AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"))    .AddPolicy("CanManageOrders", policy => policy        .RequireAuthenticatedUser()        .RequireClaim("permission", "orders:write"))    .AddPolicy("MinimumAge", policy => policy        .AddRequirements(new MinimumAgeRequirement(18)));
// Custom requirement + handlerpublic class MinimumAgeRequirement(int minimumAge) : IAuthorizationRequirement{    public int MinimumAge => minimumAge;}
public class MinimumAgeHandler(TimeProvider clock) : 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) &&            dob.AddYears(requirement.MinimumAge) <= DateOnly.FromDateTime(clock.GetUtcNow().DateTime))        {            context.Succeed(requirement);        }        return Task.CompletedTask;    }}

Protecting Endpoints

csharp
// Protect an entire groupapp.MapGroup("/api/admin")    .WithTags("Admin")    .RequireAuthorization("AdminOnly")    .MapAdminEndpoints();
// Protect individual endpointsgroup.MapPost("/", CreateOrder)    .RequireAuthorization("CanManageOrders");
// Allow anonymous on a protected groupgroup.MapGet("/public-info", GetPublicInfo)    .AllowAnonymous();

OpenID Connect (External Identity Provider)

csharp
builder.Services.AddAuthentication(options =>{    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;}).AddCookie().AddOpenIdConnect(options =>{    options.Authority = builder.Configuration["Oidc:Authority"];    options.ClientId = builder.Configuration["Oidc:ClientId"];    options.ClientSecret = builder.Configuration["Oidc:ClientSecret"];    options.ResponseType = "code";    options.SaveTokens = true;    options.Scope.Add("openid");    options.Scope.Add("profile");    options.Scope.Add("email");});

Accessing Current User

csharp
// In minimal API handlers — inject ClaimsPrincipal or HttpContextgroup.MapGet("/me", (ClaimsPrincipal user) =>{    var userId = user.FindFirstValue(ClaimTypes.NameIdentifier);    var email = user.FindFirstValue(ClaimTypes.Email);    return TypedResults.Ok(new { userId, email });}).RequireAuthorization();

Anti-patterns

Don't Use Role Strings Everywhere

csharp
// BAD — magic strings, hard to refactor, not testable[Authorize(Roles = "Admin,SuperAdmin,Manager")]public class AdminController { }
// GOOD — policy-basedbuilder.Services.AddAuthorizationBuilder()    .AddPolicy("AdminAccess", p => p.RequireRole("Admin", "SuperAdmin", "Manager"));
group.MapGet("/", Handler).RequireAuthorization("AdminAccess");

Don't Store Secrets in appsettings.json

json
// BAD — committed to source control{  "Jwt": {    "Key": "super-secret-key-12345"  }}
bash
# GOOD — use user secrets in developmentdotnet user-secrets set "Jwt:Key" "super-secret-key-12345"

Don't Skip Token Validation

csharp
// BAD — disabling validationoptions.TokenValidationParameters = new TokenValidationParameters{    ValidateIssuer = false,      // DON'T    ValidateAudience = false,    // DON'T    ValidateLifetime = false,    // DEFINITELY DON'T};
// GOOD — validate everything (see JWT Bearer Authentication pattern above for full setup)

Decision Guide

ScenarioRecommendation
REST APIJWT Bearer authentication
Blazor Server / MVCCookie authentication
External identity providerOpenID Connect
User registration / loginASP.NET Identity
Passwordless loginASP.NET Identity passkeys (WebAuthn, built-in since .NET 10)
Permission checkingPolicy-based authorization
Multi-tenant APIClaims-based with tenant claim
API-to-API communicationClient credentials (OAuth 2.0)
Simple API keysCustom AuthenticationHandler<T>

Source and attribution

Source:codewithmukesh/dotnet-claude-kitinskills/authenticationat commit2330089

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal

More from codewithmukesh/dotnet-claude-kit

Wrap Up

codewithmukesh

Captures end-of-session work, pending tasks and learnings into a handoff file, and reloads it at session start.

Productivity & Workflow754updated 2 months ago

Workflow Mastery

codewithmukesh

Claude Code workflow mastery for .NET developers. Covers parallel execution with git worktrees, plan mode strategy, verification loops, auto-formatting hooks, permission setup for dotnet CLI, prompting techniques, subagent patterns, and context discipline — token budget management, MCP-first navigation, lazy loading, and subagent isolation — all adapted for the .NET ecosystem. Load this skill when setting up Claude Code for a .NET project, optimizing workflows, running parallel sessions, when context is running low or sessions feel sluggish, when exploring a large codebase efficiently, or when the user mentions "productivity", "workflow", "parallel", "worktree", "plan mode", "permissions", "hooks", "10x", "setup Claude Code", "speed up development", "context", "tokens", "budget", "running out of context", "too many files", or "large codebase". Inspired by tips from Boris Cherny (creator of Claude Code) and the Anthropic team.

Awaiting classification754updated 2 months ago

Vertical Slice

codewithmukesh

Guides .NET developers in structuring applications with Vertical Slice Architecture, covering feature folders, endpoint grouping and handler patterns.

Software Development754updated 2 months ago

Testing

codewithmukesh

Testing strategy for .NET 10 applications. Covers xUnit v3, WebApplicationFactory for integration tests, Testcontainers for real database testing, Verify for snapshot testing, and the AAA pattern. Load this skill when writing tests, setting up test infrastructure, reviewing test coverage, or when the user mentions "test", "xUnit", "WebApplicationFactory", "Testcontainers", "integration test", "unit test", "bUnit", "snapshot test", "Verify", "test coverage", "AAA pattern", "WireMock", or "FakeTimeProvider".

Awaiting classification754updated 2 months ago

Tdd

codewithmukesh

Guided test-driven development workflow for .NET 10 using xUnit v3, WebApplicationFactory, Testcontainers, and Verify snapshots. Follows the strict red-green-refactor cycle. Use when: "TDD", "test-driven", "let's TDD this", "red green refactor", "write the test first", or when building a feature with clear acceptance criteria.

Awaiting classification754updated 2 months ago

Spec

codewithmukesh

Turns a vague feature idea into an agreed, persisted specification file through structured questioning rounds.

Productivity & Workflow754updated 2 months ago