Authentication & Authorization (Identity, JWT, OAuth)

16 questions found

What is the difference between authentication and authorization in ASP.NET Core?

Beginner
Authentication answers 'who are you?' -- verifying a user's identity, typically producing a ClaimsPrincipal representing the authenticated user. Authorization answers 'what are you allowed to do?' -- deciding whether an authenticated (or even anonymous) user is permitted to access a specific resource or perform an action, evaluated after authentication has established identity.
app.UseAuthentication();  // establishes WHO the user is
app.UseAuthorization();   // decides WHAT they can access

[Authorize(Roles = "Admin")]
public IActionResult DeleteUser(int id) { ... }
Real-world example A request with a valid login token passes authentication (identity confirmed) but still receives a 403 Forbidden from authorization if that user lacks the Admin role required for a specific delete endpoint.

Common follow-ups: What HTTP status codes correspond to failed authentication versus failed authorization?;How does ASP.NET Core represent an authenticated user internally?

ASP.NET Core Middleware & Request Pipeline;RESTful Web APIs & Controllers

How does JWT (JSON Web Token) authentication work at a high level in ASP.NET Core?

Intermediate
A client authenticates once (e.g., with credentials) and receives a signed JWT containing claims about the user (identity, roles, expiration) encoded in its payload. For subsequent requests, the client sends this token (typically in the Authorization: Bearer header), and JWT bearer middleware validates the token's signature, expiration, issuer, and audience without needing a server-side session lookup, making it stateless and well-suited for APIs and distributed systems.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options => {
        options.TokenValidationParameters = new TokenValidationParameters {
            ValidateIssuer = true,
            ValidIssuer = "myapp",
            ValidateAudience = true,
            ValidAudience = "myapp-api",
            IssuerSigningKey = new SymmetricSecurityKey(key)
        };
    });
Real-world example A single-page application logs in once, receives a JWT, and includes it as a Bearer token on every subsequent API call, letting the stateless API validate each request independently without a shared session store.

Common follow-ups: Why is JWT considered stateless compared to cookie-based sessions?;How do you handle token revocation with stateless JWTs?

ASP.NET Core Middleware & Request Pipeline;CORS & Cross-Origin Resource Sharing

What are JWT claims, and how do you add custom claims when issuing a token?

Advanced
Claims are key-value pairs embedded in a JWT's payload describing attributes about the authenticated subject (standard ones include sub, exp, iss, aud; custom ones might include role, tenant_id, or permissions). You add custom claims when constructing the token during login, and they become accessible via User.Claims or User.FindFirst() in any subsequently authenticated request.
var claims = new[] {
    new Claim(JwtRegisteredClaimNames.Sub, user.Id),
    new Claim("tenant_id", user.TenantId),
    new Claim(ClaimTypes.Role, "Manager")
};
var token = new JwtSecurityToken(issuer, audience, claims,
    expires: DateTime.UtcNow.AddHours(1),
    signingCredentials: creds);

// Later, in any authorized endpoint:
var tenantId = User.FindFirst("tenant_id")?.Value;
Real-world example A multi-tenant SaaS application embeds a tenant_id claim in every issued JWT, letting every downstream authorized request efficiently scope database queries to the correct tenant without an extra database lookup.

Common follow-ups: What's the size trade-off of embedding many claims directly in a JWT?;How do you handle claims that change frequently (like roles) with long-lived tokens?

Authentication & Authorization (Identity JWT OAuth);Entity Framework Core & Data Access

What is ASP.NET Core Identity, and what does it provide out of the box?

Intermediate
ASP.NET Core Identity is a membership system providing user registration, password hashing and validation, email confirmation, two-factor authentication, external login providers (Google, Microsoft, Facebook), role management, and account lockout -- backed by a configurable data store (commonly Entity Framework Core with a relational database), significantly reducing the boilerplate needed to implement secure user account management from scratch.
builder.Services.AddDefaultIdentity<IdentityUser>(options => {
    options.Password.RequireDigit = true;
    options.Password.RequiredLength = 8;
    options.SignIn.RequireConfirmedEmail = true;
}).AddEntityFrameworkStores<AppDbContext>();
Real-world example A new web application uses ASP.NET Core Identity's scaffolded Razor Pages for login, registration, and password reset flows instead of building and securing this notoriously error-prone functionality from scratch.

Common follow-ups: How do you customize the IdentityUser class to add custom profile fields?;How does Identity handle password hashing internally?

Entity Framework Core & Data Access;Authentication & Authorization (Identity JWT OAuth)

How does the OAuth 2.0 Authorization Code flow work, and why is it preferred over the deprecated Implicit flow for web applications?

Advanced
The Authorization Code flow has the client redirect the user to an authorization server to authenticate and consent, receive a short-lived authorization code via redirect, then exchange that code (server-side, using a client secret) for an access token via a direct back-channel request -- keeping the actual token exchange off the browser's history and network logs. The Implicit flow, which returned tokens directly in the redirect URL fragment, is now deprecated because it exposed tokens to browser history, referrer leakage, and had no refresh token support.
// Step 1: Redirect user to authorization server
// GET https://auth.example.com/authorize?client_id=...&response_type=code&redirect_uri=...

// Step 2: User authenticates, redirected back with a code
// GET https://myapp.com/callback?code=abc123

// Step 3: Server exchanges code for tokens (back-channel, not visible to browser)
// POST https://auth.example.com/token  { code: 'abc123', client_secret: '...' }
Real-world example A web application integrates 'Sign in with Google' using the Authorization Code flow with PKCE, ensuring the actual access token never appears in browser-visible URLs or history at any point in the flow.

