From 26e85911e00f9d312fd5700917a3aebe08456172 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Mon, 16 Mar 2020 10:15:04 -0700 Subject: [PATCH 1/4] Cleanup startup apis --- ...lWebAssemblyServiceCollectionExtensions.cs | 18 +++-- ...thenticationServiceCollectionExtensions.cs | 73 ++++++++++++++----- 2 files changed, 66 insertions(+), 25 deletions(-) diff --git a/src/Components/WebAssembly/Authentication.Msal/src/MsalWebAssemblyServiceCollectionExtensions.cs b/src/Components/WebAssembly/Authentication.Msal/src/MsalWebAssemblyServiceCollectionExtensions.cs index 0071f2b758a3..2d395058fc38 100644 --- a/src/Components/WebAssembly/Authentication.Msal/src/MsalWebAssemblyServiceCollectionExtensions.cs +++ b/src/Components/WebAssembly/Authentication.Msal/src/MsalWebAssemblyServiceCollectionExtensions.cs @@ -23,15 +23,23 @@ public static class MsalWebAssemblyServiceCollectionExtensions /// The to configure the . /// The . public static IServiceCollection AddMsalAuthentication(this IServiceCollection services, Action> configure) + { + return AddMsalAuthentication(services, configure); + } + + /// + /// Adds authentication using msal.js to Blazor applications. + /// + /// The type of the remote authentication state. + /// The . + /// The to configure the . + /// The . + public static IServiceCollection AddMsalAuthentication(this IServiceCollection services, Action> configure) + where TRemoteAuthenticationState : RemoteAuthenticationState, new() { services.AddRemoteAuthentication(); services.TryAddEnumerable(ServiceDescriptor.Singleton>, MsalDefaultOptionsConfiguration>()); - if (configure != null) - { - services.Configure(configure); - } - return services; } } diff --git a/src/Components/WebAssembly/WebAssembly.Authentication/src/WebAssemblyAuthenticationServiceCollectionExtensions.cs b/src/Components/WebAssembly/WebAssembly.Authentication/src/WebAssemblyAuthenticationServiceCollectionExtensions.cs index e8c2e8931080..352016df5bbb 100644 --- a/src/Components/WebAssembly/WebAssembly.Authentication/src/WebAssemblyAuthenticationServiceCollectionExtensions.cs +++ b/src/Components/WebAssembly/WebAssembly.Authentication/src/WebAssemblyAuthenticationServiceCollectionExtensions.cs @@ -78,50 +78,83 @@ public static IServiceCollection AddRemoteAuthenticationThe where the services were registered. public static IServiceCollection AddOidcAuthentication(this IServiceCollection services, Action> configure) { - AddRemoteAuthentication(services, configure); + return AddOidcAuthentication(services, configure); + } + /// + /// Adds support for authentication for SPA applications using and the . + /// + /// The type of the remote authentication state. + /// The to add the services to. + /// An action that will configure the . + /// The where the services were registered. + public static IServiceCollection AddOidcAuthentication(this IServiceCollection services, Action> configure) + where TRemoteAuthenticationState : RemoteAuthenticationState, new() + { services.TryAddEnumerable(ServiceDescriptor.Singleton>, DefaultOidcOptionsConfiguration>()); - if (configure != null) - { - services.Configure(configure); - } - - return services; + return AddRemoteAuthentication(services, configure); } /// /// Adds support for authentication for SPA applications using and the . /// + /// The type of the remote authentication state. /// The to add the services to. /// The where the services were registered. public static IServiceCollection AddApiAuthorization(this IServiceCollection services) { - var inferredClientId = Assembly.GetCallingAssembly().GetName().Name; - - services.AddRemoteAuthentication(); - - services.TryAddEnumerable( - ServiceDescriptor.Singleton>, DefaultApiAuthorizationOptionsConfiguration>(_ => - new DefaultApiAuthorizationOptionsConfiguration(inferredClientId))); + return AddApiauthorizationCore(services, configure: null, Assembly.GetCallingAssembly().GetName().Name); + } - return services; + /// + /// Adds support for authentication for SPA applications using and the . + /// + /// The type of the remote authentication state. + /// The to add the services to. + /// The where the services were registered. + public static IServiceCollection AddApiAuthorization(this IServiceCollection services) + where TRemoteAuthenticationState : RemoteAuthenticationState, new() + { + return AddApiauthorizationCore(services, configure: null, Assembly.GetCallingAssembly().GetName().Name); } /// /// Adds support for authentication for SPA applications using and the . /// + /// The type of the remote authentication state. /// The to add the services to. /// An action that will configure the . /// The where the services were registered. public static IServiceCollection AddApiAuthorization(this IServiceCollection services, Action> configure) { - services.AddApiAuthorization(); + return AddApiauthorizationCore(services, configure, Assembly.GetCallingAssembly().GetName().Name); + } - if (configure != null) - { - services.Configure(configure); - } + /// + /// Adds support for authentication for SPA applications using and the . + /// + /// The type of the remote authentication state. + /// The to add the services to. + /// An action that will configure the . + /// The where the services were registered. + public static IServiceCollection AddApiAuthorization(this IServiceCollection services, Action> configure) + where TRemoteAuthenticationState : RemoteAuthenticationState, new() + { + return AddApiauthorizationCore(services, configure, Assembly.GetCallingAssembly().GetName().Name); + } + + private static IServiceCollection AddApiauthorizationCore( + IServiceCollection services, + Action> configure, + string inferredClientId) + where TRemoteAuthenticationState : RemoteAuthenticationState, new() + { + services.TryAddEnumerable( + ServiceDescriptor.Singleton>, DefaultApiAuthorizationOptionsConfiguration>(_ => + new DefaultApiAuthorizationOptionsConfiguration(inferredClientId))); + + services.AddRemoteAuthentication(configure); return services; } From b62a939d09fa4757cf1c527e7a5a9704bce18cec Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Mon, 16 Mar 2020 10:32:16 -0700 Subject: [PATCH 2/4] Fix redirect to login --- .../ComponentsWebAssembly-CSharp/Client/App.razor | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ProjectTemplates/ComponentsWebAssembly.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/App.razor b/src/ProjectTemplates/ComponentsWebAssembly.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/App.razor index 9e038086aedf..c491110ce2b4 100644 --- a/src/ProjectTemplates/ComponentsWebAssembly.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/App.razor +++ b/src/ProjectTemplates/ComponentsWebAssembly.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/App.razor @@ -15,7 +15,14 @@ - + @if(!context.User.Identity.IsAuthenticated) + { + + } + else + { +

