Security  

Building Secure APIs with OAuth 2.1 and OpenID Connect

Introduction

APIs are the backbone of modern applications. Mobile apps, web applications, microservices, SaaS platforms, and third-party integrations all rely heavily on APIs for communication and data exchange. As API usage grows, securing these endpoints becomes increasingly important.

Traditional authentication methods such as API keys and basic authentication are no longer sufficient for many modern applications. Organizations need stronger authentication and authorization mechanisms that support scalability, delegated access, user identity verification, and modern security practices.

OAuth 2.1 and OpenID Connect (OIDC) have emerged as the industry standards for securing APIs and managing user authentication. Together, they provide a secure and flexible framework for protecting resources while delivering seamless user experiences.

In this article, you'll learn how OAuth 2.1 and OpenID Connect work, their key components, implementation approaches, and best practices for securing APIs.

Understanding OAuth 2.1

OAuth is an authorization framework that allows applications to access resources on behalf of users without exposing user credentials.

Instead of sharing usernames and passwords, applications receive access tokens that grant limited permissions.

OAuth 2.1 builds upon OAuth 2.0 by incorporating modern security recommendations and removing insecure legacy flows.

Its primary goals include:

  • Secure delegated access

  • Improved authentication security

  • Reduced attack surface

  • Simplified implementation guidance

OAuth focuses on authorization rather than authentication.

Understanding OpenID Connect

OpenID Connect is an identity layer built on top of OAuth.

While OAuth answers:

What can this application access?

OpenID Connect answers:

Who is the user?

OIDC provides:

  • User authentication

  • Identity information

  • Single Sign-On (SSO)

  • User profile claims

Applications commonly use OAuth and OpenID Connect together.

Why OAuth 2.1 and OIDC Matter

Modern applications require:

  • Secure user authentication

  • Delegated authorization

  • Mobile application support

  • Single Sign-On

  • Multi-platform access

  • Third-party integrations

OAuth 2.1 and OpenID Connect provide a standardized approach for achieving these goals.

Benefits include:

  • Strong security

  • Better user experience

  • Industry-standard protocols

  • Reduced credential exposure

  • Simplified identity management

Key Components of OAuth

Several components work together during authentication and authorization.

Resource Owner

The user who owns the protected data.

Example:

John Smith

Client Application

The application requesting access.

Examples:

  • Web applications

  • Mobile apps

  • Desktop applications

Authorization Server

Responsible for authenticating users and issuing tokens.

Examples include:

  • Microsoft Entra ID

  • Auth0

  • Okta

  • Keycloak

  • IdentityServer

Resource Server

The API containing protected resources.

Example:

Customer API

OAuth 2.1 Authorization Flow

The most commonly used flow is Authorization Code Flow with PKCE.

Step 1: User Requests Access

The application redirects the user to the authorization server.

Example:

https://auth.example.com/authorize

Step 2: User Authenticates

The user signs in using credentials, passkeys, MFA, or other supported methods.

Step 3: Authorization Code Issued

The authorization server returns an authorization code.

Step 4: Access Token Exchange

The application exchanges the authorization code for an access token.

Step 5: API Access

The access token is used to call protected APIs.

This flow minimizes security risks and protects user credentials.

What Is PKCE?

PKCE (Proof Key for Code Exchange) is a security enhancement required by OAuth 2.1.

It protects against authorization code interception attacks.

The client generates:

  • Code Verifier

  • Code Challenge

Example:

Code Verifier:
random-secret-string

The authorization server validates the verifier during token exchange.

PKCE is particularly important for:

  • Mobile applications

  • Single-page applications

  • Public clients

Understanding Access Tokens

Access tokens represent granted permissions.

Example JWT payload:

{
  "sub": "12345",
  "name": "John Smith",
  "scope": "api.read"
}

Tokens typically contain:

  • User identifier

  • Permissions

  • Expiration information

  • Issuer information

APIs validate these tokens before granting access.

Understanding ID Tokens

OpenID Connect introduces ID Tokens.

Example:

{
  "sub": "12345",
  "name": "John Smith",
  "email": "[email protected]"
}

ID Tokens provide identity information about authenticated users.

Applications use them to:

  • Display user information

  • Create sessions

  • Implement Single Sign-On

Securing ASP.NET Core APIs

