15 questions found
What is authentication in ASP.NET Core, and how does the framework represent an authenticated user?
Beginner
Authentication is the process of establishing a user's identity, resulting in a ClaimsPrincipal (accessible via HttpContext.User) populated with claims describing that user -- name, roles, and any custom attributes -- once an authentication handler successfully validates the request's credentials (a cookie, JWT, or other scheme-specific mechanism).
builder.Services.AddAuthentication("Cookies").AddCookie();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/me", (HttpContext ctx) => ctx.User.Identity?.Name);
Real-world example
After a user logs in and a cookie authentication handler validates their session cookie on a subsequent request, HttpContext.User.Identity.IsAuthenticated becomes true and the rest of the pipeline can access their claims.
Common follow-ups: What's the difference between authentication and authorization?;What happens to HttpContext.User for an anonymous, unauthenticated request?
Authorization;ASP.NET Core Middleware & Request Pipeline
How does cookie-based authentication work in ASP.NET Core, and when is it preferred over token-based authentication?
Intermediate
Cookie authentication issues an encrypted, signed cookie after successful login (via SignInAsync), which the browser automatically attaches to subsequent same-site requests; the server validates and decrypts it on each request to reconstruct the ClaimsPrincipal. It's preferred for traditional server-rendered web applications (Razor Pages, MVC views) where the browser and server share the same origin, since it requires no client-side token management code and benefits from HttpOnly cookie protection against XSS token theft.
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options => {
options.LoginPath = "/Account/Login";
options.ExpireTimeSpan = TimeSpan.FromHours(1);
});
// After validating credentials:
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
Real-world example
A traditional server-rendered admin dashboard uses cookie authentication since the browser handles cookie attachment automatically, requiring no custom JavaScript token-management code compared to a JWT-based SPA architecture.
Common follow-ups: Why is cookie authentication less suitable for a mobile app or cross-origin API?;How does the cookie's encryption key get managed across multiple server instances?
Sessions
Cookies & TempData;CORS (Cross-Origin Resource Sharing)
How does JWT bearer authentication validate an incoming token, and what claims does TokenValidationParameters check?
Advanced
The JWT bearer handler extracts the token from the Authorization: Bearer header, verifies its cryptographic signature against the configured signing key, and validates standard claims per TokenValidationParameters -- expiration (exp), not-before (nbf), issuer (iss must match ValidIssuer), and audience (aud must match ValidAudience) -- rejecting the request with 401 if any check fails, all before the request reaches your endpoint code.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters {
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = true, ValidIssuer = "myapp",
ValidateAudience = true, ValidAudience = "myapp-api",
ValidateLifetime = true
};
});
Real-world example
A stateless microservices API validates every incoming JWT's signature and claims on each request without any server-side session lookup, letting it scale horizontally without shared session state.
Common follow-ups: How do you fetch signing keys dynamically from an identity provider's JWKS endpoint instead of hardcoding them?;What happens if ClockSkew isn't configured for distributed systems with slightly different clocks?
Authorization;Configuration & Options Pattern
How do you configure ASP.NET Core to support multiple authentication schemes simultaneously, such as both cookies for a web UI and JWT for an API?
Intermediate
Register multiple named schemes via chained AddCookie/AddJwtBearer calls, then specify which scheme(s) apply per endpoint using [Authorize(AuthenticationSchemes = "Bearer")] on API controllers and a separate scheme for UI controllers -- a default scheme handles requests that don't explicitly specify one, letting a single application serve both browser-rendered pages and a JSON API with appropriately different authentication mechanisms.
builder.Services.AddAuthentication()
.AddCookie("Cookies")
.AddJwtBearer("Bearer");
[Authorize(AuthenticationSchemes = "Bearer")]
[Route("api/[controller]")]
public class ApiController : ControllerBase { }
[Authorize(AuthenticationSchemes = "Cookies")]
public class AccountController : Controller { }
Real-world example
A hybrid application serves server-rendered admin pages via cookie authentication and a separate mobile-app-facing JSON API via JWT bearer authentication, both from the same ASP.NET Core project, cleanly separated by scheme per controller.
Common follow-ups: How is the default scheme selected when an endpoint doesn't specify one?;What happens if a request presents credentials for the wrong scheme?
Authorization;RESTful Web APIs & Controllers
How do external identity provider integrations (like Google or Microsoft Entra ID) work using OAuth/OpenID Connect authentication handlers?
Advanced
Dedicated handler packages (Microsoft.AspNetCore.Authentication.Google, .MicrosoftAccount, or the generic OpenID Connect handler for any OIDC-compliant provider) implement the OAuth authorization code redirect flow, exchange the returned code for tokens, fetch the user's profile, and map the provider's claims into a local ClaimsPrincipal -- letting users 'Sign in with Google' without your application ever handling their Google password directly.
builder.Services.AddAuthentication()
.AddGoogle(options => {
options.ClientId = builder.Configuration["Google:ClientId"];
options.ClientSecret = builder.Configuration["Google:ClientSecret"];
});
// GET /signin-google (default callback path) handles the redirect back from Google
Real-world example
A B2B SaaS platform lets enterprise customers authenticate via their existing Microsoft Entra ID tenant using the OpenID Connect handler, integrating with corporate identity systems instead of maintaining separate app-specific passwords.
Common follow-ups: What's the difference between OAuth 2.0 and OpenID Connect for authentication purposes?;How do you link an external login to an existing local user account?
Authorization;Configuration & Options Pattern
What is ASP.NET Core Identity, and how does it provide a complete user account management system?
Intermediate
ASP.NET Core Identity is a full membership system handling user registration, password hashing (using a strong, salted algorithm by default), email confirmation, two-factor authentication, account lockout after failed attempts, and role management -- backed by a configurable data store, typically Entity Framework Core with a relational database -- dramatically reducing the notoriously error-prone work of building secure account management from scratch.
builder.Services.AddDefaultIdentity<IdentityUser>(options => {
options.Password.RequiredLength = 8;
options.SignIn.RequireConfirmedEmail = true;
}).AddEntityFrameworkStores<AppDbContext>();
// Scaffolded Razor Pages handle registration, login, password reset automatically
Real-world example
A new web application uses ASP.NET Core Identity's scaffolded UI for login, registration, and password reset instead of hand-rolling this security-sensitive functionality, avoiding common pitfalls like weak password hashing or missing account lockout protection.
Common follow-ups: How does Identity's password hashing algorithm compare to rolling your own?;How do you customize IdentityUser to add custom profile fields?
Authorization;Entity Framework Core & Data Access
How do refresh tokens work alongside short-lived JWT access tokens, and how would you implement a refresh endpoint?
Advanced
Short-lived access tokens (minutes) limit the exposure window if stolen, while a longer-lived, securely-stored refresh token (often in an HttpOnly cookie) can be exchanged via a dedicated /auth/refresh endpoint for a new access token pair without requiring the user to re-enter credentials -- the refresh endpoint validates the refresh token (checking it hasn't been revoked or expired), issues a new access token (and typically rotates the refresh token itself for added security), and returns both to the client.
app.MapPost("/auth/refresh", async (RefreshRequest request, ITokenService tokenService) => {
var principal = tokenService.ValidateRefreshToken(request.RefreshToken);
if (principal is null) return Results.Unauthorized();
var newAccessToken = tokenService.GenerateAccessToken(principal);
var newRefreshToken = tokenService.RotateRefreshToken(request.RefreshToken);
return Results.Ok(new { accessToken = newAccessToken, refreshToken = newRefreshToken });
});
Real-world example
A mobile banking app uses 15-minute access tokens with a 30-day refresh token, silently refreshing the access token in the background so users stay logged in for a month without frequent re-authentication, while limiting a stolen access token's usefulness.
Common follow-ups: What is refresh token rotation and why does it improve security over static refresh tokens?;How do you revoke a refresh token immediately during a security incident?
Authorization;Caching
How does two-factor authentication (2FA) work with ASP.NET Core Identity, and what does the sign-in flow look like?
Intermediate
Identity's SignInManager.PasswordSignInAsync returns a result indicating whether 2FA is required (RequiresTwoFactor), at which point the user is redirected to a verification step (typically an authenticator app TOTP code or an SMS/email code) rather than being immediately signed in -- only after successfully verifying the second factor via SignInManager.TwoFactorAuthenticatorSignInAsync does a full authenticated session get established.
var result = await _signInManager.PasswordSignInAsync(username, password, isPersistent: false, lockoutOnFailure: true);
if (result.RequiresTwoFactor) {
return RedirectToPage("./LoginWith2fa");
}
// On the 2FA verification page:
var twoFactorResult = await _signInManager.TwoFactorAuthenticatorSignInAsync(code, isPersistent, rememberClient: false);
Real-world example
A financial application requires 2FA for all user accounts, with Identity's built-in flow handling the entire authenticator-app-based verification sequence without custom-built session state management for the intermediate 'password verified, 2FA pending' state.
Common follow-ups: How does Identity generate and validate TOTP codes without a third-party service?;What's the difference between 'remember this browser' and full session persistence for repeated 2FA prompts?
Authorization;Sessions
Cookies & TempData
How do you implement API key authentication as a custom authentication scheme for machine-to-machine API access?
Advanced
Since API key authentication isn't a built-in ASP.NET Core scheme, you implement a custom AuthenticationHandler<TOptions> that extracts the key from a header or query parameter, validates it against a store (database, configuration, or cache), and constructs a ClaimsPrincipal representing the calling service/application if valid -- registered like any other scheme via AddScheme<TOptions, THandler>().
public class ApiKeyAuthHandler : AuthenticationHandler<ApiKeyAuthOptions> {
protected override async Task<AuthenticateResult> HandleAuthenticateAsync() {
if (!Request.Headers.TryGetValue("X-Api-Key", out var key))
return AuthenticateResult.Fail("Missing API key");
var client = await _keyStore.ValidateAsync(key);
if (client is null) return AuthenticateResult.Fail("Invalid API key");
var identity = new ClaimsIdentity(new[] { new Claim("client", client.Name) }, Scheme.Name);
return AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(identity), Scheme.Name));
}
}
Real-world example
A B2B integration platform issues each partner a unique API key validated by a custom authentication handler, letting partner-specific rate limits and permissions be enforced based on the resolved ClaimsPrincipal's client identity claim.
Common follow-ups: How does a custom AuthenticationHandler differ in complexity from using an existing scheme?;What are the security trade-offs of API keys versus OAuth client credentials?
Rate Limiting;Authorization
What is the purpose of the authentication middleware's position in the pipeline, and why must UseAuthentication come before UseAuthorization?
Intermediate
UseAuthentication establishes the request's identity (populating HttpContext.User) by running the configured authentication handler(s), which UseAuthorization then depends on to evaluate policy and role requirements -- registering them in the wrong order means authorization checks would run against an unauthenticated (empty) principal, incorrectly rejecting legitimately authenticated users.
app.UseRouting();
app.UseAuthentication(); // MUST come first: establishes HttpContext.User
app.UseAuthorization(); // depends on User already being populated
app.MapControllers();
Real-world example
A team debugging why all authenticated requests were incorrectly receiving 401 responses discovers UseAuthorization was accidentally registered before UseAuthentication, meaning no identity had been established yet when authorization checks ran.
Common follow-ups: What HttpContext state does UseAuthentication actually populate?;Does this ordering requirement apply the same way to minimal APIs as MVC controllers?
ASP.NET Core Middleware & Request Pipeline;Authorization