Skip to content

Commit 78636fa

Browse files
authored
Merge pull request #766 from DuendeSoftware/wca/oidc-client-dpop-extensions
Add documentation of how to use the Duende.IdentityModel.OidcClient.Extensions package to implement DPoP
2 parents 19a1b0b + 86fb52d commit 78636fa

File tree

5 files changed

+107
-4
lines changed

5 files changed

+107
-4
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
label: 'Advanced'
2+
order: 6
3+
collapsed: true
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
title: Demonstrating Proof-of-Possession (DPoP)
3+
description: Learn how to leverage Demonstrating Proof-of-Possession when using OidcClient to build a native OIDC client.
4+
sidebar:
5+
label: DPoP
6+
order: 1
7+
---
8+
9+
[DPoP][dpop-spec] specifies how to bind an asymmetric key stored
10+
within a JSON Web Key (JWK) to an access token. This will make the access token bound to the key such that if the
11+
access token were to leak, it cannot be used without also having access to the private key of the corresponding JWK.
12+
13+
The `Duende.IdentityModel.OidcClient.Extensions` library adds supports for DPoP to OidcClient.
14+
15+
## DPoP Key
16+
17+
Before we begin, your application needs to have a DPoP key in the form of a
18+
JSON Web Key (or JWK). According to the [DPoP specification][dpop-spec], this
19+
key needs to use an asymmetric algorithm ("RS", "ES", or "PS" style).
20+
21+
:::note
22+
The client application is responsible for creating the DPoP key,
23+
rotating it, and managing its lifetime. For as long as there are access tokens
24+
(and possibly refresh tokens) bound to a DPoP key, that key needs to remain
25+
available to the client application.
26+
:::
27+
28+
You can create a JWK in .NET using the `Duende.IdentityModel.OidcClient.Extensions` library.
29+
The `JsonWebKeys` class has several static methods to help with creating JWKs using various algorithms.
30+
31+
```csharp
32+
// Program.cs
33+
using Duende.IdentityModel.OidcClient.DPoP;
34+
35+
// Creates a JWK using the PS256 algorithm:
36+
var jwk = JsonWebKeys.CreateRsaJson();
37+
38+
Console.WriteLine(jwk);
39+
```
40+
41+
:::caution
42+
In a production scenario, you'll want to store this JWK in a secure location
43+
and use ASP.NET's [data protection](https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/) to further
44+
protect the JWK. See [our data protection guide](/identityserver/deployment#aspnet-core-data-protection) for more
45+
information.
46+
:::
47+
48+
## Initializing the OIDC client with DPoP support
49+
50+
We will need to extend the `OidcClientOptions` before we can use DPoP.
51+
52+
After creating the `OidcClientOptions`
53+
to connect our client application with the Identity Provider, we retrieve a JWK to use for DPoP, and add that JWK
54+
to our `options` by calling the `ConfigureDPoP` extension method:
55+
56+
```csharp
57+
// Program.cs
58+
using Duende.IdentityModel.OidcClient;
59+
using Duende.IdentityModel.OidcClient.DPoP;
60+
61+
var options = new OidcClientOptions
62+
{
63+
Authority = "https://demo.duendesoftware.com",
64+
ClientId = "native.dpop",
65+
Scope = "openid profile email offline_access",
66+
// ...
67+
};
68+
69+
// creates a new JWK, or returns an existing one
70+
var jwk = GetDPoPJwk();
71+
72+
// Enable DPoP
73+
options.ConfigureDPoP(jwk);
74+
75+
var oidcClient = new OidcClient(options);
76+
```
77+
78+
## Proof Tokens for the API
79+
80+
Now that we've configured the `OidcClientOptions` with DPoP support and created an
81+
`OidcClient` instance, you can use this instance to create an `HttpMessageHandler` which
82+
will:
83+
84+
- manage access and refresh tokens
85+
- add DPoP proof tokens to HTTP requests
86+
87+
The `OidcClient` provides `CreateDPoPHandler` as a convenience method to create such a handler,
88+
which can be used with the .NET `HttpClient`.
89+
90+
```csharp
91+
// Program.cs
92+
var sessionRefreshToken = "..."; // read from a previous session, if any
93+
94+
var handler = oidcClient.CreateDPoPHandler(jwk, sessionRefreshToken);
95+
var apiClient = new HttpClient(handler);
96+
```
97+
98+
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.
99+
100+
[dpop-spec]: https://datatracker.ietf.org/doc/html/rfc9449

src/content/docs/identitymodel-oidcclient/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ relying party implementation.**
1717

1818
The `Duende.IdentityModel.OidcClient` library is a certified OpenID Connect relying party and
1919
implements [RFC 8252](https://tools.ietf.org/html/rfc8252/), "OAuth 2.0 for native
20-
Applications". The `Duende.IdentityModel.OidcClient.Extensions` provides support for
20+
Applications". The `Duende.IdentityModel.OidcClient.Extensions` library provides support for
2121
[DPoP](https://datatracker.ietf.org/doc/html/rfc9449)
2222
extensions to Duende.IdentityModel.OidcClient for sender-constraining tokens.
2323

src/content/docs/identitymodel-oidcclient/samples.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ redirect_from:
99
---
1010

1111
Samples of IdentityModel.OidcClient are available [on
12-
GitHub](https://github.com/IdentityModel/IdentityModel.OidcClient.Samples). Our samples
13-
show how to use a OidcClient with a variety of platforms and UI tools, including:
12+
GitHub](https://github.com/DuendeSoftware/foss/tree/main/identity-model-oidc-client/samples). Our samples
13+
show how to use an OidcClient with a variety of platforms and UI tools, including:
1414

1515
- [.NET MAUI](https://github.com/DuendeSoftware/foss/tree/main/identity-model-oidc-client/samples/Maui)
1616
- [WPF with the system browser](https://github.com/DuendeSoftware/foss/tree/main/identity-model-oidc-client/samples/Wpf)

src/content/docs/identityserver/troubleshooting.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Core Authentication libraries. If it is not correctly configured it might result
4646
- The key `{xxxxx-xxxx-xxx-xxx-xxxxxxx}` was not found in the key ring.
4747
- Failed to unprotect AuthenticationTicket payload for key `{key}`
4848

49-
See [our data protection guide](/identityserver/deployment#data-protection-keys) for more
49+
See [our data protection guide](/identityserver/deployment#aspnet-core-data-protection) for more
5050
information.
5151

5252
## Load Balancing, proxies and TLS offloading

0 commit comments

Comments
 (0)