This note is structured to prepare you for interviews and practical usage of Authentication (AuthN) and Authorization (AuthZ) in .NET Web APIs.
We’ll start with fundamentals, cover the Microsoft recommended approach, and then move into advanced topics.
1. Fundamentals
Authentication vs Authorization
- Authentication (AuthN) → Proving who you are.
- Authorization (AuthZ) → Determining what you can do.
In Web APIs:
- AuthN is usually handled via tokens (JWT, cookies, OAuth).
- AuthZ is enforced via roles, claims, and policies.
2. Common Patterns in .NET Web API
🔹 ASP.NET Core Identity (with EF Core)
- Provides user & role management, login/registration.
- Usually paired with MVC/Razor apps.
- Can generate JWT tokens for APIs.
- Heavyweight if you just need token validation.
🔹 JWT Bearer Authentication (Standard for APIs)
- Stateless, scalable.
- Clients send a Bearer token in the
Authorization
header.
- Recommended by Microsoft for Web APIs.
GET /weatherforecast HTTP/1.1 Host: api.example.com Authorization: Bearer eyJhbGciOi...
3. Implementing JWT Authentication
3.1 Configure Authentication in Program.cs
builder.Services.AddAuthentication("Bearer") .AddJwtBearer("Bearer", options => { options.Authority = "<https://demo.identityserver.io>"; // Identity Provider options.Audience = "myapi"; // API identifier }); builder.Services.AddAuthorization(options => { options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin")); }); var app = builder.Build(); app.UseAuthentication(); app.UseAuthorization(); app.MapGet("/secure", [Authorize] () => "Secure endpoint"); app.MapGet("/admin", [Authorize(Roles = "Admin")] () => "Admin endpoint"); app.Run();
3.2 Generating JWTs (Custom Auth Server)
If you manage your own users:
var claims = new[] { new Claim(JwtRegisteredClaimNames.Sub, user.Id), new Claim(ClaimTypes.Role, "Admin"), }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["Jwt:Key"])); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: config["Jwt:Issuer"], audience: config["Jwt:Audience"], claims: claims, expires: DateTime.Now.AddHours(1), signingCredentials: creds ); return new JwtSecurityTokenHandler().WriteToken(token);
4. Authorization in Depth
4.1 Role-Based Authorization
[Authorize(Roles = "Admin")] [HttpGet("/admin-data")] public IActionResult GetAdminData() => Ok("Only Admins can access this");
4.2 Claims-Based Authorization
[Authorize(Policy = "CanDelete")] [HttpDelete("/delete-resource")] public IActionResult DeleteResource() => Ok("Resource deleted");
Registering policy in
Program.cs
:builder.Services.AddAuthorization(options => { options.AddPolicy("CanDelete", policy => policy.RequireClaim("permission", "delete")); });
4.3 Custom Policy Handlers
public class MinimumAgeRequirement : IAuthorizationRequirement { public int Age { get; } public MinimumAgeRequirement(int age) => Age = age; } public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement> { protected override Task HandleRequirementAsync( AuthorizationHandlerContext context, MinimumAgeRequirement requirement) { var dobClaim = context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth); if (dobClaim != null && DateTime.TryParse(dobClaim.Value, out var dob)) { if (DateTime.Today.Year - dob.Year >= requirement.Age) context.Succeed(requirement); } return Task.CompletedTask; } } // Register in Program.cs builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>(); builder.Services.AddAuthorization(options => { options.AddPolicy("Over18", policy => policy.Requirements.Add(new MinimumAgeRequirement(18))); });
Usage:
[Authorize(Policy = "Over18")] [HttpGet("/restricted")] public IActionResult GetRestricted() => Ok("Only 18+ can access");
5. Advanced Topics
5.1 Combining Multiple Schemes
- Support JWT + API Key + Cookies in the same app.
builder.Services.AddAuthentication() .AddJwtBearer("Jwt", ...) .AddScheme<ApiKeyOptions, ApiKeyHandler>("ApiKey", ...);
5.2 Resource-Based Authorization
- Instead of just roles/claims, authorization depends on the resource instance.
public class DocumentAuthorizationHandler : AuthorizationHandler<OperationAuthorizationRequirement, Document> { protected override Task HandleRequirementAsync( AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement, Document resource) { if (requirement.Name == "Edit" && resource.OwnerId == context.User.Identity.Name) context.Succeed(requirement); return Task.CompletedTask; } }
5.3 External Providers (Azure AD / Entra ID)
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(options => { configuration.Bind("AzureAd", options); }, options => { configuration.Bind("AzureAd", options); });
- Delegates authentication to Azure AD.
- Common for enterprise-grade apps.
5.4 Policy vs Role vs Claims
Approach | When to Use |
Roles | Coarse-grained access ( Admin , Manager ) |
Claims | Finer control ( delete , export , department=HR ) |
Policies | Custom logic, often combining multiple claims/roles |
6. Quick Comparison: Identity vs JWT
Feature | ASP.NET Core Identity | JWT Bearer Auth (Standard) |
User Store | Built-in with EF Core | External (Azure AD, IdentityServer) or custom |
Best for | Full app (UI + API) | Stateless APIs |
State | Database-backed | Token-based, stateless |
Complexity | Higher (DB migrations, tables) | Lower (validate token) |
7. Interview-Ready Summary
- AuthN vs AuthZ – Know the difference.
- Web APIs should be stateless → JWT is standard.
- ASP.NET Core Identity → only when managing users inside your app.
- Roles, Claims, Policies → 3 levels of authorization.
- Advanced → Custom policy handlers, resource-based auth, external identity providers.
✅ With this, you can answer both theoretical and coding interview questions on .NET Authentication & Authorization.