|
| 1 | +--- |
| 2 | +title: "Quickstart: ASP.NET Core web app that signs in users and calls Microsoft Graph | Azure" |
| 3 | +titleSuffix: Microsoft identity platform |
| 4 | +description: In this quickstart, you learn how an app leverages Microsoft.Identity.Web to implement Microsoft sign-in in an ASP.NET Core web app using OpenID Connect and calls Microsoft Graph |
| 5 | +services: active-directory |
| 6 | +author: jmprieur |
| 7 | +manager: CelesteDG |
| 8 | + |
| 9 | +ms.service: active-directory |
| 10 | +ms.subservice: develop |
| 11 | +ms.topic: quickstart |
| 12 | +ms.workload: identity |
| 13 | +ms.date: 11/22/2021 |
| 14 | +ms.author: jmprieur |
| 15 | +ms.custom: "devx-track-csharp, aaddev, identityplatformtop40, scenarios:getting-started, languages:aspnet-core" |
| 16 | +#Customer intent: As an application developer, I want to know how to write an ASP.NET Core web app that can sign in personal Microsoft accounts and work/school accounts from any Azure Active Directory instance, then access their data in Microsoft Graph on their behalf. |
| 17 | +--- |
| 18 | + |
| 19 | +In this quickstart, you download and run a code sample that demonstrates how an ASP.NET Core web app can sign in users from any Azure Active Directory (Azure AD) organization. |
| 20 | + |
| 21 | +The following diagram shows how the sample app works: |
| 22 | + |
| 23 | + |
| 24 | + |
| 25 | +## Prerequisites |
| 26 | + |
| 27 | +* [Visual Studio 2019](https://visualstudio.microsoft.com/vs/) or [Visual Studio Code](https://code.visualstudio.com/) |
| 28 | +* [.NET Core SDK 3.1+](https://dotnet.microsoft.com/download) |
| 29 | + |
| 30 | +## Register and download your quickstart application |
| 31 | + |
| 32 | +#### Step 1: Register your application |
| 33 | +1. Sign in to the <a href="https://portal.azure.com/" target="_blank">Azure portal</a>. |
| 34 | +1. If you have access to multiple tenants, use the **Directories + subscriptions** filter :::image type="icon" source="../../media/common/portal-directory-subscription-filter.png" border="false"::: in the top menu to switch to the tenant in which you want to register the application. |
| 35 | +1. Search for and select **Azure Active Directory**. |
| 36 | +1. Under **Manage**, select **App registrations** > **New registration**. |
| 37 | +1. For **Name**, enter a name for your application. For example, enter **AspNetCore-Quickstart**. Users of your app will see this name, and you can change it later. |
| 38 | +1. For **Redirect URI**, enter **https://localhost:44321/signin-oidc**. |
| 39 | +1. Select **Register**. |
| 40 | +1. Under **Manage**, select **Authentication**. |
| 41 | +1. For **Front-channel logout URL**, enter **https://localhost:44321/signout-oidc**. |
| 42 | +1. Under **Implicit grant and hybrid flows**, select **ID tokens**. |
| 43 | +1. Select **Save**. |
| 44 | +1. Under **Manage**, select **Certificates & secrets** > **Client secrets** > **New client secret**. |
| 45 | +1. Enter a **Description**, for example `clientsecret1`. |
| 46 | +1. Select **In 1 year** for the secret's expiration. |
| 47 | +1. Select **Add** and immediately record the secret's **Value** for use in a later step. The secret value is *never displayed again* and is irretrievable by any other means. Record it in a secure location as you would any password. |
| 48 | + |
| 49 | +#### Step 2: Download the ASP.NET Core project |
| 50 | + |
| 51 | + |
| 52 | +[Download the ASP.NET Core solution](https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/archive/aspnetcore3-1.zip) |
| 53 | + |
| 54 | +[!INCLUDE [active-directory-develop-path-length-tip](../../../../../includes/active-directory-develop-path-length-tip.md)] |
| 55 | + |
| 56 | +#### Step 3: Configure your ASP.NET Core project |
| 57 | +1. Extract the .zip archive into a local folder near the root of your drive. For example, extract into *C:\Azure-Samples*. |
| 58 | + |
| 59 | + We recommend extracting the archive into a directory near the root of your drive to avoid errors caused by path length limitations on Windows. |
| 60 | +1. Open the solution in Visual Studio 2019. |
| 61 | +1. Open the *appsettings.json* file and modify the following code: |
| 62 | + |
| 63 | + ```json |
| 64 | + "Domain": "[Enter the domain of your tenant, e.g. contoso.onmicrosoft.com]", |
| 65 | + "ClientId": "Enter_the_Application_Id_here", |
| 66 | + "TenantId": "common", |
| 67 | + ``` |
| 68 | + |
| 69 | + - Replace `Enter_the_Application_Id_here` with the application (client) ID of the application that you registered in the Azure portal. You can find the **Application (client) ID** value on the app's **Overview** page. |
| 70 | + - Replace `common` with one of the following: |
| 71 | + - If your application supports **Accounts in this organizational directory only**, replace this value with the directory (tenant) ID (a GUID) or the tenant name (for example, `contoso.onmicrosoft.com`). You can find the **Directory (tenant) ID** value on the app's **Overview** page. |
| 72 | + - If your application supports **Accounts in any organizational directory**, replace this value with `organizations`. |
| 73 | + - If your application supports **All Microsoft account users**, leave this value as `common`. |
| 74 | + - Replace `Enter_the_Client_Secret_Here` with the **Client secret** you created and recorded in an earlier step. |
| 75 | + |
| 76 | +For this quickstart, don't change any other values in the *appsettings.json* file. |
| 77 | + |
| 78 | +#### Step 4: Build and run the application |
| 79 | + |
| 80 | +Build and run the app in Visual Studio by selecting the **Debug** menu > **Start Debugging**, or by pressing the F5 key. |
| 81 | + |
| 82 | +You're prompted for your credentials, and then asked to consent to the permissions that your app requires. Select **Accept** on the consent prompt. |
| 83 | + |
| 84 | +:::image type="content" source="../../media/quickstart-v2-aspnet-core-webapp/webapp-01-consent.png" alt-text="Screenshot of the consent dialog box, showing the permissions that the app is requesting from the user."::: |
| 85 | + |
| 86 | +After consenting to the requested permissions, the app displays that you've successfully logged in using your Azure Active Directory credentials, and you'll see your email address in the "Api result" section of the page. This was extracted using Microsoft Graph. |
| 87 | + |
| 88 | +:::image type="content" source="../../media/quickstart-v2-aspnet-core-webapp-calls-graph/webapp-02-signed-in.png" alt-text="Web browser displaying the running web app and the user signed in"::: |
| 89 | + |
| 90 | +## More information |
| 91 | + |
| 92 | +This section gives an overview of the code required to sign in users and call the Microsoft Graph API on their behalf. This overview can be useful to understand how the code works, main arguments, and also if you want to add sign-in to an existing ASP.NET Core application and call Microsoft Graph. It uses [Microsoft.Identity.Web](../../microsoft-identity-web.md), which is a wrapper around [MSAL.NET](../../msal-overview.md). |
| 93 | + |
| 94 | +### Startup class |
| 95 | + |
| 96 | +The *Microsoft.AspNetCore.Authentication* middleware uses a `Startup` class that's executed when the hosting process starts: |
| 97 | + |
| 98 | +```csharp |
| 99 | + // Get the scopes from the configuration (appsettings.json) |
| 100 | + var initialScopes = Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' '); |
| 101 | + |
| 102 | + public void ConfigureServices(IServiceCollection services) |
| 103 | + { |
| 104 | + // Add sign-in with Microsoft |
| 105 | + services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) |
| 106 | + .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) |
| 107 | + |
| 108 | + // Add the possibility of acquiring a token to call a protected web API |
| 109 | + .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) |
| 110 | + |
| 111 | + // Enables controllers and pages to get GraphServiceClient by dependency injection |
| 112 | + // And use an in memory token cache |
| 113 | + .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi")) |
| 114 | + .AddInMemoryTokenCaches(); |
| 115 | + |
| 116 | + services.AddControllersWithViews(options => |
| 117 | + { |
| 118 | + var policy = new AuthorizationPolicyBuilder() |
| 119 | + .RequireAuthenticatedUser() |
| 120 | + .Build(); |
| 121 | + options.Filters.Add(new AuthorizeFilter(policy)); |
| 122 | + }); |
| 123 | + |
| 124 | + // Enables a UI and controller for sign in and sign out. |
| 125 | + services.AddRazorPages() |
| 126 | + .AddMicrosoftIdentityUI(); |
| 127 | + } |
| 128 | +``` |
| 129 | + |
| 130 | +The `AddAuthentication()` method configures the service to add cookie-based authentication. This authentication is used in browser scenarios and to set the challenge to OpenID Connect. |
| 131 | + |
| 132 | +The line that contains `.AddMicrosoftIdentityWebApp` adds Microsoft identity platform authentication to your application. The application is then configured to sign in users based on the following information in the `AzureAD` section of the *appsettings.json* configuration file: |
| 133 | + |
| 134 | +| *appsettings.json* key | Description | |
| 135 | +|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------| |
| 136 | +| `ClientId` | Application (client) ID of the application registered in the Azure portal. | |
| 137 | +| `Instance` | Security token service (STS) endpoint for the user to authenticate. This value is typically `https://login.microsoftonline.com/`, indicating the Azure public cloud. | |
| 138 | +| `TenantId` | Name of your tenant or the tenant ID (a GUID), or `common` to sign in users with work or school accounts or Microsoft personal accounts. | |
| 139 | + |
| 140 | +The `EnableTokenAcquisitionToCallDownstreamApi` method enables your application to acquire a token to call protected web APIs. `AddMicrosoftGraph` enables your controllers or Razor pages to benefit directly the `GraphServiceClient` (by dependency injection) and the `AddInMemoryTokenCaches` methods enables your app to benefit from a token cache. |
| 141 | + |
| 142 | +The `Configure()` method contains two important methods, `app.UseAuthentication()` and `app.UseAuthorization()`, that enable their named functionality. Also in the `Configure()` method, you must register Microsoft Identity Web routes with at least one call to `endpoints.MapControllerRoute()` or a call to `endpoints.MapControllers()`: |
| 143 | + |
| 144 | +```csharp |
| 145 | +app.UseAuthentication(); |
| 146 | +app.UseAuthorization(); |
| 147 | + |
| 148 | +app.UseEndpoints(endpoints => |
| 149 | +{ |
| 150 | + endpoints.MapControllerRoute( |
| 151 | + name: "default", |
| 152 | + pattern: "{controller=Home}/{action=Index}/{id?}"); |
| 153 | + endpoints.MapRazorPages(); |
| 154 | +}); |
| 155 | +``` |
| 156 | + |
| 157 | +### Protect a controller or a controller's method |
| 158 | + |
| 159 | +You can protect a controller or its methods by applying the `[Authorize]` attribute to the controller's class or one or more of its methods. This `[Authorize]` attribute restricts access by allowing only authenticated users. If the user isn't already authenticated, an authentication challenge can be started to access the controller. In this quickstart, the scopes are read from the configuration file: |
| 160 | + |
| 161 | +```csharp |
| 162 | +[AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")] |
| 163 | +public async Task<IActionResult> Index() |
| 164 | +{ |
| 165 | + var user = await _graphServiceClient.Me.Request().GetAsync(); |
| 166 | + ViewData["ApiResult"] = user.DisplayName; |
| 167 | + |
| 168 | + return View(); |
| 169 | +} |
| 170 | +``` |
| 171 | + |
| 172 | +[!INCLUDE [Help and support](../../../../../includes/active-directory-develop-help-support-include.md)] |
| 173 | + |
| 174 | +## Next steps |
| 175 | + |
| 176 | +The GitHub repo that contains the ASP.NET Core code sample referenced in this quickstart includes instructions and more code samples that show you how to: |
| 177 | + |
| 178 | +- Add authentication to a new ASP.NET Core web application. |
| 179 | +- Call Microsoft Graph, other Microsoft APIs, or your own web APIs. |
| 180 | +- Add authorization. |
| 181 | +- Sign in users in national clouds or with social identities. |
| 182 | + |
| 183 | +> [!div class="nextstepaction"] |
| 184 | +> [ASP.NET Core web app tutorials on GitHub](https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/) |
0 commit comments