惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

有赞技术团队
有赞技术团队
G
Google Developers Blog
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
J
Java Code Geeks
P
Proofpoint News Feed
V
Visual Studio Blog
爱范儿
爱范儿
The Cloudflare Blog
博客园 - 叶小钗
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
M
MIT News - Artificial intelligence
Microsoft Security Blog
Microsoft Security Blog
博客园 - 聂微东
H
Help Net Security
B
Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 【当耐特】
量子位
宝玉的分享
宝玉的分享
WordPress大学
WordPress大学
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

Duende Software Official Site

WhatsApp One-Time Password (OTP) Login with Duende IdentityServer and User Management Planning a Successful Migration from IdentityServer3 to Duende IdentityServer Client Secrets, Mutual TLS and Private Key JWT, Oh My! How To Spell "Duende" Understanding .NET 11 Automatic CSRF Protection: A Guide for Identity Developers Security Lingo Explained: TOTP (Time-based One-Time Password) Custom Passkey Attestation Policies: Restricting Login to Hardware Keys OAuth Identity Chaining, Transaction Tokens, and Human-in-the-Loop: Summer 2026 Identity Standards Recap What is Identity? - The Question Every Team Should Answer Before Writing Code Security Is a Spectrum: How to Choose Session Lifetimes in Duende IdentityServer Passkeys and WebAuthn with Duende IdentityServer and User Management Authenticating Players in Godot 4 with OAuth 2.0 and OpenID Connect Hardening OAuth in the newest 2026-07-28 MCP Release Candidate Unify Your SAML and OIDC Signing Keys with Automatic Rotation and Duende IdentityServer Duende Software Duende Software Duende Software Duende Software Duende Software Duende Software Duende Software Duende Software Stop AI Bots from Wasting Your Server How Duende IdentityServer Filters Claims (And Why It Matters) Core vs Extended Protocols in Duende IdentityServer v8: What You Get and When You Need More Your IdentityServer v8 Upgrade Checklist: A Quick Pre-Flight Guide Setting Up SAML Single Sign-On in ASP.NET with Duende IdentityServer Your Identity, Your Terms: Duende's Modular Identity Infrastructure and v8.x Release Duende Spring Launch '26: Identity Infrastructure That Expands With You SAML and OpenID Connect (OIDC): Coexistence, Not Competition
Implementing Zero Trust with Resource Isolation
Maarten Balliauw · 2026-02-10 · via Duende Software Official Site

There's a good chance your application consumes one or more APIs. For example, you may have a back-office application that works with a shipping API and an invoice API. Or perhaps you have a microservice architecture, and there are 50 different APIs involved.

In this landscape, one of the most persistent security anti-patterns we see is having access tokens with too much access. An overprivileged token occurs when a client requests a wide array of scopes, for example, invoice.read, shipping.write, and, and receives a single access token that contains all the issued claims.

While asking for multiple scopes at once can be convenient, the issued token raises a concerning trust issue. If the shipping API is compromised and the token is leaked, an attacker can use it to access the invoice API. The attacker has a token that’s issued once, but usable against almost every service within a solution. We’ve sacrificed security for convenience, which can weaken our security posture.

This is where Resource Isolation comes in. Based on RFC 8707 (Resource Indicators for OAuth 2.0), this feature allows you to enforce strict trust boundaries between your APIs, ensuring that a token is only valid for the specific target it was intended for.

The Problem With Audience Ambiguity

In OAuth 2.0, the aud (audience) claim tells an API, "this token is for you." However, in many default implementations, the audience is either a single value shared by all APIs, or a list of all valid audiences.

If you have a large system, your token might look like this:

Json

{
  "iss": "https://identity.duendesoftware.com",
  "aud": ["invoice_api", "shipping_api", "inventory_api"],
  "scope": ["invoice.read", "shipping.write", "inventory.read"]
}

This token is valid at three different services: invoice_api, shipping_api, and inventory_api. This violates the Principle of Least Privilege. In a Zero Trust architecture, we want to ensure that a token sent to the Shipping API is unusable at the Invoice API.

OAuth And Resource Indicators (RFC 8707)

Resource Isolation forces a change in how we think about requesting access. Instead of just asking for "what I want to do" (Scopes), the client must also specify "where I want to do it" (Resources).