You are not authorized to access this resource.

+ }
From 2b38f206d8df15c71625f394bf962025426e86f5 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Mon, 16 Mar 2020 10:49:51 -0700 Subject: [PATCH 3/4] Escape data string --- .../Client/Shared/RedirectToLogin.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProjectTemplates/ComponentsWebAssembly.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/Shared/RedirectToLogin.razor b/src/ProjectTemplates/ComponentsWebAssembly.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/Shared/RedirectToLogin.razor index 7fa0d95bafe2..b535ae4216f2 100644 --- a/src/ProjectTemplates/ComponentsWebAssembly.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/Shared/RedirectToLogin.razor +++ b/src/ProjectTemplates/ComponentsWebAssembly.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/Shared/RedirectToLogin.razor @@ -3,6 +3,6 @@ @code { protected override void OnInitialized() { - Navigation.NavigateTo($"authentication/login?returnUrl={Navigation.Uri}"); + Navigation.NavigateTo($"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}"); } } From 07a13916e5da17ce5766051face16fbdb1503af4 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Mon, 16 Mar 2020 11:30:37 -0700 Subject: [PATCH 4/4] Fix async initialization bug --- .../src/Interop/AuthenticationService.ts | 19 +++++++++++++++---- .../src/Interop/package.json | 1 + 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Components/WebAssembly/WebAssembly.Authentication/src/Interop/AuthenticationService.ts b/src/Components/WebAssembly/WebAssembly.Authentication/src/Interop/AuthenticationService.ts index 7a95395af1ed..42fb5e5a39d1 100644 --- a/src/Components/WebAssembly/WebAssembly.Authentication/src/Interop/AuthenticationService.ts +++ b/src/Components/WebAssembly/WebAssembly.Authentication/src/Interop/AuthenticationService.ts @@ -253,15 +253,26 @@ class OidcAuthorizeService implements AuthorizeService { export class AuthenticationService { static _infrastructureKey = 'Microsoft.AspNetCore.Components.WebAssembly.Authentication'; - static _initialized = false; + static _initialized : Promise; static instance: OidcAuthorizeService; public static async init(settings: UserManagerSettings & AuthorizeServiceSettings) { + // Multiple initializations can start concurrently and we want to avoid that. + // In order to do so, we create an initialization promise and the first call to init + // tries to initialize the app and sets up a promise other calls can await on. if (!AuthenticationService._initialized) { - AuthenticationService._initialized = true; - const userManager = await this.createUserManager(settings); - AuthenticationService.instance = new OidcAuthorizeService(userManager); + this._initialized = new Promise(async (resolve, reject) => { + try { + const userManager = await this.createUserManager(settings); + AuthenticationService.instance = new OidcAuthorizeService(userManager); + resolve(); + } catch (e) { + reject(e); + } + }); } + + await this._initialized; } public static getUser() { diff --git a/src/Components/WebAssembly/WebAssembly.Authentication/src/Interop/package.json b/src/Components/WebAssembly/WebAssembly.Authentication/src/Interop/package.json index b0ae30371739..dd40f447edc6 100644 --- a/src/Components/WebAssembly/WebAssembly.Authentication/src/Interop/package.json +++ b/src/Components/WebAssembly/WebAssembly.Authentication/src/Interop/package.json @@ -1,4 +1,5 @@ { + "private": true, "scripts": { "build": "npm run build:release", "build:release": "webpack --mode production --env.production --env.configuration=Release",