Skip to content

Commit 865883f

Browse files
Merge pull request #693 from DuendeSoftware/fix-sidebar-labels
Add sidebar labels and refine documentation structure
2 parents 199cc86 + 5100489 commit 865883f

File tree

75 files changed

+803
-579
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+803
-579
lines changed

.idea/dictionaries/project.xml

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ WebStorm has Grazie as a built-in spell checker and grammar checker, and support
6262
* You can link to header anchors using the `#` symbol, for example `[multiple authentication methods](/identityserver/ui/federation.md#multiple-authentication-methods-for-users)`.
6363
* Link relevant text. Prefer `learn more about [improving the sign-in experience]` over `click [here] to learn more`.
6464
* Run `npm run linkchecker` to validate all links (note this will ignore links to GitHub because of rate limits in place).
65+
* When a markdown link is long (75+ characters) or a link is repeated multiple times on a page, prefer moving the link to the bottom of the file and using markdown anchor syntax `[test.cs][repo-test-file]`
6566

6667
### Code Block Style
6768

@@ -74,19 +75,23 @@ WebStorm has Grazie as a built-in spell checker and grammar checker, and support
7475
* Make sure examples are runnable and complete. The goal is "Copy-paste from docs". Include namespaces, a result, and other prerequisites that are not obvious to someone new to the code.
7576
* Inline comments can be used to explain essential parts of the code. Expressive code can highlight line numbers, show diffs, and more.
7677
* Mention NuGet packages as a `bash` code block showing how to install it (`dotnet add package ...`). Link to the NuGet Gallery.
78+
* When referencing a property, field, class, or other symbol in text, use the `test` format instead of *test*.
79+
* Values should also be back-ticked, especially HTTP Status codes like `404` or `401`.
80+
* Make sure code blocks start at the very first character space and don't have excessive starting padding.
7781

7882
### Frontmatter Rules
7983

8084
* Always have a `title` property to set the page title.
81-
* Always have a `description` property to set the page description.
85+
* Always have a `description` property to set the page description. This is a summary of the page's core content.
8286
* Always have a `date` property to set the creation/significant update date for a page. Use the `YYYY-MM-DD` format.
83-
* Add the `sidebar` property and include the `label`. The `label` is used in the menu, and should typically be shorter than the more descriptive `title`. For example:
87+
* Add the `sidebar` property and must include the `label` and `order`. The `label` is used in the menu, and should typically be shorter than the more descriptive `title`. For example:
88+
8489
```yaml
8590
title: "Using IdentityServer As A Federation Gateway"
8691
sidebar:
8792
label: "Federation"
93+
order: 1
8894
```
89-
* In the `sidebar` property, use `order` to re-order entries in the navigation bar.
9095
9196
## 🧞 Commands
9297

src/content/docs/accesstokenmanagement/advanced/client-assertions.md

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
title: Client Assertions
33
description: Learn how to use client assertions instead of shared secrets for token client authentication in Duende.AccessTokenManagement.
44
sidebar:
5+
label: Client Assertions
56
order: 30
67
redirect_from:
78
- /foss/accesstokenmanagement/advanced/client_assertions/
@@ -14,34 +15,36 @@ If your token client is using a client assertion instead of a shared secret, you
1415

1516
Here's a sample client assertion service using the Microsoft JWT library:
1617

17-
```cs
18-
public class ClientAssertionService : IClientAssertionService
19-
{
20-
private readonly IOptionsSnapshot<ClientCredentialsClient> _options;
21-
22-
public ClientAssertionService(IOptionsSnapshot<ClientCredentialsClient> options)
23-
{
24-
_options = options;
25-
}
18+
```csharp
19+
// ClientAssertionService.cs
20+
using Duende.AccessTokenManagement;
21+
using Duende.IdentityModel;
22+
using Duende.IdentityModel.Client;
23+
using Microsoft.Extensions.Options;
24+
using Microsoft.IdentityModel.JsonWebTokens;
25+
using Microsoft.IdentityModel.Tokens;
2626