ASP.NET Core provides built-in support for OAuth and OpenID Connect.

Install authentication packages:

dotnet add package
Microsoft.AspNetCore.Authentication.JwtBearer

Configure authentication:

builder.Services
.AddAuthentication("Bearer")
.AddJwtBearer(options =>
{
    options.Authority =
        "https://auth.example.com";

    options.Audience =
        "api";
});

Enable middleware:

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

This ensures requests are validated before accessing protected resources.

Protecting API Endpoints

Use authorization attributes to secure controllers.

Example:

[Authorize]
[HttpGet]
public IActionResult GetOrders()
{
    return Ok();
}

Only authenticated users can access the endpoint.

Role-based authorization:

[Authorize(Roles = "Admin")]

Claim-based authorization:

[Authorize(Policy = "CanManageOrders")]

This enables fine-grained access control.

Implementing OpenID Connect Login

For web applications:

builder.Services
.AddAuthentication(options =>
{
})
.AddCookie()
.AddOpenIdConnect(options =>
{
    options.Authority =
        "https://auth.example.com";

    options.ClientId =
        "web-app";

    options.ResponseType =
        "code";
});

This enables secure user authentication using OpenID Connect.

Refresh Tokens

Access tokens are intentionally short-lived.

Refresh tokens allow applications to obtain new access tokens without requiring users to sign in repeatedly.

Benefits include:

  • Better user experience

  • Reduced login prompts

  • Improved security

Refresh tokens should be protected carefully.

API Security Best Practices

Securing APIs requires more than token validation.

Important practices include:

Use HTTPS Everywhere

Never transmit tokens over unsecured connections.

Validate Tokens Properly

Always verify:

  • Signature

  • Issuer

  • Audience

  • Expiration

Apply Least Privilege

Grant only the permissions required.

Example:

api.read

Instead of:

admin.fullaccess

Implement Rate Limiting

Protect APIs against abuse and denial-of-service attacks.

Use Short-Lived Access Tokens

Reduce exposure if tokens are compromised.

Monitor Authentication Events

Track:

  • Failed logins

  • Suspicious activity

  • Token misuse

Common OAuth Mistakes

Avoid these common implementation issues:

  • Storing tokens in insecure locations.

  • Using implicit flow.

  • Skipping PKCE.

  • Not validating JWT signatures.

  • Granting excessive permissions.

  • Exposing client secrets.

  • Using long-lived access tokens.

These mistakes can introduce significant security vulnerabilities.

Practical Example

Consider an e-commerce platform.

Components:

React Frontend
     ↓
Identity Provider
     ↓
ASP.NET Core API
     ↓
Database

Workflow:

  1. User signs in.

  2. Identity provider issues tokens.

  3. Frontend sends access token.

  4. API validates token.

  5. Authorized requests access resources.

This architecture supports secure authentication and authorization at scale.

OAuth 2.1 vs API Keys

FeatureOAuth 2.1API Keys
User IdentityYesNo
Authorization ScopesYesLimited
Token ExpirationYesUsually No
Delegated AccessYesNo
SecurityHighModerate
Enterprise SupportExcellentLimited

For most enterprise applications, OAuth provides a significantly stronger security model.

Best Practices

When implementing OAuth 2.1 and OpenID Connect:

  • Use Authorization Code Flow with PKCE.

  • Validate all tokens.

  • Enforce HTTPS.

  • Use short-lived access tokens.

  • Protect refresh tokens.

  • Implement role-based authorization.

  • Monitor authentication events.

  • Rotate secrets regularly.

  • Apply least-privilege principles.

  • Keep identity providers updated.

These practices help create secure and maintainable authentication systems.

Conclusion

OAuth 2.1 and OpenID Connect have become the foundation of modern API security. Together, they provide secure authentication, delegated authorization, user identity management, and support for web, mobile, and enterprise applications.

ASP.NET Core offers excellent support for implementing these standards, making it easier for developers to secure APIs without building authentication systems from scratch. By understanding authorization flows, token management, PKCE, and security best practices, developers can create APIs that are scalable, secure, and ready for modern application architectures.

As organizations continue adopting cloud-native applications and distributed systems, OAuth 2.1 and OpenID Connect remain essential technologies for protecting users, services, and sensitive data.