app.UseAuthentication(); // establishes WHO the user is
app.UseAuthorization(); // decides WHAT they can access
[Authorize(Roles = "Admin")]
public IActionResult DeleteUser(int id) { ... }
Topics
31
.NET CLI, SDK & Project Structure (csproj)
.NET vs .NET Framework
API Versioning
ASP.NET Core Middleware & Request Pipeline
Assemblies & NuGet
Authentication & Authorization (Identity, JWT, OAuth)
Background Services
Blazor (Server & WebAssembly)
Caching (In-Memory, Distributed & Redis)
CI/CD, Publishing & Deployment
CLR & Runtime
Configuration & Options
CORS & Cross-Origin Resource Sharing
Dependency Injection
Diagnostics & Performance
Docker & Containerization
Entity Framework Core & Data Access
Generic Host
Global Exception Handling & Middleware
gRPC Services
Health Checks & Readiness/Liveness Probes
Logging
Microservices & Distributed Architecture Patterns
Minimal APIs
MVC & Razor Pages
Rate Limiting & Throttling
RESTful Web APIs & Controllers
Secrets Management & Configuration Providers (Key Vault, User Secrets)
SignalR & Real-Time Communication
Testing in .NET (xUnit, Integration & Unit Testing)
Worker Services & IHostedService
Authentication & Authorization (Identity, JWT, OAuth)
16 questions found
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.
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.
ASP.NET Core Middleware & Request Pipeline;RESTful Web APIs & Controllers
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.
ASP.NET Core Middleware & Request Pipeline;CORS & Cross-Origin Resource Sharing
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.
Authentication & Authorization (Identity
JWT
OAuth);Entity Framework Core & Data Access
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.
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?
AdvancedThe 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.
Authentication & Authorization (Identity
JWT
OAuth);CORS & Cross-Origin Resource Sharing
How do you implement role-based authorization using the [Authorize(Roles = "...")] attribute?
IntermediateApplying [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.
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?
AdvancedPolicy-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.
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?
IntermediateAccess 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.
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?
AdvancedSince 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.
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?
IntermediateThe 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.
Microservices & Distributed Architecture Patterns;Authentication & Authorization (Identity
JWT
OAuth)
Showing 1–10 of 16