27+
public class ClientAssertionService(IOptionsSnapshot<ClientCredentialsClient> options)
28+
: IClientAssertionService
29+
{
2730
public Task<ClientAssertion?> GetClientAssertionAsync(
2831
string? clientName = null, TokenRequestParameters? parameters = null)
2932
{
3033
if (clientName == "invoice")
3134
{
32-
var options = _options.Get(clientName);
35+
var options1 = options.Get(clientName);
3336

3437
var descriptor = new SecurityTokenDescriptor
3538
{
36-
Issuer = options.ClientId,
37-
Audience = options.TokenEndpoint,
39+
Issuer = options1.ClientId,
40+
Audience = options1.TokenEndpoint,
3841
Expires = DateTime.UtcNow.AddMinutes(1),
3942
SigningCredentials = GetSigningCredential(),
4043

4144
Claims = new Dictionary<string, object>
4245
{
4346
{ JwtClaimTypes.JwtId, Guid.NewGuid().ToString() },
44-
{ JwtClaimTypes.Subject, options.ClientId! },
47+
{ JwtClaimTypes.Subject, options1.ClientId! },
4548
{ JwtClaimTypes.IssuedAt, DateTime.UtcNow.ToEpochTime() }
4649
},
4750

@@ -63,6 +66,11 @@ public class ClientAssertionService : IClientAssertionService
6366

6467
return Task.FromResult<ClientAssertion?>(null);
6568
}
69+
70+
private SigningCredentials GetSigningCredential()
71+
{
72+
throw new NotImplementedException();
73+
}
6674
}
6775
```
6876

src/content/docs/accesstokenmanagement/advanced/client-credentials.md

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ redirect_from:
88
- /foss/accesstokenmanagement/advanced/client_credentials/
99
---
1010

11-
The most common way to use the access token management for machine to machine communication is described [here](/accesstokenmanagement/workers) - however you may want to customize certain aspects of it - here's what you can do.
11+
The most common way to use the access token management for [machine-to-machine communication](/accesstokenmanagement/workers) - however, you may want to customize certain aspects of it. Here's what you can do.
1212

13-
## Client options
13+
## Client Options
1414

1515
You can add token client definitions to your host while configuring the ASP.NET Core service provider, e.g.:
1616

17-
```cs
17+
```csharp
18+
// Program.cs
1819
services.AddClientCredentialsTokenManagement()
1920
.AddClient("invoices", client =>
2021
{
@@ -40,7 +41,8 @@ You can set the following options:
4041

4142
Internally the standard .NET options system is used to register the configuration. This means you can also register clients like this:
4243

43-
```cs
44+
```csharp
45+
// Program.cs
4446
services.Configure<ClientCredentialsClient>("invoices", client =>
4547
{
4648
client.TokenEndpoint = "https://sts.company.com/connect/token";
@@ -55,45 +57,51 @@ services.Configure<ClientCredentialsClient>("invoices", client =>
5557

5658
Or use the `IConfigureNamedOptions` if you need access to the ASP.NET Core service provider during registration, e.g.:
5759

58-
```cs
59-
public class ClientCredentialsClientConfigureOptions : IConfigureNamedOptions<ClientCredentialsClient>
60-
{
61-
private readonly DiscoveryCache _cache;
60+
```csharp
61+
// ClientCredentialsClientConfigureOptions.cs
62+
using Duende.AccessTokenManagement;
63+
using Duende.IdentityModel.Client;
64+
using Microsoft.Extensions.Options;
6265

63-
public ClientCredentialsClientConfigureOptions(DiscoveryCache cache)
64-
{
65-
_cache = cache;
66-
}
67-
68-
public void Configure(string name, ClientCredentialsClient options)
66+
public class ClientCredentialsClientConfigureOptions(DiscoveryCache cache)
67+
: IConfigureNamedOptions<ClientCredentialsClient>
68+
{
69+
public void Configure(string? name, ClientCredentialsClient options)
6970
{
7071
if (name == "invoices")
7172
{
72-
var disco = _cache.GetAsync().GetAwaiter().GetResult();
73+
var disco = cache.GetAsync().GetAwaiter().GetResult();
7374

7475
options.TokenEndpoint = disco.TokenEndpoint;
7576

76-
client.ClientId = "4a632e2e-0466-4e5a-a094-0455c6105f57";
77-
client.ClientSecret = "e8ae294a-d5f3-4907-88fa-c83b3546b70c";
77+
options.ClientId = "4a632e2e-0466-4e5a-a094-0455c6105f57";
78+
options.ClientSecret = "e8ae294a-d5f3-4907-88fa-c83b3546b70c";
7879

79-
client.Scope = "list";
80-
client.Resource = "urn:invoices";
80+
options.Scope = "list";
81+
options.Resource = "urn:invoices";
8182
}
8283
}
84+
85+
public void Configure(ClientCredentialsClient options)
86+
{
87+
// implement default configure
88+
Configure("", options);
89+
}
8390
}
8491
```
8592

8693
You will also need to register the config options, for example:
8794

88-
```cs
95+
```csharp
96+
// Program.cs
8997
services.AddClientCredentialsTokenManagement();
9098

9199
services.AddSingleton(new DiscoveryCache("https://sts.company.com"));
92100
services.AddSingleton<IConfigureOptions<ClientCredentialsClient>,
93101
ClientCredentialsClientConfigureOptions>();
94102
```
95103

96-
### Backchannel communication
104+
### Backchannel Communication
97105

98106
By default, all backchannel communication will be done using a named client from the HTTP client factory. The name is `Duende.AccessTokenManagement.BackChannelHttpClient` which is also a constant called `ClientCredentialsTokenManagementDefaults.BackChannelHttpClientName`.
99107

@@ -111,6 +119,7 @@ By default, tokens will be cached using the `IDistributedCache` abstraction in A
111119
For development purposes, you can use the `MemoryDistributedCache`:
112120

113121
```cs
122+
// Program.cs
114123
services.AddDistributedMemoryCache();
115124
```
116125

@@ -122,6 +131,7 @@ For production deployments, we recommend using a [distributed cache](https://lea
122131
The built-in cache in `Duende.AccessTokenManagment` uses two settings from the options, which apply with any `IDistributedCache`:
123132

124133
```cs
134+
// Program.cs
125135
services.AddClientCredentialsTokenManagement(options =>
126136
{
127137
options.CacheLifetimeBuffer = 60;

src/content/docs/accesstokenmanagement/advanced/dpop.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
---
2-
title: DPoP
3-
description: DPoP (Demonstrating Proof-of-Possession) is a security mechanism that binds access tokens to specific cryptographic keys to prevent token theft and misuse.
2+
title: Demonstrating Proof-of-Possession (DPoP)
3+
description: Demonstrating Proof-of-Possession is a security mechanism that binds access tokens to specific cryptographic keys to prevent token theft and misuse.
44
sidebar:
5+
label: DPoP
56
order: 40
67
redirect_from:
78
- /foss/accesstokenmanagement/advanced/dpop/
@@ -19,11 +20,18 @@ The creation and management of this DPoP key is up to the policy of the client.
1920

2021
Creating a JWK in .NET is simple:
2122

22-
```cs
23+
```csharp
24+
// Program.cs
25+
using System.Security.Cryptography;
26+
using System.Text.Json;
27+
using Microsoft.IdentityModel.Tokens;
28+
2329
var rsaKey = new RsaSecurityKey(RSA.Create(2048));
2430
var jwkKey = JsonWebKeyConverter.ConvertFromSecurityKey(rsaKey);
2531
jwkKey.Alg = "PS256";
2632
var jwk = JsonSerializer.Serialize(jwkKey);
33+
34+
Console.WriteLine(jwk);
2735
```
2836

2937
## Key Configuration
@@ -36,6 +44,7 @@ Once you have a JWK you wish to use, then it must be configured or made availabl
3644
Here's a sample configuring the key in an application using `AddOpenIdConnectAccessTokenManagement` in the startup code:
3745

3846
```cs
47+
// Program.cs
3948
services.AddOpenIdConnectAccessTokenManagement(options =>
4049
{
4150
options.DPoPJsonWebKey = jwk;
@@ -45,6 +54,7 @@ services.AddOpenIdConnectAccessTokenManagement(options =>
4554
Similarly, for an application using `AddClientCredentialsTokenManagement`, it would look like this:
4655

4756
```cs
57+
// Program.cs
4858
services.AddClientCredentialsTokenManagement()
4959
.AddClient("client_name", options =>
5060
{
@@ -61,7 +71,7 @@ There is nothing explicit needed on behalf of the developer using this library.
6171

6272
When using DPoP and `AddOpenIdConnectAccessTokenManagement`, this library will also automatically include the `dpop_jkt` parameter to the authorize endpoint.
6373

64-
## Proof Tokens at the API
74+
## Proof Tokens At The API
6575

6676
Once the library has obtained a DPoP bound access token for the client, then if your application is using any of the `HttpClient` client factory helpers (e.g. `AddClientCredentialsHttpClient` or `AddUserAccessTokenHttpClient`) then those outbound HTTP requests will automatically include a DPoP proof token for the associated DPoP access token.
6777

src/content/docs/accesstokenmanagement/advanced/user-tokens.md

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,28 @@ redirect_from:
88
- /foss/accesstokenmanagement/advanced/user_tokens/
99
---
1010

11-
The most common way to use the access token management for interactive web applications is described [here](/accesstokenmanagement/web-apps/) - however you may want to customise certain aspects of it - here's what you can do.
11+
The most common way
12+
to use [access token management is for interactive web applications](/accesstokenmanagement/web-apps.md) -
13+
however, you may want to customize certain aspects of it. Here's what you can do.
1214

13-
## General options
15+
## General Options
1416

1517
You can pass in some global options when registering token management in the ASP.NET Core service provider.
1618

17-
* `ChallengeScheme` - by default the OIDC configuration is inferred from the default challenge scheme. This is recommended approach. If for some reason your OIDC handler is not the default challenge scheme, you can set the scheme name on the options
18-
* `UseChallengeSchemeScopedTokens` - the general assumption is that you only have one OIDC handler configured. If that is not the case, token management needs to maintain multiple sets of token artefacts simultaneously. You can opt in to that feature using this setting.
19-
* `ClientCredentialsScope` - when requesting client credentials tokens from the OIDC provider, the scope parameter will not be set since its value cannot be inferred from the OIDC configuration. With this setting you can set the value of the scope parameter.
19+
* `ChallengeScheme` - by default the OIDC configuration is inferred from the default challenge scheme. This is
20+
recommended approach. If for some reason your OIDC handler is not the default challenge scheme, you can set the scheme
21+
name on the options
22+
* `UseChallengeSchemeScopedTokens` - the general assumption is that you only have one OIDC handler configured. If that
23+
is not the case, token management needs to maintain multiple sets of token artefacts simultaneously. You can opt in to
24+
that feature using this setting.
25+
* `ClientCredentialsScope` - when requesting client credentials tokens from the OIDC provider, the scope parameter will
26+
not be set since its value cannot be inferred from the OIDC configuration. With this setting you can set the value of
27+
the scope parameter.
2028
* `ClientCredentialsResource` - same as previous, but for the resource parameter
2129
* `ClientCredentialStyle` - specifies how client credentials are transmitted to the OIDC provider
2230

23-
```cs
31+
```csharp
32+
// Program.cs
2433
builder.Services.AddOpenIdConnectAccessTokenManagement(options =>
2534
{
2635
options.ChallengeScheme = "schmeName";
@@ -34,7 +43,7 @@ builder.Services.AddOpenIdConnectAccessTokenManagement(options =>
3443

3544
## Per Request Parameters
3645

37-
You can also modify token management parameters on a per-request basis.
46+
You can also modify token management parameters on a per-request basis.
3847

3948
The `UserTokenRequestParameters` class can be used for that:
4049

@@ -47,20 +56,21 @@ The `UserTokenRequestParameters` class can be used for that:
4756

4857
The request parameters can be passed via the manual API:
4958

50-
```cs
59+
```csharp
5160
var token = await _tokenManagementService.GetAccessTokenAsync(User, new UserAccessTokenRequestParameters { ... });
5261
```
5362

5463
...the extension methods
5564

56-
```cs
65+
```csharp
5766
var token = await HttpContext.GetUserAccessTokenAsync(
5867
new UserTokenRequestParameters { ... });
5968
```
6069

6170
...or the HTTP client factory
6271

63-
```cs
72+
```csharp
73+
// Program.cs
6474
// registers HTTP client that uses the managed user access token
6575
builder.Services.AddUserAccessTokenHttpClient("invoices",
6676
parameters: new UserTokenRequestParameters { ... },
@@ -77,9 +87,10 @@ builder.Services.AddHttpClient<InvoiceClient>(client =>
7787
.AddUserAccessTokenHandler(new UserTokenRequestParameters { ... });
7888
```
7989

80-
## Token storage
90+
## Token Storage
8191

82-
By default, the user's access and refresh token will be store in the ASP.NET Core authentication session (implemented by the cookie handler).
92+
By default, the user's access and refresh token will be store in the ASP.NET Core authentication session (implemented by
93+
the cookie handler).
8394

8495
You can modify this in two ways
8596

0 commit comments

Comments
 (0)