Common follow-ups: What is PKCE and why is it required for public clients (SPAs, mobile apps)?;What's the difference between an authorization code and an access token?

Authentication & Authorization (Identity JWT OAuth);CORS & Cross-Origin Resource Sharing

How do you implement role-based authorization using the [Authorize(Roles = "...")] attribute?

Intermediate
Applying [Authorize(Roles = "Admin,Manager")] to a controller or action restricts access to only authenticated users whose ClaimsPrincipal contains a role claim matching any of the listed roles (comma-separated means OR logic), with the framework automatically returning 401 Unauthorized for unauthenticated requests or 403 Forbidden for authenticated-but-insufficiently-privileged ones.
[Authorize(Roles = "Admin")]
[HttpDelete("{id}")]
public IActionResult DeleteUser(int id) {
    _userService.Delete(id);
    return NoContent();
}

// Multiple roles (OR logic): [Authorize(Roles = "Admin,Manager")]
Real-world example An admin dashboard's user-deletion endpoint is restricted with [Authorize(Roles = "Admin")] so that even a fully authenticated regular user attempting to call the endpoint directly receives a 403 Forbidden.

Common follow-ups: How would you require a user to have ALL of multiple roles instead of ANY?;How does role-based authorization compare to claims-based or policy-based authorization?

Authentication & Authorization (Identity JWT OAuth);RESTful Web APIs & Controllers

How do you implement policy-based authorization for more complex, custom access rules beyond simple roles?

Advanced
Policy-based authorization lets you define named policies with custom requirements (evaluated by an IAuthorizationHandler), enabling logic beyond simple role checks -- such as resource-based rules (a user can only edit their own resources) or combinations of claims. Policies are registered at startup and applied via [Authorize(Policy = "PolicyName")].
builder.Services.AddAuthorization(options => {
    options.AddPolicy("MinimumAge", policy =>
        policy.RequireAssertion(context =>
            context.User.HasClaim(c => c.Type == "age" && int.Parse(c.Value) >= 18)));
});

[Authorize(Policy = "MinimumAge")]
public IActionResult ViewRestrictedContent() { ... }
Real-world example An age-restricted content endpoint uses a custom MinimumAge policy evaluating a claim on the user's token, providing far more precise control than a generic role check could express.

Common follow-ups: How do you implement resource-based authorization where the specific object being accessed matters?;What's the difference between RequireAssertion and a custom IAuthorizationHandler class?

Authentication & Authorization (Identity JWT OAuth);RESTful Web APIs & Controllers

How do refresh tokens work alongside short-lived access tokens, and why is this pattern used?

Intermediate
Access tokens are intentionally short-lived (minutes to a couple hours) to limit the damage if one is stolen, while a longer-lived refresh token (stored more securely, often HttpOnly cookie) can be exchanged for a new access token without requiring the user to re-authenticate with credentials again, balancing security (short exposure window) with usability (infrequent re-logins).
// Client uses access token normally until it expires
// Then exchanges the refresh token for a new pair:
POST /auth/refresh
{ "refreshToken": "long-lived-opaque-token" }

// Response:
{ "accessToken": "new-short-lived-jwt", "refreshToken": "new-refresh-token" }
Real-world example A mobile banking app uses 15-minute access tokens with a 30-day refresh token stored in secure device storage, so users stay logged in for a month without needing to constantly re-enter credentials, while limiting a stolen access token's usefulness to a short window.

Common follow-ups: How do you securely store refresh tokens on different client types (web, mobile)?;What is refresh token rotation and why does it improve security?

Authentication & Authorization (Identity JWT OAuth);CORS & Cross-Origin Resource Sharing

How does token revocation work with stateless JWTs, given they can't simply be 'deleted' server-side once issued?

Advanced
Since JWTs are self-contained and valid until expiration regardless of server-side state, true revocation requires either: keeping token expiration very short combined with refresh token revocation (revoke the refresh token so no new access tokens can be issued, while the current one simply expires soon), or maintaining a server-side denylist/blocklist of revoked token IDs (jti claim) checked on every request -- which reintroduces some statefulness, trading off JWT's original stateless benefit for revocation capability.
// Denylist approach: check jti against a fast cache (e.g., Redis) on each request
var jti = User.FindFirst(JwtRegisteredClaimNames.Jti)?.Value;
if (await _revokedTokenCache.ExistsAsync(jti)) {
    return Results.Unauthorized();
}
Real-world example A security incident forces immediate logout of a compromised account; the team adds the affected user's active token jti values to a Redis-backed denylist checked by a custom authorization handler on every request until those tokens naturally expire.

Common follow-ups: What's the performance cost of checking a denylist on every request?;How do short-lived tokens plus refresh revocation compare to a full denylist approach?

Caching (In-Memory Distributed & Redis);Authentication & Authorization (Identity JWT OAuth)

What is the OAuth 2.0 Client Credentials flow, and when is it used instead of the Authorization Code flow?

Intermediate
The Client Credentials flow authenticates the application itself (not an end user) using its own client ID and secret to obtain an access token, used for machine-to-machine communication like a backend service calling another API with no human user involved -- unlike Authorization Code flow, which represents delegated user authorization.
POST https://auth.example.com/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=service-a&client_secret=***&scope=api.read
Real-world example A nightly batch job service authenticates to a partner's API using Client Credentials flow since it runs unattended with no user present to authorize anything, obtaining a service-level token scoped to just the permissions the job needs.

Common follow-ups: Why shouldn't client secrets ever be embedded in browser-based or mobile client code?;How does scope limiting reduce the blast radius of a compromised service credential?

Microservices & Distributed Architecture Patterns;Authentication & Authorization (Identity JWT OAuth)

Showing 1–10 of 16