When Resource Isolation is enabled, the IdentityServer engine performs a crucial check: it calculates the intersection of the requested scopes and the requested resource. The resulting access token is "downscoped" to contain only the permissions relevant to the resource(s) you requested.

Configuring Resource Isolation (Server-Side)

Configuring Resource Isolation in Duende IdentityServer requires the Enterprise plan, and configuration updates to shift from defining ApiScopes to grouping them under ApiResources.

Here is how you configure a resource to enforce this isolation in your Config.cs. Note that while the resource id in this code snippet is a Uniform Resource Name (URN), you can use any type of identifier here.

Csharp

public static IEnumerable<ApiResource> ApiResources =>
    new List<ApiResource>
    {
        new ApiResource("urn:invoice-service", "Invoice Microservice")
        {
            // These scopes are now exclusively bound to this resource
            Scopes = { "invoice.read", "invoice.pay" },
            
            // This turns on the requirement for resource isolation
            RequireResourceIndicator = true
        },
        new ApiResource("urn:shipping-service", "Shipping Microservice")
        {
            Scopes = { "shipping.write" },
            RequireResourceIndicator = true
        }
    };

By setting RequireResourceIndicator = true, you are telling IdentityServer to reject any token request that includes these scopes unless the client explicitly specifies the target resource.

Client Implementation

Enforcing resource isolation on the server is only half the battle. Your clients must now explicitly signal which resource they intend to access. If they don't, IdentityServer will reject the request with an invalid_target error.

Machine-to-Machine (Worker)

For background workers or daemons using the Client Credentials flow, you typically use the Duende.IdentityModel library.
The ClientCredentialsTokenRequest object includes a Resource collection where you can add any number of resource indicators:

Csharp

using Duende.IdentityModel.Client;

var client = new HttpClient();

var response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
    Address = "https://demo.duendesoftware.com/connect/token",
    ClientId = "invoice_worker",
    ClientSecret = "secret",
    
    // The scope defines the permission
    Scope = "invoice.read", 
    
    // The parameter defines the target (RFC 8707)
    Resource = [ "urn:invoice-service" ]
});

In this example, the resulting access token will contain only the urn:invoice-service audience. If the worker later needs to talk to the shipping service, it must make a separate token request targeting urn:shipping-service.

Interactive Web Apps and ASP.NET Core

For user-facing applications using the standard OpenID Connect handler in ASP.NET Core, you can utilize the Resource property directly on the OpenIdConnectOptions. It ensures the resource parameter is sent not only during the initial redirect to the login page but also during the back-channel exchange of the authorization code for the access token.

Csharp

services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
    options.Authority = "https://demo.duendesoftware.com";
    options.ClientId = "interactive_app";
    options.ClientSecret = "secret";
    
    // Standard scopes
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("invoice.read");

    // Explicitly set the target resource here
    options.Resource = "urn:invoice-service";
    
    options.ResponseType = "code";
    options.SaveTokens = true;
});

Keep in mind that while the RFC allows multiple resource parameters, the Microsoft OpenID Connect handler only supports a single resource value here.

Note the Resource property can also be set as a parameter in the OnRedirectToIdentityProvider event, which may be helpful if you need to execute custom code and logic to determine the resource, for example, in multi-tenant environments:

Csharp

.AddOpenIdConnect(options =>
{
    // ... existing configuration ...

    options.Events.OnRedirectToIdentityProvider = context =>
    {
        var tenantSpecificResource = DetermineResource(context);

        // Overwrite or set the 'resource' parameter
        context.ProtocolMessage.SetParameter("resource", tenantSpecificResource);

        return Task.CompletedTask;
    };
});

Summary

Adopting Resource Isolation is one of the highest-value changes you can make to harden your security posture. You will generally see smaller tokens, and benefit from a reduced blast radius when a token is compromised. In addition, you can audit which resource a token was generated for, which may help with compliance needs.

While resource isolation introduces some complexity in client-side state management (requiring management of multiple tokens rather than one), the security benefits for enterprise-scale systems are undeniable.

If you are building an architecture that consists of multiple services and APIs working together, we highly recommend evaluating Resource Isolation in Duende IdentityServer to ensure trust boundaries between services are respected.