Skip to main content
net10.0

Dependency injection and IHttpClientFactory integration for Duende.Labs.IdentityModel

Published
Jul 29, 2026
2mo ago
Total Downloads
338
338

Install

dotnet add package Duende.Labs.IdentityModel.DependencyInjection --version 2026.729.19
ProductVersions
.NET
net10.0

README

IdentityModel dependency injection for .NET

Dependency injection and IHttpClientFactory integration for Duende.Labs.IdentityModel.

Installation

dotnet add package Duende.Labs.IdentityModel.DependencyInjection

Note This package is experimental/preview.

What it does

Duende.Labs.IdentityModel is a dependency-free set of HttpClient extensions. Every request carries its own endpoint address and client credential. In an application those values are fixed per authority, so this package lets you configure them once:

services.AddIdentityModelClient(options =>
{
    options.Authority = new Uri("https://demo.duendesoftware.com");
    options.ClientCredential = new ClientCredential("m2m", "secret");
    options.Scope = "api";
});
public class Worker(IdentityModelClient client)
{
    public async Task RunAsync(CancellationToken ct)
    {
        var result = await client.RequestClientCredentialsTokenAsync(ct);
    }
}

Endpoints are resolved from the authority's discovery document, which is fetched once and reused for DiscoveryRefreshInterval (24 hours by default). Failed retrievals are never cached. If the authority or discovery policy changes, for example through a configuration reload, the cached document is discarded and re-fetched rather than served until the interval lapses.

Named clients

services.AddIdentityModelClient("customers", options => { /* ... */ });
services.AddIdentityModelClient("partners", options => { /* ... */ });

Resolve them with keyed services:

public class Worker([FromKeyedServices("customers")] IdentityModelClient client);

Adjusting individual requests

Each method takes an optional delegate that receives the request built from your configuration:

var result = await client.RequestClientCredentialsTokenAsync(
    ct,
    request => request with { Scope = "api.read" });

Composing handlers

Registration returns the IHttpClientBuilder for the backing client, so caching, resilience and telemetry compose as usual — and apply to discovery too:

services
    .AddIdentityModelClient(options => { /* ... */ })
    .AddHttpMessageHandler<MyHandler>()
    .AddStandardResilienceHandler();

Configuration binding

services.AddIdentityModelClient(builder.Configuration.GetSection("IdentityProvider"));

Recognised keys are Authority, ClientId, ClientSecret, ClientCredentialStyle, Scope, DiscoveryRefreshInterval, and the endpoint overrides. Relative endpoint overrides are resolved against Authority. Values are read explicitly rather than through reflection-based binding, so the package stays trim and AOT compatible.

Testing

There are no interfaces to mock. IdentityModelClient is a sealed concrete type; substitute an HttpMessageHandler instead:

services
    .AddIdentityModelClient(options => { /* ... */ })
    .ConfigurePrimaryHttpMessageHandler(() => new FakeHandler());

Scope

This package stops at endpoint resolution and configured defaults. Token caching, automatic refresh and DPoP nonce handling belong to Duende.AccessTokenManagement.

License

IdentityModel is open source under the Apache 2.0 license.

Adoption Assessment

A verified publisher signal is available. Assess fit from the package's supported frameworks, license and dependency graph rather than popularity alone.

No SPDX license expression is published. Review the license text and your organisation's policy before redistribution.Compatibility metadata lists 1 target framework; confirm the exact target used by your application.

Related Guides & Workflows

Learn how to evaluate, integrate, or audit this package in your .NET project.