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/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",
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;
}
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
+ {
+