Skip to content

Commit c31d726

Browse files
authored
Merge pull request #233102 from jmprieur/jmprieur/daemon-v2
Daemon using idweb. App config
2 parents b73b2ab + 13424eb commit c31d726

File tree

3 files changed

+313
-115
lines changed

3 files changed

+313
-115
lines changed

articles/active-directory/develop/scenario-daemon-acquire-token.md

Lines changed: 76 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,23 @@ After you've constructed a confidential client application, you can acquire a to
2222

2323
The scope to request for a client credential flow is the name of the resource followed by `/.default`. This notation tells Azure Active Directory (Azure AD) to use the *application-level permissions* declared statically during application registration. Also, these API permissions must be granted by a tenant administrator.
2424

25-
# [.NET](#tab/dotnet)
25+
# [.NET](#tab/idweb)
2626

27-
```csharp
28-
ResourceId = "someAppIDURI";
29-
var scopes = new [] { ResourceId+"/.default"};
27+
Here's an example of defining the scopes for the web API as part of the configuration in an [*appsettings.json*](https://github.com/Azure-Samples/active-directory-dotnetcore-daemon-v2/blob/master/2-Call-OwnApi/daemon-console/appsettings.json) file. This example is taken from the [.NET Core console daemon](https://github.com/Azure-Samples/active-directory-dotnetcore-daemon-v2) code sample on GitHub.
28+
29+
```json
30+
{
31+
"AzureAd": {
32+
// Same AzureAd section as before.
33+
},
34+
35+
"MyWebApi": {
36+
"BaseUrl": "https://localhost:44372/",
37+
"RelativePath": "api/TodoList",
38+
"RequestAppToken": true,
39+
"Scopes": [ "[Enter here the scopes for your web API]" ]
40+
}
41+
}
3042
```
3143

3244
# [Java](#tab/java)
@@ -53,6 +65,13 @@ In MSAL Python, the configuration file looks like this code snippet:
5365
}
5466
```
5567

68+
# [.NET (low level)](#tab/dotnet)
69+
70+
```csharp
71+
ResourceId = "someAppIDURI";
72+
var scopes = new [] { ResourceId+"/.default"};
73+
```
74+
5675
---
5776

5877
### Azure AD (v1.0) resources
@@ -65,42 +84,25 @@ The scope used for client credentials should always be the resource ID followed
6584
6685
## AcquireTokenForClient API
6786

68-
To acquire a token for the app, you'll use `AcquireTokenForClient` or its equivalent, depending on the platform.
87+
To acquire a token for the app, use `AcquireTokenForClient` or its equivalent, depending on the platform.
6988

70-
# [.NET](#tab/dotnet)
89+
# [.NET](#tab/idweb)
90+
91+
With Microsoft.Identity.Web, you don't need to acquire a token. You can use higher level APIs, as you see in [Calling a web API from a daemon application](scenario-daemon-call-api.md). If however you're using an SDK that requires a token, the following code snippet shows how to get this token.
7192

7293
```csharp
73-
using Microsoft.Identity.Client;
94+
using Microsoft.Extensions.DependencyInjection;
95+
using Microsoft.Identity.Abstractions;
96+
using Microsoft.Identity.Web;
7497

75-
// With client credentials flows, the scope is always of the shape "resource/.default" because the
76-
// application permissions need to be set statically (in the portal or by PowerShell), and then granted by
77-
// a tenant administrator.
78-
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
98+
// In the Program.cs, acquire a token for your downstream API
7999
80-
AuthenticationResult result = null;
81-
try
82-
{
83-
result = await app.AcquireTokenForClient(scopes)
84-
.ExecuteAsync();
85-
}
86-
catch (MsalUiRequiredException ex)
87-
{
88-
// The application doesn't have sufficient permissions.
89-
// - Did you declare enough app permissions during app creation?
90-
// - Did the tenant admin grant permissions to the application?
91-
}
92-
catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011"))
93-
{
94-
// Invalid scope. The scope has to be in the form "https://resourceurl/.default"
95-
// Mitigation: Change the scope to be as expected.
96-
}
100+
var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
101+
ITokenAcquirer acquirer = tokenAcquirerFactory.GetTokenAcquirer();
102+
AcquireTokenResult tokenResult = await acquirer.GetTokenForUserAsync(new[] { https://graph.microsoft.com/.default" });
103+
string accessToken = tokenResult.AccessToken;
97104
```
98105

