From 5cc925382810643e6a93c01ce8494efd62f5cc58 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Sat, 15 Feb 2020 13:54:13 -0800 Subject: [PATCH 1/3] Fixing a build break --- .gitignore | 1 + Microsoft.Identity.Web/Microsoft.Identity.Web.csproj | 1 + 2 files changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index b58fe4ee..d2f3b0a1 100644 --- a/.gitignore +++ b/.gitignore @@ -129,3 +129,4 @@ /2-WebApp-graph-user/2-3-Multi-Tenant/bin/Debug/netcoreapp2.2 /2-WebApp-graph-user/2-3-Multi-Tenant/obj /Microsoft.Identity.Web.Test/bin/Release/netcoreapp3.0 +/2-WebApp-graph-user/2-1-Call-MSGraph/TestResults diff --git a/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj b/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj index 7f4c898b..7fbea89f 100644 --- a/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj +++ b/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj @@ -55,6 +55,7 @@ + From 81c281e6165b068460bb43d8378ad18ba6bfcd51 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Sun, 16 Feb 2020 13:30:11 -0800 Subject: [PATCH 2/3] Fixing the configuration and a problem brought bad a by merge by jmprieur --- .../Client/Properties/launchSettings.json | 6 ++--- 4-WebApp-your-API/Client/Startup.cs | 2 +- 4-WebApp-your-API/Client/appsettings.json | 5 ++-- .../WebApp-OpenIDConnect-DotNet.sln | 6 +++++ .../WebApiServiceCollectionExtensionsTests.cs | 13 +++++++--- .../WebApiServiceCollectionExtensions.cs | 24 ++++++++++++------- 6 files changed, 38 insertions(+), 18 deletions(-) diff --git a/4-WebApp-your-API/Client/Properties/launchSettings.json b/4-WebApp-your-API/Client/Properties/launchSettings.json index f1f25b7f..f0c28a9b 100644 --- a/4-WebApp-your-API/Client/Properties/launchSettings.json +++ b/4-WebApp-your-API/Client/Properties/launchSettings.json @@ -3,8 +3,8 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "https://localhost:44316/", - "sslPort": 44316 + "applicationUrl": "https://localhost:5000/", + "sslPort": 5000 } }, "profiles": { @@ -14,7 +14,7 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, - "applicationUrl": "https://localhost:44316" + "applicationUrl": "https://localhost:5000" } } } \ No newline at end of file diff --git a/4-WebApp-your-API/Client/Startup.cs b/4-WebApp-your-API/Client/Startup.cs index 84faec2a..557e013b 100644 --- a/4-WebApp-your-API/Client/Startup.cs +++ b/4-WebApp-your-API/Client/Startup.cs @@ -43,7 +43,7 @@ public void ConfigureServices(IServiceCollection services) services.AddOptions(); services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddSignIn("AzureAdB2C", Configuration, options => Configuration.Bind("AzureAdB2C", options)); + .AddSignIn("AzureAdB2C", Configuration, options => Configuration.Bind("AzureAdB2C", options), subscribeToOpenIdConnectMiddlewareDiagnosticsEvents:true); // This is required to be instantiated before the OpenIdConnectOptions starts getting configured. // By default, the claims mapping will map claim names in the old format to accommodate older SAML applications. diff --git a/4-WebApp-your-API/Client/appsettings.json b/4-WebApp-your-API/Client/appsettings.json index f035bb93..ab89c863 100644 --- a/4-WebApp-your-API/Client/appsettings.json +++ b/4-WebApp-your-API/Client/appsettings.json @@ -1,12 +1,13 @@ { "AzureAdB2C": { "Instance": "https://fabrikamb2c.b2clogin.com", - "ClientId": "90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6", + "ClientId": "fdb91ff5-5ce6-41f3-bdbd-8267c817015d", "Domain": "fabrikamb2c.onmicrosoft.com", "SignedOutCallbackPath": "/signout/B2C_1_susi", "SignUpSignInPolicyId": "b2c_1_susi", "ResetPasswordPolicyId": "b2c_1_reset", - "EditProfilePolicyId": "b2c_1_edit_profile" // Optional profile editing policy + "EditProfilePolicyId": "b2c_1_edit_profile", // Optional profile editing policy + "ClientSecret": "X330F3#92!z614M4" //"CallbackPath": "/signin/B2C_1_sign_up_in" // defaults to /signin-oidc }, "AzureAd": { diff --git a/4-WebApp-your-API/WebApp-OpenIDConnect-DotNet.sln b/4-WebApp-your-API/WebApp-OpenIDConnect-DotNet.sln index 8bb77477..c59f0994 100644 --- a/4-WebApp-your-API/WebApp-OpenIDConnect-DotNet.sln +++ b/4-WebApp-your-API/WebApp-OpenIDConnect-DotNet.sln @@ -17,6 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Identity.Web", ". EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Identity.Web.UI", "..\Microsoft.Identity.Web.UI\Microsoft.Identity.Web.UI.csproj", "{A2B0D2D4-6799-4B6F-AC51-F0F0A6CA1E89}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Identity.Web.Test", "..\Microsoft.Identity.Web.Test\Microsoft.Identity.Web.Test.csproj", "{C4827ACC-3765-46C2-8D86-ACFCEB175A11}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -39,6 +41,10 @@ Global {A2B0D2D4-6799-4B6F-AC51-F0F0A6CA1E89}.Debug|Any CPU.Build.0 = Debug|Any CPU {A2B0D2D4-6799-4B6F-AC51-F0F0A6CA1E89}.Release|Any CPU.ActiveCfg = Release|Any CPU {A2B0D2D4-6799-4B6F-AC51-F0F0A6CA1E89}.Release|Any CPU.Build.0 = Release|Any CPU + {C4827ACC-3765-46C2-8D86-ACFCEB175A11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4827ACC-3765-46C2-8D86-ACFCEB175A11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4827ACC-3765-46C2-8D86-ACFCEB175A11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4827ACC-3765-46C2-8D86-ACFCEB175A11}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Microsoft.Identity.Web.Test/WebApiServiceCollectionExtensionsTests.cs b/Microsoft.Identity.Web.Test/WebApiServiceCollectionExtensionsTests.cs index fba6c594..d2e0bbfa 100644 --- a/Microsoft.Identity.Web.Test/WebApiServiceCollectionExtensionsTests.cs +++ b/Microsoft.Identity.Web.Test/WebApiServiceCollectionExtensionsTests.cs @@ -46,24 +46,31 @@ public void TestAuthority() public void TestAudience() { JwtBearerOptions options = new JwtBearerOptions(); + MicrosoftIdentityOptions microsoftIdentityOptions = new MicrosoftIdentityOptions() { ClientId = Guid.NewGuid().ToString() }; // Act and Assert options.Audience = "https://localhost"; - WebApiServiceCollectionExtensions.EnsureValidAudiencesContainsApiGuidIfGuidProvided(options); + WebApiServiceCollectionExtensions.EnsureValidAudiencesContainsApiGuidIfGuidProvided(options, microsoftIdentityOptions); Assert.True(options.TokenValidationParameters.ValidAudiences.Count() == 1); Assert.True(options.TokenValidationParameters.ValidAudiences.First() == "https://localhost"); options.Audience = "api://1EE5A092-0DFD-42B6-88E5-C517C0141321"; - WebApiServiceCollectionExtensions.EnsureValidAudiencesContainsApiGuidIfGuidProvided(options); + WebApiServiceCollectionExtensions.EnsureValidAudiencesContainsApiGuidIfGuidProvided(options, microsoftIdentityOptions); Assert.True(options.TokenValidationParameters.ValidAudiences.Count() == 1); Assert.True(options.TokenValidationParameters.ValidAudiences.First() == "api://1EE5A092-0DFD-42B6-88E5-C517C0141321"); options.Audience = "1EE5A092-0DFD-42B6-88E5-C517C0141321"; - WebApiServiceCollectionExtensions.EnsureValidAudiencesContainsApiGuidIfGuidProvided(options); + WebApiServiceCollectionExtensions.EnsureValidAudiencesContainsApiGuidIfGuidProvided(options, microsoftIdentityOptions); Assert.True(options.TokenValidationParameters.ValidAudiences.Count() == 2); Assert.Contains("api://1EE5A092-0DFD-42B6-88E5-C517C0141321", options.TokenValidationParameters.ValidAudiences); Assert.Contains("1EE5A092-0DFD-42B6-88E5-C517C0141321", options.TokenValidationParameters.ValidAudiences); + options.Audience = null; + WebApiServiceCollectionExtensions.EnsureValidAudiencesContainsApiGuidIfGuidProvided(options, microsoftIdentityOptions); + Assert.True(options.TokenValidationParameters.ValidAudiences.Count() == 2); + Assert.Contains($"api://{microsoftIdentityOptions.ClientId}", options.TokenValidationParameters.ValidAudiences); + Assert.Contains($"{microsoftIdentityOptions.ClientId}", options.TokenValidationParameters.ValidAudiences); + } } } diff --git a/Microsoft.Identity.Web/WebApiServiceCollectionExtensions.cs b/Microsoft.Identity.Web/WebApiServiceCollectionExtensions.cs index 4f8c8a6c..2fea242b 100644 --- a/Microsoft.Identity.Web/WebApiServiceCollectionExtensions.cs +++ b/Microsoft.Identity.Web/WebApiServiceCollectionExtensions.cs @@ -171,10 +171,8 @@ public static AuthenticationBuilder AddProtectedWebApi( // The valid audience could be given as Client Id or as Uri. // If it does not start with 'api://', this variant is added to the list of valid audiences. - EnsureValidAudiencesContainsApiGuidIfGuidProvided(options); + EnsureValidAudiencesContainsApiGuidIfGuidProvided(options, microsoftIdentityOptions); - options.TokenValidationParameters.ValidAudiences = GetValidAudiences(options, microsoftIdentityOptions); - // If the developer registered an IssuerValidator, do not overwrite it if (options.TokenValidationParameters.IssuerValidator == null) { @@ -270,13 +268,21 @@ internal static void EnsureAuthorityIsV2_0(JwtBearerOptions options) /// /// Jwt bearer options for which to ensure that /// api://GUID is a valid audience - internal static void EnsureValidAudiencesContainsApiGuidIfGuidProvided(JwtBearerOptions options) + internal static void EnsureValidAudiencesContainsApiGuidIfGuidProvided(JwtBearerOptions options, MicrosoftIdentityOptions msIdentityOptions) { - var validAudiences = new List { options.Audience }; - if (!options.Audience.StartsWith("api://", StringComparison.OrdinalIgnoreCase) - && Guid.TryParse(options.Audience, out _)) - validAudiences.Add($"api://{options.Audience}"); - + var validAudiences = new List(); + if (!string.IsNullOrWhiteSpace(options.Audience)) + { + validAudiences.Add(options.Audience); + if (!options.Audience.StartsWith("api://", StringComparison.OrdinalIgnoreCase) + && Guid.TryParse(options.Audience, out _)) + validAudiences.Add($"api://{options.Audience}"); + } + else + { + validAudiences.Add(msIdentityOptions.ClientId); + validAudiences.Add($"api://{msIdentityOptions.ClientId}"); + } options.TokenValidationParameters.ValidAudiences = validAudiences; } } From 2962513068ce435d5ae4539217fa59ce82fe6bbf Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Sun, 16 Feb 2020 13:34:16 -0800 Subject: [PATCH 3/3] add uitid to the claims for b2c --- Microsoft.Identity.Web/ClaimConstants.cs | 1 + Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs | 9 ++------- .../WebAppServiceCollectionExtensions.cs | 1 + 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Microsoft.Identity.Web/ClaimConstants.cs b/Microsoft.Identity.Web/ClaimConstants.cs index f332da4e..390f1918 100644 --- a/Microsoft.Identity.Web/ClaimConstants.cs +++ b/Microsoft.Identity.Web/ClaimConstants.cs @@ -15,6 +15,7 @@ public static class ClaimConstants public const string TenantId = "http://schemas.microsoft.com/identity/claims/tenantid"; public const string Tid = "tid"; public const string ClientInfo = "client_info"; + public const string UniqueObjectIdentifier = "utid"; // Older scope claim public const string Scope = "http://schemas.microsoft.com/identity/claims/scope"; // Newer scope claim diff --git a/Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs b/Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs index 6c04e5e2..579af09b 100644 --- a/Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs +++ b/Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs @@ -28,7 +28,7 @@ public static string GetMsalAccountId(this ClaimsPrincipal claimsPrincipal) !string.IsNullOrWhiteSpace(userFlowId)) { // B2C pattern: {oid}-{userFlow}.{tid} - return $"{nameIdentifierId}-{userFlowId}.{tenantId}"; + return $"{nameIdentifierId}.{tenantId}"; } else if (!string.IsNullOrWhiteSpace(userObjectId) && !string.IsNullOrWhiteSpace(tenantId)) { @@ -152,12 +152,7 @@ public static string GetUserFlowId(this ClaimsPrincipal claimsPrincipal) /// Name identifier ID (sub) of the identity, or null if it cannot be found public static string GetNameIdentifierId(this ClaimsPrincipal claimsPrincipal) { - string sub = claimsPrincipal.FindFirstValue(ClaimConstants.Sub); - if (string.IsNullOrEmpty(sub)) - { - sub = claimsPrincipal.FindFirstValue(ClaimTypes.NameIdentifier); - } - return sub; + return claimsPrincipal.FindFirstValue(ClaimConstants.UniqueObjectIdentifier); } } } diff --git a/Microsoft.Identity.Web/WebAppServiceCollectionExtensions.cs b/Microsoft.Identity.Web/WebAppServiceCollectionExtensions.cs index 5da93a31..74069341 100644 --- a/Microsoft.Identity.Web/WebAppServiceCollectionExtensions.cs +++ b/Microsoft.Identity.Web/WebAppServiceCollectionExtensions.cs @@ -122,6 +122,7 @@ public static IServiceCollection AddWebAppCallsProtectedWebApi( if (clientInfoFromServer != null) { context.Principal.Identities.FirstOrDefault().AddClaim(new Claim(ClaimConstants.Tid, clientInfoFromServer.UniqueTenantIdentifier)); + context.Principal.Identities.FirstOrDefault().AddClaim(new Claim(ClaimConstants.UniqueObjectIdentifier, clientInfoFromServer.UniqueObjectIdentifier)); } } }