IdentityModel.OidcClient: Documentation for Duende's open-source IdentityModel.OidcClient library which can be used to build OIDC native clients with a variety of .NET UI tools
-----
# Duende IdentityModel OIDC Client
> A certified OpenID Connect relying party library for building native clients with .NET, supporting various UI frameworks and authentication flows
The `Duende.IdentityModel.OidcClient` library is a certified OpenID Connect relying party and implements [RFC 8252](https://tools.ietf.org/html/rfc8252/), “OAuth 2.0 for native Applications”. The `Duende.IdentityModel.OidcClient.Extensions` library provides support for [DPoP](https://datatracker.ietf.org/doc/html/rfc9449) extensions to Duende.IdentityModel.OidcClient for sender-constraining tokens. ## Use Cases [Section titled “Use Cases”](#use-cases) OidcClient targets .NET Standard, making it suitable for .NET and .NET Framework. It can be used to build OIDC native clients with a variety of .NET UI tools. * .NET MAUI * WPF with the system browser * WPF with an embedded browser * WinForms with an embedded browser * Cross-platform Console Applications (relies on kestrel for processing the callback) * Windows Console Applications (relies on an HttpListener - a wrapper around the windows HTTP.sys driver) * Windows Console Applications using custom uri schemes ## License and Feedback [Section titled “License and Feedback”](#license-and-feedback) `Duende.IdentityModel.OidcClient` is released as open source under the [Apache 2.0 license](https://github.com/DuendeSoftware/foss/blob/main/LICENSE). Bug reports and contributions are welcome at [the GitHub repository](https://github.com/DuendeSoftware/foss). [GitHub Repository ](https://github.com/DuendeSoftware/foss/tree/main/identity-model-oidc-client)View the source code for this library on GitHub. [NuGet Package ](https://www.nuget.org/packages/Duende.IdentityModel.OidcClient/)View the package on NuGet.org.
-----
# Demonstrating Proof-of-Possession (DPoP)
> Learn how to leverage Demonstrating Proof-of-Possession when using OidcClient to build a native OIDC client.
[DPoP](https://datatracker.ietf.org/doc/html/rfc9449) specifies how to bind an asymmetric key stored within a JSON Web Key (JWK) to an access token. This will make the access token bound to the key such that if the access token were to leak, it cannot be used without also having access to the private key of the corresponding JWK. The `Duende.IdentityModel.OidcClient.Extensions` library adds supports for DPoP to OidcClient. ## DPoP Key [Section titled “DPoP Key”](#dpop-key) Before we begin, your application needs to have a DPoP key in the form of a JSON Web Key (or JWK). According to the [DPoP specification](https://datatracker.ietf.org/doc/html/rfc9449), this key needs to use an asymmetric algorithm (“RS”, “ES”, or “PS” style). You can create a JWK in .NET using the `Duende.IdentityModel.OidcClient.Extensions` library. The `JsonWebKeys` class has several static methods to help with creating JWKs using various algorithms. Program.cs ```csharp using Duende.IdentityModel.OidcClient.DPoP; // Creates a JWK using the PS256 algorithm: var jwk = JsonWebKeys.CreateRsaJson(); Console.WriteLine(jwk); ``` Caution In a production scenario, you’ll want to store this JWK in a secure location and use ASP.NET’s [data protection](https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/) to further protect the JWK. See [our data protection guide](/identityserver/deployment/#aspnet-core-data-protection) for more information. ## Initializing the OIDC client with DPoP support [Section titled “Initializing the OIDC client with DPoP support”](#initializing-the-oidc-client-with-dpop-support) We will need to extend the `OidcClientOptions` before we can use DPoP. After creating the `OidcClientOptions` to connect our client application with the Identity Provider, we retrieve a JWK to use for DPoP, and add that JWK to our `options` by calling the `ConfigureDPoP` extension method: Program.cs ```csharp using Duende.IdentityModel.OidcClient; using Duende.IdentityModel.OidcClient.DPoP; var options = new OidcClientOptions { Authority = "https://demo.duendesoftware.com", ClientId = "native.dpop", Scope = "openid profile email offline_access", // ... }; // creates a new JWK, or returns an existing one var jwk = GetDPoPJwk(); // Enable DPoP options.ConfigureDPoP(jwk); var oidcClient = new OidcClient(options); ``` ## Proof Tokens for the API [Section titled “Proof Tokens for the API”](#proof-tokens-for-the-api) Now that we’ve configured the `OidcClientOptions` with DPoP support and created an `OidcClient` instance, you can use this instance to create an `HttpMessageHandler` which will: * manage access and refresh tokens * add DPoP proof tokens to HTTP requests The `OidcClient` provides `CreateDPoPHandler` as a convenience method to create such a handler, which can be used with the .NET `HttpClient`. Program.cs ```csharp var sessionRefreshToken = "..."; // read from a previous session, if any var handler = oidcClient.CreateDPoPHandler(jwk, sessionRefreshToken); var apiClient = new HttpClient(handler); ``` For a full example, have a look at our [WPF with the system browser](https://github.com/DuendeSoftware/foss/tree/main/identity-model-oidc-client/samples/Wpf) sample.
-----
# OIDC Client Automatic Mode
> Learn how to implement automatic OAuth/OIDC authentication by encapsulating browser interactions using OidcClient
OpenID Connect (OIDC) is an identity layer on top of the OAuth 2.0 protocol. It allows clients to verify the identity of the end-user based on the authentication performed by an authorization server, as well as obtain basic profile information. An essential part of the OIDC flow is the use of a browser to interact with the end-user and to obtain permissions to access protected resources. In the OidcClient library, you can encapsulate the browser interaction by implementing the [IBrowser](https://github.com/DuendeSoftware/foss/blob/main/identity-model-oidc-client/src/IdentityModel.OidcClient/Browser/IBrowser.cs) interface. Using `IBrowser` helps create a reusable component for all OIDC interaction. ```csharp // Copyright (c) Duende Software. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. namespace Duende.IdentityModel.OidcClient.Browser; /// /// Models a browser /// public interface IBrowser { /// /// Invokes the browser. /// /// The options. /// A token that can be used to cancel the request /// Task InvokeAsync(BrowserOptions options, CancellationToken cancellationToken = default); } ``` The `BrowserResult` represents the result of the browser interaction, including any OIDC payloads that are returned from the authentication server. ```csharp // Copyright (c) Duende Software. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. namespace Duende.IdentityModel.OidcClient.Browser; /// /// The result from a browser login. /// /// public class BrowserResult : Result { /// /// Gets or sets the type of the result. /// /// /// The type of the result. /// public BrowserResultType ResultType { get; set; } /// /// Gets or sets the response. /// /// /// The response. /// public string Response { get; set; } } ``` For a simple example, the following code shows how to use the [SystemBrowser](https://github.com/DuendeSoftware/foss/blob/main/identity-model-oidc-client/clients/ConsoleClientWithBrowser/SystemBrowser.cs) to invoke a browser on the host desktop platform. The `SystemBrowser` is a naive implementation that uses the [System.Diagnostics.Process](https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process) class to start the system default browser. ```csharp var options = new OidcClientOptions { Authority = "https://demo.duendesoftware.com", ClientId = "native", RedirectUri = redirectUri, Scope = "openid profile api", Browser = new SystemBrowser() }; var client = new OidcClient(options); ``` Once the `IBrowser` is configured, the `LoginAsync` method can be invoked to start the authentication flow. ```csharp var result = await client.LoginAsync(); ``` Setting the `Browser` property reduces the need to process browser respones and to handle the `BrowserResult` directly. When using this automatic mode, the `LoginAsync` method will return a [`LoginResult`](https://github.com/DuendeSoftware/foss/blob/19370c6d4820a684d41d1d40b8192ee8b873b8f0/identity-model-oidc-client/src/IdentityModel.OidcClient/LoginResult.cs) which will contain a `ClaimsPrincipal` with the user’s claims along with the `IdentityToken` and `AccessToken`.
-----
# OIDC Client Logging
> Learn how to configure and customize logging in OidcClient using Microsoft.Extensions.Logging.ILogger
`OidcClient` logs errors, warnings, and diagnostic information using `Microsoft.Extensions.Logging.ILogger`, the standard .NET logging library. You can use any logging provider to store your logs however you like, by setting the `LoggerFactory` property on `OidcClientOptions`: Program.cs ```csharp using Duende.IdentityModel; using Duende.IdentityModel.OidcClient; var builder = Host.CreateApplicationBuilder(args); builder.Services.AddSingleton(svc => { var loggerFactory = svc.GetRequiredService(); var options = new OidcClientOptions { Authority = "https://demo.duendesoftware.com", ClientId = "interactive.public", Scope = "openid profile email offline_access", RedirectUri = "app://localhost/", PostLogoutRedirectUri = "app://localhost/", LoggerFactory = loggerFactory }; return new OidcClient(options); }); var app = builder.Build(); var client = app.Services.GetService(); ``` Using this approach, you can use other logging frameworks, like [Serilog](https://github.com/serilog/serilog-extensions-hosting) for example. For general information on how to configure logging in .NET applications, see our [Logging Fundamentals](/general/logging/) guide. ## Log Levels [Section titled “Log Levels”](#log-levels) The `OidcClient` logs at the following levels: * `Trace` * `Debug` * `Information` * `Error` You can set the log level in your `appsettings.json` by modifying the following snippet. appsettings.json ```json { "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information", "Duende.IdentityModel.OidcClient": "Error" } } } ```
-----
# OIDC Client Manual Mode
> Guide for implementing manual mode in OidcClient to handle browser interactions and token processing
OpenID Connect is a protocol that allows you to authenticate users using a browser and involves browser-based interactions. When using this library you can choose between two modes: [automatic](/identitymodel-oidcclient/automatic/) and manual. We recommend using automatic mode when possible, but sometimes you need to use manual mode when you want to handle browser interactions yourself. With manual mode, `OidcClient` is still useful, as it helps with creating the necessary start URL and state parameters needed to complete an OIDC flow. You’ll need to handle all browser interactions yourself with custom code. This is beneficial for scenarios where you want to customize the browser experience or when you want to integrate with other platform-specific browser libraries. ```csharp var options = new OidcClientOptions { Authority = "https://demo.duendesoftware.com", ClientId = "native", RedirectUri = redirectUri, Scope = "openid profile api" }; var client = new OidcClient(options); // generate start URL, state, nonce, code challenge var state = await client.PrepareLoginAsync(); ``` When the browser work is done, `OidcClient` can take over to process the response, get the access/refresh tokens, contact userinfo endpoint etc.: ```csharp var result = await client.ProcessResponseAsync(data, state); ``` When using this manual mode, and processing the response, the `ProcessResponseAsync` method will return a [`LoginResult`](https://github.com/DuendeSoftware/foss/blob/19370c6d4820a684d41d1d40b8192ee8b873b8f0/identity-model-oidc-client/src/IdentityModel.OidcClient/LoginResult.cs) which will contain a `ClaimsPrincipal` with the user’s claims along with the `IdentityToken` and `AccessToken`.
-----
# Duende IdentityModel OIDC Client Samples
> A collection of sample applications demonstrating how to use IdentityModel.OidcClient with various platforms and UI frameworks.
Samples of IdentityModel.OidcClient are available [on GitHub](https://github.com/DuendeSoftware/foss/tree/main/identity-model-oidc-client/samples). Our samples show how to use an OidcClient with a variety of platforms and UI tools, including: * [.NET MAUI](https://github.com/DuendeSoftware/foss/tree/main/identity-model-oidc-client/samples/Maui) * [WPF with the system browser](https://github.com/DuendeSoftware/foss/tree/main/identity-model-oidc-client/samples/Wpf) * [WPF with an embedded browser](https://github.com/DuendeSoftware/foss/tree/main/identity-model-oidc-client/samples/WpfWebView2) * [WinForms with an embedded browser](https://github.com/DuendeSoftware/foss/tree/main/identity-model-oidc-client/samples/WinFormsWebView2) * [Cross Platform Console Applications](https://github.com/DuendeSoftware/foss/tree/main/identity-model-oidc-client/samples/NetCoreConsoleClient) (relies on kestrel for processing the callback) * [Windows Console Applications](https://github.com/DuendeSoftware/foss/tree/main/identity-model-oidc-client/samples/HttpSysConsoleClient) (relies on an HttpListener - a wrapper around the windows HTTP.sys driver) * [Windows Console Applications using custom uri schemes](https://github.com/DuendeSoftware/foss/tree/main/identity-model-oidc-client/samples/WindowsConsoleSystemBrowser) All samples use a [demo instance of Duende IdentityServer](https://demo.duendesoftware.com) as their OIDC Provider. You can see its [source code on GitHub](https://github.com/DuendeSoftware/demo.duendesoftware.com). You can log in with *alice/alice* or *bob/bob* ## Additional samples [Section titled “Additional samples”](#additional-samples) * [Unity3D](https://github.com/peterhorsley/Unity3D.Authentication.Example) ## No Longer Maintained [Section titled “No Longer Maintained”](#no-longer-maintained) These samples are no longer maintained because their underlying technology is no longer supported. * [UWP](https://github.com/IdentityModel/IdentityModel.OidcClient.Samples/tree/archived/uwp/Uwp) * [Xamarin](https://github.com/IdentityModel/IdentityModel.OidcClient.Samples/tree/archived/xamarin/XamarinAndroidClient) * [Xamarin Forms](https://github.com/IdentityModel/IdentityModel.OidcClient.Samples/tree/archived/xamarin/XamarinForms) * [Xamarin iOS - AuthenticationServices](https://github.com/IdentityModel/IdentityModel.OidcClient.Samples/tree/archived/xamarin/iOS_AuthenticationServices) * [Xamarin iOS - SafariServices](https://github.com/IdentityModel/IdentityModel.OidcClient.Samples/tree/archived/xamarin/iOS_SafariServices)