API Client Authentication and Authorization with Duende IdentityServer

Learn how Duende IdentityServer handles web API authentication by separating authentication, authorization, and enforcement across clients and APIs.

Clifford Spielman |

Modern web APIs rarely exist in isolation. They are typically part of a larger system that includes one or more client applications, a centralized identity platform, and a set of protected backend services. In these systems, securing an API does not depend solely on its implementation. Instead, authentication and authorization decisions occur earlier, during interactions between client applications and an identity provider.

When using current implementations of Duende IdentityServer, this separation of responsibilities becomes clear. Duende IdentityServer handles authentication and authorization during interactions with client applications, issues tokens that represent the outcomes of those interactions, and enables APIs to remain focused on validating and enforcing access rather than authenticating users directly.

Rather than walking through configuration or setup steps, this article examines how Duende IdentityServer handles web API authentication by separating authentication, authorization, and enforcement responsibilities across clients and APIs.

Unless otherwise noted, this article assumes the use of self-contained access tokens, typically JSON Web Tokens (JWTs), that APIs can validate locally.

The Three Core Components in a Duende IdentityServer-Based System

A Duende IdentityServer-based system is easiest to understand when broken into three distinct components, each with a well-defined responsibility.

  1. The client application is the component that initiates authentication. This might be a browser-based application, a mobile app, a desktop client, a server-side application acting on its own behalf, or a combination of these types of applications. The client is responsible for redirecting users to IdentityServer when authentication is required and for requesting tokens that allow it to call secured APIs.
  2. Duende IdentityServer acts as the central authorization server. It authenticates end users or client applications, evaluates authorization requirements, and issues tokens that represent the outcome of those decisions. Duende IdentityServer is where identity, trust, and access policies are enforced.
  3. The API is the protected resource. It does not authenticate users directly. Instead, it validates tokens issued by IdentityServer and enforces authorization based on their contents.

These components interact at different stages, and not all participate in every request. Understanding when each component is involved is critical to designing systems correctly.

Where Authentication Actually Occurs

Authentication occurs between the client application and Duende IdentityServer, not between the client and API.

When a client needs to identify a user, it redirects the user to a designated login page hosted by Duende IdentityServer, where OpenID Connect is employed to perform the authentication. Duende IdentityServer also handles credential verification, multifactor authentication, and any other identity-related checks dictated by the system.

If authentication succeeds, Duende IdentityServer issues an ID token to the client application. This token represents the authenticated identity and is intended for the client’s internal use. It allows the client to identify the user and enables the client to manage its internal application state, whether session state or a different state management mechanism.

At this stage, no API has been contacted. Authentication is complete before any protected resource is involved, and the API remains unaware that authentication has even taken place. This separation ensures that APIs do not need to understand user credentials, authentication methods, or the client’s state management.

After a user successfully authenticates, the client typically requires an access token to call protected APIs. In interactive scenarios, this typically occurs through a direct token exchange between the client and IdentityServer, following the initial redirect-based login flow.

That exchange might look similar to the following snippet, where the client requests tokens from IdentityServer and provides Duende IdentityServer with proof that authentication has already completed successfully. That proof is conveyed through a small set of request parameters that identify the client, reference the completed authentication flow, and bind the token request to that interaction:

POST /connect/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
client_id=client-app
client_secret=secret
code=SplxlOBeZQQYbYS6WxSbIA
redirect_uri=https://app.example/callback
code_verifier=...

How Duende IdentityServer Represents Authorization

Authorization decisions are also made by IdentityServer, but they are represented differently.

When a client requests an access token for a protected API, IdentityServer evaluates the request based on the client’s identity, any associated user context, and authorization policies defined within IdentityServer.

The result of this process is an access token issued by IdentityServer. This token represents delegated authorization: it describes what the client application is allowed to access and under what conditions. Scopes and claims embedded in the token encode these decisions so that APIs can subsequently validate and enforce them.

At a high level, an access token issued by Duende IdentityServer contains claims that describe what the client is authorized to do and which API the token is intended for. An access token might include information similar to the following:

{
  "iss": "https://identityserver.example",
  "aud": "orders-api",
  "sub": "orders-service",
  "client_id": "orders-service",
  "scope": "orders.read",
  "exp": 1717257600
}

Crucially, Duende IdentityServer makes authorization decisions when tokens are issued during the authentication flow. APIs simply validate and enforce those decisions during normal request handling.

What Happens When the Client Calls the API

Once the client application obtains an access token from Duende IdentityServer, it can then call the protected API.

