Secure Authentication: OAuth2, OpenID, JWTs

Master secure authentication with OAuth2, OpenID Connect, and JWTs. Learn the correct patterns and ASP.NET Core examples to prevent auth-related vulnerabilities.

๐Ÿ” Introduction

Authentication is the foundation of application security. As we build modern applications that connect with APIs, third-party services, and mobile clients, ensuring proper identity verification becomes critical. Misconfigured authentication can expose user data, leak credentials, and open doors for unauthorized access.

๐Ÿ” Authentication vs Authorization

Many developers confuse authentication and authorization. Authentication confirms the user is who they say they are. Authorization defines what the authenticated user is allowed to do within the system. Mistaking one for the other can lead to privilege escalation vulnerabilities.

Authentication vs Authorization visual

โŒ Insecure Example

// No role-based check
[Authorize]
public IActionResult SecureData() => Ok("Everyone with token can see this");

โœ… Secure Example

[Authorize(Roles = "Admin")]
public IActionResult SecureData() => Ok("Only admins can see this");

๐Ÿ”‘ OAuth2 Explained

OAuth2 is an open standard for access delegation, commonly used for token-based authorization. It enables applications to access user data without sharing credentials, using flows like Authorization Code or Client Credentials. Misusing OAuth2 can expose tokens or allow impersonation.

OAuth2 Authorization Code Flow Diagram

โŒ Insecure Example

// Using hardcoded token and no OAuth flow
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer static_token");

โœ… Secure Example

services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "OAuthProvider";
})
.AddCookie("Cookies")
.AddOAuth("OAuthProvider", options =>
{
    options.ClientId = Configuration["OAuth:ClientId"];
    options.ClientSecret = Configuration["OAuth:ClientSecret"];
    options.CallbackPath = new PathString("/signin-oauth");

    options.AuthorizationEndpoint = "https://provider.com/oauth/authorize";
    options.TokenEndpoint = "https://provider.com/oauth/token";
    options.SaveTokens = true;
});

๐Ÿ—พ OpenID Connect

OpenID Connect (OIDC) extends OAuth2 to add identity verification using ID tokens. These tokens help applications confirm the user's identity in a standardized, secure manner. If implemented incorrectly, malicious tokens could be accepted without validation.

OpenID Connect Flow Diagram

โŒ Insecure Example

// Just trusting any ID token without validating claims
var idToken = context.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
var payload = JWT.Decode(idToken); // Without validation

โœ… Secure Example

services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
})
.AddCookie()
.AddOpenIdConnect("oidc", options =>
{
    options.Authority = "https://login.example.com";
    options.ClientId = "client_id";
    options.ClientSecret = "secret";
    options.ResponseType = "code";
    options.SaveTokens = true;
    options.Scope.Add("openid");
    options.Scope.Add("profile");
});

๐Ÿ” JSON Web Tokens (JWTs)

JWTs are compact, URL-safe tokens used to securely transmit information. They enable stateless authentication across microservices and APIs. JWTs must be properly signed and validated to avoid forgery or replay attacks.

JWT Anatomy Diagram

โŒ Insecure Example

// WARNING: This is NOT secure
services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = false,
            ValidateAudience = false,
            ValidateLifetime = false,
            ValidateIssuerSigningKey = false
        };
    });

โœ… Secure Example

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.Authority = "https://login.example.com";
        options.Audience = "api1";
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true
        };
    });

โš ๏ธ Common Implementation Mistakes

Even when using secure technologies, improper implementation can result in serious vulnerabilities. Avoid these common pitfalls:

Authentication Mistakes Visual
  • Storing tokens in localStorage
  • Using HS256 for public clients
  • Mixing ID and Access tokens

โŒ Insecure Example

// Using localStorage to store access token in JS app
localStorage.setItem("token", accessToken);

โœ… Secure Example

services.ConfigureApplicationCookie(options =>
{
    options.Cookie.HttpOnly = true;
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    options.Cookie.SameSite = SameSiteMode.Strict;
});

๐Ÿงฐ Best Practices Checklist

Follow these best practices when implementing secure authentication:

Auth Checklist Infographic
  • โœ… Use HTTPS - app.UseHttpsRedirection();
  • ๐Ÿ”„ Rotate secrets - Use DataProtection APIs
  • โฐ Short-lived tokens - Configure token lifespan
  • ๐Ÿงช Input validation - Always validate headers and claims

๐Ÿง‘โ€๐Ÿ’ป Real-World Login Flow

A minimal secure login implementation using JWT or OIDC, enabling authenticated access to protected routes.

Login flow with claims and token verification

โœ… Secure Example

app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/profile", [Authorize] (ClaimsPrincipal user) =>
{
    return Results.Json(new { Name = user.Identity.Name });
});

๐Ÿ“„ Real-World Breaches

High-profile breaches underscore the importance of getting authentication right:

  • Facebook (2018): Access tokens leaked via โ€œView Asโ€ feature. Lesson: Minimize token scope and lifetime.
  • Uber (2016): Tokens in GitHub repo were stolen. Lesson: Secure secrets properly.
  • Slack (2022): Long-lived token reused. Lesson: Always use refresh tokens and short expiry.

๐Ÿ”— Conclusion

Secure authentication is no longer optional. Implement OAuth2 for authorization, OpenID Connect for identity, and JWTs for stateless tokens โ€” but do it right. The smallest misconfiguration can lead to major breaches.

Explore more: OWASP A01 - Broken Access Control