You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 4-WebApp-your-API/4-3-AnyOrg/Readme.md
+71-71Lines changed: 71 additions & 71 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -34,30 +34,33 @@ This sample demonstrates how to develop a multi-tenant ASP.NET Core MVC web appl
34
34
-[Step 1: Clone or download this repository](#step-1-clone-or-download-this-repository)
35
35
-[Step 2: Register the sample application with your Azure Active Directory tenant](#step-2-register-the-sample-application-with-your-azure-active-directory-tenant)
36
36
-[Step 3: Run the sample](#step-3-run-the-sample)
37
+
-[Testing the Application](#testing-the-application)
37
38
-[About the code](#about-the-code)
38
39
-[Community Help and Support](#community-help-and-support)
39
40
-[Contributing](#contributing)
40
41
-[More information](#more-information)
41
42
42
43
### Scenario
43
44
44
-
In this scenario, you protect a Web API using the Microsoft Identity Platform so that only authenticated users can access it. The API will support authenticated users with Work and School accounts. Further on the API will also call a downstream API (Microsoft Graph) on-behalf of the signed-in user to provide additional value to its client apps.
45
+
In this sample, we would protect an ASP.Net Core Web API using the Microsoft Identity Platform. The Web API will be protected using Azure Active Directory OAuth Bearer Authorization. The API will support authenticated users with Work and School accounts. Further on the API will also call a downstream API (Microsoft Graph) on-behalf of the signed-in user to provide additional value to its client apps.
45
46
46
47
### Overview
47
48
48
49
This sample presents a Web application that signs-in users and obtains an Access Token for protected Web API.
49
50
51
+
Both applications use the Microsoft Authentication Library [MSAL.NET](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet) to sign-in user and obtain a JWT access token through the [OAuth 2.0](https://docs.microsoft.com/azure/active-directory/develop/active-directory-protocols-oauth-code) protocol.
52
+
50
53
The Web App:
51
54
52
-
1.TodoListClient uses [MSAL.NET](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet) and [Microsoft.Identity.Web](https://github.com/AzureAD/microsoft-identity-web) to authenticate a user.
53
-
2. Acquires an access token for the Web API.
54
-
3. Calls the ASP.NET Core Web API by using the access token as a bearer token in the authentication header of the Http request.
55
+
1.Signs-in users using the MSAL.NET library.
56
+
1. Acquires an access token for the Web API.
57
+
1. Calls the ASP.NET Core Web API by using the access token as a bearer token in the authentication header of the Http request.
55
58
56
59
The Web API:
57
60
58
-
1.TodoListService uses [MSAL.NET](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet) and [Microsoft.Identity.Web](https://github.com/AzureAD/microsoft-identity-web) to protect its endpoint and accept authorized calls.
59
-
2. Acquires another access token on-behalf-of the signed-in user using the [on-behalf of flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow).
60
-
3. The Web API then uses this new Access token to call Microsoft Graph
61
+
1.Authorizes the caller (user) using the ASP.NET JWT Bearer Authorization middleware.
62
+
1. Acquires another access token on-behalf-of the signed-in user using the [on-behalf of flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow).
63
+
1. The Web API then uses this new Access token to call Microsoft Graph.
61
64
62
65

63
66
@@ -224,7 +227,20 @@ Open the project in your IDE (like Visual Studio) to configure the code.
224
227
1. Find the app key `AdminConsentRedirectApi` and replace the existing value with the Redirect URI for WebApi-MultiTenant-v2 app. For example, `https://localhost:44351/api/Home` .
225
228
### Step 3: Run the sample
226
229
227
-
#### Using a command line interface such as VS Code integrated terminal, follow the steps below:
230
+
You can run the sample by using either Visual Studio or command line interface as shown below:
231
+
232
+
#### Run the sample using Visual Studio
233
+
234
+
Clean the solution, rebuild the solution, and run it. You might want to go into the solution properties and set both projects as startup projects, with the service project starting first.
235
+
236
+
When you start the Web API from Visual Studio, depending on the browser you use, you'll get:
237
+
238
+
- an empty web page (with Microsoft Edge)
239
+
- or an error HTTP 401 (with Chrome)
240
+
241
+
This behavior is expected as the browser is not authenticated. The Web application will be authenticated, so it will be able to access the Web API.
242
+
243
+
#### Run the sample using a command line interface such as VS Code integrated terminal
228
244
229
245
##### Step 1. Install .NET Core dependencies
230
246
@@ -252,36 +268,70 @@ Learn more about [HTTPS in .NET Core](https://docs.microsoft.com/aspnet/core/sec
252
268
253
269
##### Step 3. Run the applications
254
270
255
-
In both the windows execute the below command:
271
+
In both the console windows execute the below command:
256
272
257
273
```console
258
274
dotnet run
259
275
```
260
276
Open your browser and navigate to `https://localhost:44321`.
261
277
262
-
#### Run the sample using Visual Studio:
278
+
> NOTE: Remember, the To-Do list is stored in memory in this `TodoListService` app. Each time you run the projects, your To-Do list will get emptied.
263
279
264
-
Clean the solution, rebuild the solution, and run it. You might want to go into the solution properties and set both projects as startup projects, with the service project starting first.
280
+
### Testing the Application
265
281
266
-
When you start the Web API from Visual Studio, depending on the browser you use, you'll get:
282
+
To properly test this application, you need *at least***2** tenants, and on each tenant, *at least***1** administrator and **1** non-administrator account.
267
283
268
-
- an empty web page (case with Microsoft Edge)
269
-
- or an error HTTP 401 (case with Chrome)
284
+
Before each test, you should delete your **service principal** for the tenant you are about to test, in order to remove any previously given consents and start the **provisioning process** from scratch.
270
285
271
-
This behavior is expected as you are not authenticated. The client application will be authenticated, so it will be able to access the Web API.
286
+
> #### How to delete Service Principals
287
+
>
288
+
> Steps for deleting a service principal differs with respect to whether the principal is in the **home tenant** of the application or in another tenant. If it is in the **home tenant**, you will find the entry for the application under the **App Registrations** blade. If it is another tenant, you will find the entry under the **Enterprise Applications** blade. Read more about these blades in the [How and why applications are added to Azure AD](https://docs.microsoft.com/azure/active-directory/develop/active-directory-how-applications-are-added).The screenshot below shows how to access the service principal from a **home tenant**:
289
+
>
290
+
> 
291
+
>
292
+
> The rest of the process is the same for both cases. In the next screen, click on **Properties** and then the **Delete** button on the upper side.
> You have now deleted the service principal of Web App for that tenant. Similarly, you can delete the service principal for Web API. Next time, admin needs to provision service principal for both the applications in the tenant from which *that* admin belongs.
272
297
273
-
##Explore the sample
298
+
#### Ways of providing admin consent
274
299
275
-
Explore the sample by signing in into the TodoList client, adding items to the To Do list and assigning them to users. If you stop the application without signing out, the next time you run the application, you won't be prompted to sign in again.
300
+
A service principal of your multi-tenant app is created manually or programmatically by a tenant admin using one of the following
301
+
1. Using the [/adminconsent endpoint](https://docs.microsoft.com/azure/active-directory/develop/v2-admin-consent)
302
+
2.[Using the PowerShell command](https://docs.microsoft.com/powershell/azure/create-azure-service-principal-azureps).
276
303
277
-
For Home Tenant, admin needs to sign-in first as `User.Read.All` permission requires admin consent for the organization.
304
+
-**Consent using the `/adminconsent` endpoint**
278
305
279
-
For guest tenant, you need to provision service principal for that tenant. It can be done by clicking on `Admin Consent` link that is present on home page of Web App. The link provides consent screen that is used to create service principal by admin of the guest tenant.
306
+
You can try the /adminconsent endpoint on the home page of the sample by clicking on the `Consent as Admin` link. Web API is provisioned first because the Web Appis dependent on the Web API.
280
307
281
-
> NOTE: Remember, the To-Do list is stored in memory in this `TodoListService` app. Each time you run the projects, your To-Do list will get emptied.
> Did you notice the scope here is set to `.default`, as opposed to `User.Read.All` for Microsoft Graph and `access_as_user` for Web API? This is a built-in scope for every application that refers to the static list of permissions configured on the application registration. Basically, it *bundles* all the permissions in one scope. The /.default scope can be used in any OAuth 2.0 flow, but is necessary when using the v2 admin consent endpoint to request application permissions. Read about `scopes` usage at [Scopes and permissions in the Microsoft Identity Platform](https://docs.microsoft.com/azure/active-directory/develop/v2-permissions-and-consent#scopes-and-permissions).
313
+
314
+
When redirected to the `/adminconsent` endpoint, the tenant admin will see:
315
+
316
+

317
+
318
+
After you choose an admin account, it will lead to the following prompt for Web API consent screen:
319
+
320
+

321
+
322
+
When you click `Accept`, it will redirects to `/adminconsent` endpoint for Web App:
323
+
324
+

325
+
326
+
After you choose an admin account, it will lead to the Web App consent as below:
327
+
328
+

329
+
330
+
Once it finishes, your applications service principal will be provisioned in that tenant.
282
331
283
332
> Did the sample not work for you as expected? Did you encounter issues trying this sample? Then please reach out to us using the [GitHub Issues](../../../../issues) page.
284
333
334
+
285
335
## About the code
286
336
287
337
### Provisioning your Multi-tenant Apps in another Azure AD Tenant
>Stepsfordeletingaserviceprincipaldifferswithrespecttowhethertheprincipalisinthe **hometenant** oftheapplicationorinanothertenant. Ifitisinthe **hometenant**, youwillfindtheentryfortheapplicationunderthe**AppRegistrations**blade. Ifitisanothertenant, youwillfindtheentryunderthe**EnterpriseApplications**blade. Readmoreaboutthesebladesinthe [HowandwhyapplicationsareaddedtoAzureAD](https://docs.microsoft.com/azure/active-directory/develop/active-directory-how-applications-are-added).The screenshot below shows how to access the service principal from a **home tenant**:
>Didyounoticethescopehereissetto `.default`, asopposedto `User.Read.All` forMicrosoftGraphand `access_as_user` forWebAPI?Thisisabuilt-inscopeforeveryapplicationthatreferstothestaticlistofpermissionsconfiguredontheapplicationregistration. Basically, it*bundles*allthepermissionsinonescope. The/.defaultscopecanbeusedinanyOAuth2.0flow, butisnecessary when using the v2 admin consent endpoint to request application permissions. Read about `scopes` usage at [Scopes and permissions in the Microsoft Identity Platform](https://docs.microsoft.com/azure/active-directory/develop/v2-permissions-and-consent#scopes-and-permissions).
0 commit comments