Unlock Authentication in .NET: JWT, Bearer Tokens & Identity Server

Authentication is the cornerstone of secure applications. Whether you're building APIs, Blazor apps, or microservices, understanding JWT tokens, Bearer authentication, and Identity Servers is essential.
In this 5-minute guide, we'll break down these concepts and show you how to implement them in .NET 10.
๐ What is a JWT Token?
A JWT (JSON Web Token) is a compact, self-contained token that securely transmits information between parties as a JSON object. It's digitally signed, so you can trust its contents haven't been tampered with.
JWT Structure
A JWT consists of three parts separated by dots:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0In0.signature
โโโโโ Header โโโโโโโโโโโ Payload โโโโโโโโโโ Sig โโ
- Header โ Algorithm & token type (
alg,typ) - Payload โ Claims (user data, expiration, issuer)
- Signature โ Verifies the token hasn't been tampered with
Common JWT Claims
iss(Issuer) โ Who created the tokensub(Subject) โ The user identifieraud(Audience) โ Intended recipientexp(Expiration) โ When the token expiresiat(Issued At) โ When the token was created
๐ซ What is a Bearer Token?
A Bearer Token is a type of access token included in HTTP requests using the Authorization header:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
The term "bearer" means: "whoever bears (carries) this token is authorized."
๐ก Key insight: JWTs are commonly used as bearer tokens, but they're not the same thing. JWT is a format, while Bearer is a transport mechanism.
๐ข What is an Identity Server?
An Identity Server (also called a Secure Token Service or STS) is a centralized authentication service that:
- โ Authenticates users (login with credentials)
- โ Issues tokens (JWT/access tokens)
- โ Validates tokens for APIs
- โ Supports standards like OAuth 2.0 and OpenID Connect (OIDC)
Popular Identity Servers
- Duende IdentityServer โ .NET-based, self-hosted
- Microsoft Entra ID โ Azure's cloud identity (formerly Azure AD)
- Auth0 โ Cloud-based, easy integration
- Keycloak โ Open-source, Java-based
๐ How It Works: The Authentication Flow
Here's how the complete authentication flow works:

Validation Steps
When the API receives a request, it validates:
- Signature โ Was this token created by a trusted issuer?
- Expiration โ Is the token still valid?
- Issuer (
iss) โ Did the expected identity server issue this? - Audience (
aud) โ Is this token intended for this API?
๐ป Implementation in .NET 10
Let's implement JWT Bearer authentication in a .NET 10 application.
Step 1: Install the NuGet Package
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
Step 2: Configure JWT Authentication
// Program.cs using System.Security.Claims; using Microsoft.AspNetCore.Authentication.JwtBearer; var builder = WebApplication.CreateBuilder(args); // Add JWT Bearer authentication builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.Authority = "https://your-identity-server.com"; options.Audience = "your-api-audience"; }); builder.Services.AddAuthorization(); var app = builder.Build(); // Enable authentication & authorization middleware app.UseAuthentication(); app.UseAuthorization(); // Public endpoint - no auth required app.MapGet("/", () => "Hello, World!"); // Protected endpoint - requires valid JWT app.MapGet("/secret", (ClaimsPrincipal user) => $"Hello, {user.Identity?.Name}! This is secret data.") .RequireAuthorization(); app.Run();
Step 3: Protect Controllers (Alternative Approach)
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; [Authorize] [ApiController] [Route("api/[controller]")] public class WeatherController : ControllerBase { [HttpGet] public IActionResult GetForecast() { return Ok(new { Temperature = 22, Unit = "Celsius" }); } [AllowAnonymous] [HttpGet("public")] public IActionResult GetPublicData() { return Ok("This is public data"); } }
Step 4: Force Authentication Globally (Optional)
If you want all endpoints to require authentication by default:
var requireAuthPolicy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); builder.Services.AddAuthorizationBuilder() .SetFallbackPolicy(requireAuthPolicy);
๐ Understanding HTTP Response Codes
- 200 OK โ Success: Valid token, authorized
- 401 Unauthorized โ Authentication failed: Invalid/expired token, wrong signature
- 403 Forbidden โ Authorization failed: Valid token, but insufficient permissions
โก Quick Reference
- JWT โ Self-contained token with encoded claims
- Bearer Token โ Token sent in
Authorizationheader - Identity Server โ Issues and validates tokens (OAuth/OIDC)
- Access Token โ Short-lived token for API access
- Refresh Token โ Long-lived token to get new access tokens
๐ก๏ธ Security Best Practices
- Always use HTTPS โ Never transmit tokens over unencrypted connections
- Validate all claims โ Issuer, audience, and expiration at minimum
- Use short expiration times โ Access tokens should expire in minutes, not days
- Store tokens securely โ Use HTTP-only cookies for web apps, secure storage for mobile
- Use asymmetric keys โ RSA or ECDSA signatures are more secure than symmetric keys
๐ Further Reading
- Configure JWT Bearer Authentication - Microsoft Docs
- OAuth 2.0 and OpenID Connect
- ASP.NET Core Security Documentation
See you next time for more on www.devskillsunlock.com ๐
