Skip to content

Commit a20b104

Browse files
updated webapps
1 parent 782620e commit a20b104

File tree

2 files changed

+107
-77
lines changed

2 files changed

+107
-77
lines changed

src/content/docs/accesstokenmanagement/web-apps.md

Lines changed: 86 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,16 @@ While many of the details can be customized, by default the following is assumed
2020
token service
2121
* the token service returns a refresh token
2222

23+
Using this library, you can either request `user access tokens` or `client credentials tokens`. User access tokens typically contain information about the currently logged in user, such as the `sub` claim. They are used to access services under the credentials of the currently logged in user. `Client credentials tokens` do not contain information about the currently logged in user and are typically used to do machine-to-machine calls.
24+
2325
## Usage
2426
First, you'll need to add `Duende.AccessTokenManagement.OpenIdConnect` to your solution.
2527

26-
Then, there are two fundamental ways to interact with token management:
28+
Then, there are two fundamental ways to interact with token management:
2729
1. **Automatic** <Badge text="recommended"/>: You request a http client from the IHTTPClientFactory. This http client automatically requests, optionally renews and attaches the access tokens on each request.
2830
2. **Manually** <Badge text="advanced"/>: You request an access token, which you can then use to (for example) authenticate with services. You are responsible for attaching the access token to requests.
2931

30-
31-
## Adding Duende.AccessTokenManagement.OpenIdConnect
32+
### Adding AccessTokenManagement to your project
3233

3334

3435
To use this library, start by adding the library to your .NET projects.
@@ -145,46 +146,103 @@ builder.Services.AddHttpClient<MasterDataClient>(client =>
145146
.AddClientAccessTokenHandler();
146147
```
147148

148-
## Usage
149149

150-
There are three ways to interact with the token management service:
150+
Last but not least, if you registered clients with the factory, you can use them. They will try to make sure that a
151+
current access token is always sent along. If that is not possible, ultimately a 401 will be returned to the calling
152+
code.
151153

152-
* Manually
153-
* HTTP context extension methods
154-
* HTTP client factory
154+
```csharp
155+
public async Task<IActionResult> CallApi()
156+
{
157+
var client = _httpClientFactory.CreateClient("invoices");
155158

156-
### Manually
159+
var response = await client.GetAsync("list");
160+
161+
// rest omitted
162+
}
163+
```
157164

158-
You can get the current user and client access token manually by writing code against the `IUserTokenManagementService`.
165+
...or for a typed client:
159166

160167
```csharp
161-
public class HomeController : Controller
168+
public async Task<IActionResult> CallApi([FromServices] InvoiceClient client)
162169
{
163-
private readonly IHttpClientFactory _httpClientFactory;
164-
private readonly IUserTokenManagementService _tokenManagementService;
170+
var response = await client.GetList();
171+
172+
// rest omitted
173+
}
174+
```
165175

166-
public HomeController(IHttpClientFactory httpClientFactory, IUserTokenManagementService tokenManagementService)
167-
{
168-
_httpClientFactory = httpClientFactory;
169-
_tokenManagementService = tokenManagementService;
170-
}
176+
### Manually request access tokens
177+
178+
If you want to use access tokens in a different way or have more advanced needs which the automatic option doesn't cover, then you can also manually request user access tokens.
179+
180+
{/* prettier-ignore */}
181+
<Tabs syncKey="atm-workers">
182+
{/* prettier-ignore */}
183+
<TabItem label="V4">
171184

172-
public async Task<IActionResult> CallApi()
185+
You can get the current user access token manually by writing code against the `IUserTokenManager`.
186+
187+
```csharp
188+
public class HomeController : Controller
173189
{
174-
var token = await _tokenManagementService.GetAccessTokenAsync(User);
175-
var client = _httpClientFactory.CreateClient();
176-
client.SetBearerToken(token.Value);
190+
private readonly IHttpClientFactory _httpClientFactory;
191+
private readonly IUserTokenManager _userTokenManager;
192+
193+
public HomeController(IHttpClientFactory httpClientFactory, IUserTokenManager userTokenManager)
194+
{
195+
_httpClientFactory = httpClientFactory;
196+
_userTokenManager = userTokenManager;
197+
}
198+
199+
public async Task<IActionResult> CallApi(CancellationToken ct)
200+
{
201+
var token = await _userTokenManager.GetAccessTokenAsync(User, ct: ct);
202+
var client = _httpClientFactory.CreateClient();
203+
client.SetBearerToken(token.Value);
204+
205+
var response = await client.GetAsync("https://api.company.com/invoices", ct);
177206
178-
var response = await client.GetAsync("https://api.company.com/invoices");
179-
180-
// rest omitted
207+
// rest omitted
208+
}
181209
}
182-
}
183-
```
210+
```
211+
212+
</TabItem>
213+
<TabItem label="V3">
214+
You can get the current user access token manually by writing code against the `IUserTokenManagementService`.
215+
216+
```csharp
217+
public class HomeController : Controller
218+
{
219+
private readonly IHttpClientFactory _httpClientFactory;
220+
private readonly IUserTokenManagementService _tokenManagementService;
221+
222+
public HomeController(IHttpClientFactory httpClientFactory, IUserTokenManagementService tokenManagementService)
223+
{
224+
_httpClientFactory = httpClientFactory;
225+
_tokenManagementService = tokenManagementService;
226+
}
227+
228+
public async Task<IActionResult> CallApi()
229+
{
230+
var token = await _tokenManagementService.GetAccessTokenAsync(User);
231+
var client = _httpClientFactory.CreateClient();
232+
client.SetBearerToken(token.Value);
233+
234+
var response = await client.GetAsync("https://api.company.com/invoices");
235+
236+
// rest omitted
237+
}
238+
}
239+
</TabItem>
240+
</Tabs>
241+
184242

185243
### HTTP Context Extension Methods
186244

187-
There are three extension methods on the HTTP context that simplify interaction with the token management service:
245+
Alternatively, you can also manually request access tokens via these extension methods on the `HttpContext`:
188246

189247
* `GetUserAccessTokenAsync` - returns an access token representing the user. If the current access token is expired, it
190248
will be refreshed.
@@ -204,31 +262,3 @@ public async Task<IActionResult> CallApi()
204262
// rest omitted
205263
}
206264
```
207-
208-
### HTTP Client Factory
209-
210-
Last but not least, if you registered clients with the factory, you can use them. They will try to make sure that a
211-
current access token is always sent along. If that is not possible, ultimately a 401 will be returned to the calling
212-
code.
213-
214-
```csharp
215-
public async Task<IActionResult> CallApi()
216-
{
217-
var client = _httpClientFactory.CreateClient("invoices");
218-
219-
var response = await client.GetAsync("list");
220-
221-
// rest omitted
222-
}
223-
```
224-
225-
...or for a typed client:
226-
227-
```csharp
228-
public async Task<IActionResult> CallApi([FromServices] InvoiceClient client)
229-
{
230-
var response = await client.GetList();
231-
232-
// rest omitted
233-
}
234-
```

