← Files Duende SkillsARCHIVED FILE
skills/token-management/docs/api-delegation.md
2.32 KB · Oct 2, 2026 · 00:31 UTC
## Pattern 6: API-to-API Token Delegation
An API that receives a user request and needs to call a downstream API can use either the user's access token (delegation) or a client credentials token (machine identity). Both approaches integrate cleanly with `IHttpClientFactory`. This pattern extends the core `token-management` skill.
### Approach A — Forward the User Token (Downstream API Trusts Upstream's Token)
When the downstream API accepts the same audience as the upstream token, forward it directly:
```csharp
// In the calling API's Program.cs
builder.Services.AddOpenIdConnectAccessTokenManagement();
builder.Services.AddUserAccessTokenHttpClient(
"downstream",
configureClient: client =>
{
client.BaseAddress = new Uri("https://downstream.company.com/api/");
});
```
```csharp
// In the controller
public sealed class UpstreamController(IHttpClientFactory factory) : ControllerBase
{
[HttpGet("data")]
public async Task<IActionResult> GetData(CancellationToken ct)
{
// ✅ Forwards the current user's access token to the downstream API
var client = factory.CreateClient("downstream");
var response = await client.GetAsync("resource", ct);
return Ok(await response.Content.ReadAsStringAsync(ct));
}
}
```
### Approach B — Use a Dedicated Client Credentials Token
When the downstream API requires a service identity rather than a user identity:
```csharp
// In the calling API's Program.cs
services.AddClientCredentialsTokenManagement()
.AddClient("downstream.client", client =>
{
client.TokenEndpoint = new Uri("https://sts.company.com/connect/token");
client.ClientId = ClientId.Parse("upstream-service");
client.ClientSecret = ClientSecret.Parse("...");
client.Scope = Scope.Parse("downstream:read");
});
services.AddClientCredentialsHttpClient(
"downstream",
ClientCredentialsClientName.Parse("downstream.client"),
client => { client.BaseAddress = new Uri("https://downstream.company.com/api/"); });
```
### Decision Guide
| Scenario | Approach |
|----------|----------|
| Downstream API accepts the same user token audience | A — forward user token |
| Downstream API requires a service identity | B — client credentials |
| OAuth 2.0 Token Exchange (RFC 8693) is needed | See `identityserver-token-lifecycle` skill |
SHA-256: 2ed2ff86ee989ff5dd2ce8403089406bfde5cce1eb4ef0d4f315e97b6b55d878