From 67aa920480eca51f621a51920b474cbf8d4e1d9d Mon Sep 17 00:00:00 2001 From: damienbod Date: Fri, 11 Sep 2020 11:31:47 +0200 Subject: [PATCH 1/4] code clean up --- .../Controllers/HomeController.cs | 9 +-- .../2-1-Call-MSGraph/Startup.cs | 55 ++++++++----------- 2 files changed, 26 insertions(+), 38 deletions(-) diff --git a/2-WebApp-graph-user/2-1-Call-MSGraph/Controllers/HomeController.cs b/2-WebApp-graph-user/2-1-Call-MSGraph/Controllers/HomeController.cs index 1d4682fa..f006ff1c 100644 --- a/2-WebApp-graph-user/2-1-Call-MSGraph/Controllers/HomeController.cs +++ b/2-WebApp-graph-user/2-1-Call-MSGraph/Controllers/HomeController.cs @@ -1,13 +1,8 @@ using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; -using Microsoft.Extensions.Configuration; using Microsoft.Identity.Web; -using System.Net; -using System.Net.Http; using Microsoft.Graph; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; @@ -26,9 +21,9 @@ public class HomeController : Controller public HomeController(ILogger logger, GraphServiceClient graphServiceClient) { - _logger = logger; + _logger = logger; _graphServiceClient = graphServiceClient; - } + } [AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")] public async Task Index() diff --git a/2-WebApp-graph-user/2-1-Call-MSGraph/Startup.cs b/2-WebApp-graph-user/2-1-Call-MSGraph/Startup.cs index b97dd51d..9bb07b77 100644 --- a/2-WebApp-graph-user/2-1-Call-MSGraph/Startup.cs +++ b/2-WebApp-graph-user/2-1-Call-MSGraph/Startup.cs @@ -1,20 +1,13 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.Identity.Web; using Microsoft.Identity.Web.UI; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc.Authorization; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Microsoft.Graph; namespace _2_1_Call_MSGraph { @@ -38,32 +31,32 @@ public void ConfigureServices(IServiceCollection services) .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi")) .AddInMemoryTokenCaches(); - /* - // or use a distributed Token Cache by adding - .AddDistributedTokenCaches(); + /* + // or use a distributed Token Cache by adding + .AddDistributedTokenCaches(); - // and then choose your implementation. - // See https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed?view=aspnetcore-2.2#distributed-memory-cache + // and then choose your implementation. + // See https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed?view=aspnetcore-2.2#distributed-memory-cache - // For instance the distributed in memory cache - services.AddDistributedMemoryCache() + // For instance the distributed in memory cache + services.AddDistributedMemoryCache() - // Or a Redis cache - services.AddStackExchangeRedisCache(options => - { - options.Configuration = "localhost"; - options.InstanceName = "SampleInstance"; - }); + // Or a Redis cache + services.AddStackExchangeRedisCache(options => + { + options.Configuration = "localhost"; + options.InstanceName = "SampleInstance"; + }); - // Or even a SQL Server token cache - services.AddDistributedSqlServerCache(options => - { - options.ConnectionString = - _config["DistCache_ConnectionString"]; - options.SchemaName = "dbo"; - options.TableName = "TestCache"; - }); - */ + // Or even a SQL Server token cache + services.AddDistributedSqlServerCache(options => + { + options.ConnectionString = + _config["DistCache_ConnectionString"]; + options.SchemaName = "dbo"; + options.TableName = "TestCache"; + }); + */ services.AddControllersWithViews(options => { @@ -72,8 +65,8 @@ public void ConfigureServices(IServiceCollection services) .Build(); options.Filters.Add(new AuthorizeFilter(policy)); }); - services.AddRazorPages() - .AddMicrosoftIdentityUI(); + services.AddRazorPages() + .AddMicrosoftIdentityUI(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. From 1ed0fda02e530a31e75c335c4e978dd4098242dc Mon Sep 17 00:00:00 2001 From: damienbod Date: Fri, 11 Sep 2020 11:32:06 +0200 Subject: [PATCH 2/4] removing unused headers --- 2-WebApp-graph-user/2-1-Call-MSGraph/Program.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/2-WebApp-graph-user/2-1-Call-MSGraph/Program.cs b/2-WebApp-graph-user/2-1-Call-MSGraph/Program.cs index bc030274..b697b428 100644 --- a/2-WebApp-graph-user/2-1-Call-MSGraph/Program.cs +++ b/2-WebApp-graph-user/2-1-Call-MSGraph/Program.cs @@ -1,11 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; namespace _2_1_Call_MSGraph { From 8550ebdfba25c95e676740a97417c5347e3d5136 Mon Sep 17 00:00:00 2001 From: damienbod Date: Fri, 11 Sep 2020 11:37:59 +0200 Subject: [PATCH 3/4] Fixing readme 2-1-Call-MSGraph --- .../2-1-Call-MSGraph/Models/ErrorViewModel.cs | 2 - .../2-1-Call-MSGraph/README.md | 46 +++++++++---------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/2-WebApp-graph-user/2-1-Call-MSGraph/Models/ErrorViewModel.cs b/2-WebApp-graph-user/2-1-Call-MSGraph/Models/ErrorViewModel.cs index ffe85ddc..c6ed3de6 100644 --- a/2-WebApp-graph-user/2-1-Call-MSGraph/Models/ErrorViewModel.cs +++ b/2-WebApp-graph-user/2-1-Call-MSGraph/Models/ErrorViewModel.cs @@ -1,5 +1,3 @@ -using System; - namespace _2_1_Call_MSGraph.Models { public class ErrorViewModel diff --git a/2-WebApp-graph-user/2-1-Call-MSGraph/README.md b/2-WebApp-graph-user/2-1-Call-MSGraph/README.md index 7ecc5662..0edd382d 100644 --- a/2-WebApp-graph-user/2-1-Call-MSGraph/README.md +++ b/2-WebApp-graph-user/2-1-Call-MSGraph/README.md @@ -100,9 +100,13 @@ After the following lines in the ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services) { . . . - services.AddMicrosoftIdentityWebAppAuthentication(Configuration) - .EnableTokenAcquisitionToCallDownstreamApi(new string[] { Constants.ScopeUserRead }) - .AddInMemoryTokenCaches(); + string[] initialScopes = Configuration.GetValue("DownstreamApi:Scopes")?.Split(' '); + + services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) + .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) + .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) + .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi")) + .AddInMemoryTokenCaches(); ``` The two new lines of code: @@ -154,11 +158,15 @@ Add the `Services\*.cs` files. The `GraphServiceClientFactory.cs` returns a `Gra ### Update the `Startup.cs` file to enable the Microsoft Graph custom service -Still in the `Startup.cs` file, add the following lines just after the following. This lines ensures that the GraphAPIService benefits from the optimized `HttpClient` management by ASP.NET Core. +Still in the `Startup.cs` file, add the following `AddMicrosoftGraph` extension method. This lines ensures that the GraphAPIService benefits from the optimized `HttpClient` management by ASP.NET Core. ```CSharp // Add Graph - services.AddGraphService(Configuration); + services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) + .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) + .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) + .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi")) + .AddInMemoryTokenCaches(); ``` ### Change the controller code to acquire a token and call Microsoft Graph @@ -168,32 +176,29 @@ In the `Controllers\HomeController.cs`file: 1. Add a constructor to HomeController, making the ITokenAcquisition service available (used by the ASP.NET dependency injection mechanism) ```CSharp -readonly ITokenAcquisition tokenAcquisition; -readonly WebOptions webOptions; +private readonly GraphServiceClient _graphServiceClient; -public HomeController(ITokenAcquisition tokenAcquisition, IOptions webOptionValue) +public HomeController(ILogger logger, + GraphServiceClient graphServiceClient) { - this.tokenAcquisition = tokenAcquisition; - this.webOptions = webOptionValue.Value; + _logger = logger; + _graphServiceClient = graphServiceClient; } ``` 1. Add a `Profile()` action so that it calls the Microsoft Graph *me* endpoint. In case a token cannot be acquired, a challenge is attempted to re-sign-in the user, and have them consent to the requested scopes. This is expressed declaratively by the `AuthorizeForScopes`attribute. This attribute is part of the `Microsoft.Identity.Web` project and automatically manages incremental consent. ```CSharp -[AuthorizeForScopes(Scopes = new[] { Constants.ScopeUserRead })] +[AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")] public async Task Profile() { - // Initialize the GraphServiceClient. - Graph::GraphServiceClient graphClient = GetGraphServiceClient(new[] { Constants.ScopeUserRead }); - - var me = await graphClient.Me.Request().GetAsync(); + var me = await _graphServiceClient.Me.Request().GetAsync(); ViewData["Me"] = me; try { // Get user photo - using (var photoStream = await graphClient.Me.Photo.Content.Request().GetAsync()) + using (var photoStream = await _graphServiceClient.Me.Photo.Content.Request().GetAsync()) { byte[] photoByte = ((MemoryStream)photoStream).ToArray(); ViewData["Photo"] = Convert.ToBase64String(photoByte); @@ -206,15 +211,6 @@ public async Task Profile() return View(); } - -private Graph::GraphServiceClient GetGraphServiceClient(string[] scopes) -{ - return GraphServiceClientFactory.GetAuthenticatedGraphClient(async () => - { - string result = await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(scopes); - return result; - }, webOptions.GraphApiUrl); -} ``` ### Add a Profile view to display the *me* object From c581497f30fb196fd2037fe7edd1ea2e0638b86f Mon Sep 17 00:00:00 2001 From: damienbod Date: Fri, 11 Sep 2020 11:46:28 +0200 Subject: [PATCH 4/4] some formatting --- 2-WebApp-graph-user/2-1-Call-MSGraph/README.md | 17 +++++++++-------- 2-WebApp-graph-user/2-1-Call-MSGraph/Startup.cs | 8 ++++---- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/2-WebApp-graph-user/2-1-Call-MSGraph/README.md b/2-WebApp-graph-user/2-1-Call-MSGraph/README.md index 0edd382d..459f7b74 100644 --- a/2-WebApp-graph-user/2-1-Call-MSGraph/README.md +++ b/2-WebApp-graph-user/2-1-Call-MSGraph/README.md @@ -102,11 +102,12 @@ After the following lines in the ConfigureServices(IServiceCollection services) . . . string[] initialScopes = Configuration.GetValue("DownstreamApi:Scopes")?.Split(' '); + // Add Graph services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) - .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) - .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi")) - .AddInMemoryTokenCaches(); + .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) + .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) + .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi")) + .AddInMemoryTokenCaches(); ``` The two new lines of code: @@ -163,10 +164,10 @@ Still in the `Startup.cs` file, add the following `AddMicrosoftGraph` extension ```CSharp // Add Graph services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) - .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) - .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi")) - .AddInMemoryTokenCaches(); + .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) + .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) + .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi")) + .AddInMemoryTokenCaches(); ``` ### Change the controller code to acquire a token and call Microsoft Graph diff --git a/2-WebApp-graph-user/2-1-Call-MSGraph/Startup.cs b/2-WebApp-graph-user/2-1-Call-MSGraph/Startup.cs index 9bb07b77..8e432a1c 100644 --- a/2-WebApp-graph-user/2-1-Call-MSGraph/Startup.cs +++ b/2-WebApp-graph-user/2-1-Call-MSGraph/Startup.cs @@ -26,10 +26,10 @@ public void ConfigureServices(IServiceCollection services) string[] initialScopes = Configuration.GetValue("DownstreamApi:Scopes")?.Split(' '); services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) - .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) - .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi")) - .AddInMemoryTokenCaches(); + .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) + .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) + .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi")) + .AddInMemoryTokenCaches(); /* // or use a distributed Token Cache by adding