Each API request includes the access token, typically in the Authorization header. When the API receives the request, it validates the token locally. This validation confirms that the token was issued by Duende IdentityServer, has not expired, and is intended for the API that received it.

In practice, APIs typically express this trust relationship by configuring JWT validation against Duende IdentityServer as the token issuer (authority) and the API as the intended audience.

services.AddAuthentication("Bearer")
    .AddJwtBearer(options =>
    {
        options.Authority = "https://identityserver.example";
        options.Audience = "orders-api";
        options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };
    });

The API then enforces authorization rules based on the token’s contents. Scopes and claims determine whether the requested operation is permitted. If the token satisfies the API’s requirements, the request proceeds. If not, access is denied.

At no point during this process does the API authenticate the user or communicate directly with Duende IdentityServer. The API trusts IdentityServer’s prior decisions and focuses solely on enforcement.

Why Duende IdentityServer Is Not in the Request Path

A common misconception is that Duende IdentityServer participates in the handling of client requests to protected API endpoints. In reality, the authorization server is intentionally not involved in normal API request processing.

Duende IdentityServer’s responsibility ends once it issues a token and until that token expires. From that point forward, the token itself carries the necessary information. APIs validate tokens independently, without interacting with Duende IdentityServer.

This separation has important benefits. It improves scalability by removing a central dependency from every request. It increases reliability by allowing APIs to continue functioning independently for the lifetime of tokens currently issued, even if the identity system is temporarily unavailable. It also enforces clean architectural boundaries between identity concerns and business logic.

Common Sources of Confusion

Many potential security issues arise from misunderstanding the boundaries between authentication, authorization, and APIs. These challenges are common in systems based on OAuth and OpenID Connect, including those built with Duende IdentityServer.

Some of these misunderstandings include:

  • Using ID tokens as authorization credentials for APIs: ID tokens describe authentication outcomes and are intended for client applications, not APIs. Their audience is the client, and accepting them at the API boundary bypasses OAuth’s audience restriction, causing the API to trust a token that was never issued for it.
  • Expecting APIs to verify user identities: In a Duende IdentityServer-based system, APIs authenticate requests by validating tokens; they do not authenticate users or participate in login flows.
  • Treating Duende IdentityServer as a runtime dependency for authorization decisions: Embedding business logic into identity flows increases coupling and undermines the separation between identity concerns and application behavior.
  • Mistaking successful authentication for permission: Authentication establishes who an identity is; authorization determines what that identity is allowed to access.
  • Expecting Duende IdentityServer to provide runtime identity or authorization APIs: IdentityServer issues tokens that represent authentication and authorization decisions; it is not a general-purpose identity query service. Treating it as an authoritative runtime API encourages tight coupling and undermines token-based trust.

How Opaque Tokens Change the Request Path

While this article focuses primarily on self-contained access tokens such as JWTs and their role in authorization, some systems use opaque tokens instead. Opaque tokens do not carry claims or authorization data that APIs can interpret locally. Instead, they function as references that must be validated by the authorization server, in this case, Duende IdentityServer.

In an opaque token model, when an API receives a request, it cannot validate the token itself. The API must call back to Duende IdentityServer, typically using token introspection, where the API asks the authorization server whether the opaque token is valid and what access should be authorized.

This introduces Duende IdentityServer into the request path, making it a runtime dependency for authorization decisions.

This approach is useful when token contents must remain hidden from clients and intermediaries, or when immediate revocation may be required. However, this changes the system’s operational characteristics. Latency likely increases, scalability may be reduced, and API availability becomes tied to Duende IdentityServer’s availability.

The core separation of responsibilities remains the same, but the enforcement model differs. With opaque tokens, APIs must retrieve authorization information from IdentityServer when a client issues a request, rather than enforcing access solely based on information embedded in an access token.

In Duende IdentityServer, opaque tokens are only an access-token concern. ID tokens are always self-contained rather than opaque tokens, which means they require external validation.

Final Thoughts

When the boundaries between clients, Duende IdentityServer, and APIs are respected, systems become easier to understand, maintain, and secure.

Clients authenticate with Duende IdentityServer and request access tokens. Duende IdentityServer authenticates identities, evaluates authorization policy, and issues tokens that represent trust and permission. APIs then validate those tokens and enforce access control without participating in client authentication themselves.

This division of responsibility helps keep APIs lightweight and focused. Duende IdentityServer centralizes identity and access decisions.

As a standards-compliant and highly configurable identity platform, Duende IdentityServer provides the tooling and guidance to consistently apply the principles in this article to modern systems.