99-
### AcquireTokenForClient uses the application token cache
100-
101-
In MSAL.NET, `AcquireTokenForClient` uses the application token cache. (All the other AcquireToken*XX* methods use the user token cache.)
102-
Don't call `AcquireTokenSilent` before you call `AcquireTokenForClient`, because `AcquireTokenSilent` uses the *user* token cache. `AcquireTokenForClient` checks the *application* token cache itself and updates it.
103-
104106
# [Java](#tab/java)
105107

106108
This code is extracted from the [MSAL Java dev samples](https://github.com/AzureAD/microsoft-authentication-library-for-java/tree/dev/msal4j-sdk/src/samples/confidential-client/).
@@ -152,7 +154,7 @@ private static IAuthenticationResult acquireToken() throws Exception {
152154

153155
# [Node.js](#tab/nodejs)
154156

155-
The code snippet below illustrates token acquisition in an MSAL Node confidential client application:
157+
The following code snippet illustrates token acquisition in an MSAL Node confidential client application:
156158

157159
```JavaScript
158160
try {
@@ -187,6 +189,40 @@ else:
187189
print(result.get("correlation_id")) # You might need this when reporting a bug.
188190
```
189191

192+
# [.NET (low level)](#tab/dotnet)
193+
194+
```csharp
195+
using Microsoft.Identity.Client;
196+
197+
// With client credentials flows, the scope is always of the shape "resource/.default" because the
198+
// application permissions need to be set statically (in the portal or by PowerShell), and then granted by
199+
// a tenant administrator.
200+
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
201+
202+
AuthenticationResult result = null;
203+
try
204+
{
205+
result = await app.AcquireTokenForClient(scopes)
206+
.ExecuteAsync();
207+
}
208+
catch (MsalUiRequiredException ex)
209+
{
210+
// The application doesn't have sufficient permissions.
211+
// - Did you declare enough app permissions during app creation?
212+
// - Did the tenant admin grant permissions to the application?
213+
}
214+
catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011"))
215+
{
216+
// Invalid scope. The scope has to be in the form "https://resourceurl/.default"
217+
// Mitigation: Change the scope to be as expected.
218+
}
219+
```
220+
221+
### AcquireTokenForClient uses the application token cache
222+
223+
In MSAL.NET, `AcquireTokenForClient` uses the application token cache. (All the other AcquireToken*XX* methods use the user token cache.)
224+
Don't call `AcquireTokenSilent` before you call `AcquireTokenForClient`, because `AcquireTokenSilent` uses the *user* token cache. `AcquireTokenForClient` checks the *application* token cache itself and updates it.
225+
190226
---
191227

192228
### Protocol
@@ -253,10 +289,10 @@ If your daemon app calls your own web API and you weren't able to add an app per
253289

254290
## Next steps
255291

256-
# [.NET](#tab/dotnet)
292+
# [.NET](#tab/idweb)
257293

258294
Move on to the next article in this scenario,
259-
[Calling a web API](./scenario-daemon-call-api.md?tabs=dotnet).
295+
[Calling a web API](./scenario-daemon-call-api.md?tabs=idweb).
260296

261297
# [Java](#tab/java)
262298

@@ -273,4 +309,8 @@ Move on to the next article in this scenario,
273309
Move on to the next article in this scenario,
274310
[Calling a web API](./scenario-daemon-call-api.md?tabs=python).
275311

312+
# [.NET low level](#tab/dotnet)
313+
314+
Move on to the next article in this scenario,
315+
[Calling a web API](./scenario-daemon-call-api.md?tabs=dotnet).
276316
---

0 commit comments

Comments
 (0)