src/content/docs/accesstokenmanagement/workers.mdx

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -159,39 +159,39 @@ The following code registers an `HttpClient` called `invoices` which automatical
159159
</Tabs>
160160

161161

162-
Once you have set up HTTP clients in the HTTP factory, then no token related code is needed at all, e.g.:
162+
Once you have set up HTTP clients in the HTTP factory, then no token related code is needed at all, e.g.:
163163

164-
```csharp
165-
// WorkerHttpClient.cs
166-
public class WorkerHttpClient : BackgroundService
167-
{
168-
private readonly ILogger<WorkerHttpClient> _logger;
169-
private readonly IHttpClientFactory _clientFactory;
164+
```csharp
165+
// WorkerHttpClient.cs
166+
public class WorkerHttpClient : BackgroundService
167+
{
168+
private readonly ILogger<WorkerHttpClient> _logger;
169+
private readonly IHttpClientFactory _clientFactory;
170170

171-
public WorkerHttpClient(ILogger<WorkerHttpClient> logger, IHttpClientFactory factory)
172-
{
173-
_logger = logger;
174-
_clientFactory = factory;
175-
}
171+
public WorkerHttpClient(ILogger<WorkerHttpClient> logger, IHttpClientFactory factory)
172+
{
173+
_logger = logger;
174+
_clientFactory = factory;
175+
}
176176

177-
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
177+
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
178+
{
179+
while (!stoppingToken.IsCancellationRequested)
178180
{
179-
while (!stoppingToken.IsCancellationRequested)
180-
{
181-
var client = _clientFactory.CreateClient("invoices");
182-
var response = await client.GetAsync("test", stoppingToken);
181+
var client = _clientFactory.CreateClient("invoices");
182+
var response = await client.GetAsync("test", stoppingToken);
183183

184-
// rest omitted
185-
}
184+
// rest omitted
186185
}
187186
}
188-
```
187+
}
188+
```
189189

190190
:::note
191191
The clients in the HTTP client factory have a message handler attached to them that automatically retries the request in case of a `401` response code. The request get resent with a newly requested access token. If this still results in a `401`, the response is returned to the caller.
192192
:::
193193

194-
### Manual
194+
### Manually request access tokens
195195

196196
If you want to use access tokens in a different way or have more advanced needs which the automatic option doesn't cover, then you can also manually request access tokens.
197197

0 commit comments

Comments
 (0)