diff --git a/src/Components/WebAssembly/Authentication.Msal/src/Models/MsalProviderOptions.cs b/src/Components/WebAssembly/Authentication.Msal/src/Models/MsalProviderOptions.cs
index 20af240d0502..8fa6b8b29249 100644
--- a/src/Components/WebAssembly/Authentication.Msal/src/Models/MsalProviderOptions.cs
+++ b/src/Components/WebAssembly/Authentication.Msal/src/Models/MsalProviderOptions.cs
@@ -24,7 +24,12 @@ public class MsalProviderOptions
///
/// Gets or sets the msal.js cache options.
///
- public MsalCacheOptions Cache { get; set; }
+ public MsalCacheOptions Cache { get; set; } = new MsalCacheOptions
+ {
+ // This matches the defaults in msal.js
+ CacheLocation = "sessionStorage",
+ StoreAuthStateInCookie = false
+ };
///
/// Gets or set the list of default access tokens scopes to provision during the sign-in flow.
diff --git a/src/Components/WebAssembly/Authentication.Msal/src/MsalDefaultOptionsConfiguration.cs b/src/Components/WebAssembly/Authentication.Msal/src/MsalDefaultOptionsConfiguration.cs
index b0dc7ffa0707..c98c6f871e82 100644
--- a/src/Components/WebAssembly/Authentication.Msal/src/MsalDefaultOptionsConfiguration.cs
+++ b/src/Components/WebAssembly/Authentication.Msal/src/MsalDefaultOptionsConfiguration.cs
@@ -40,11 +40,6 @@ public void Configure(RemoteAuthenticationOptions options)
}
options.ProviderOptions.Authentication.NavigateToLoginRequestUrl = false;
- options.ProviderOptions.Cache = new MsalCacheOptions
- {
- CacheLocation = "localStorage",
- StoreAuthStateInCookie = true
- };
}
public void PostConfigure(string name, RemoteAuthenticationOptions options)
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 a0f6a9b3002b..919ee1d5e092 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/Options/OidcProviderOptions.cs b/src/Components/WebAssembly/WebAssembly.Authentication/src/Options/OidcProviderOptions.cs
index 9c1c74933ca4..56859689ed01 100644
--- a/src/Components/WebAssembly/WebAssembly.Authentication/src/Options/OidcProviderOptions.cs
+++ b/src/Components/WebAssembly/WebAssembly.Authentication/src/Options/OidcProviderOptions.cs
@@ -16,6 +16,11 @@ public class OidcProviderOptions
///
public string Authority { get; set; }
+ ///
+ /// Gets or sets the metadata url of the oidc provider.
+ ///
+ public string MetadataUrl { get; set; }
+
///
/// Gets or sets the client of the application.
///
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/Components/WebAssembly/testassets/Wasm.Authentication.Server/Startup.cs b/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Startup.cs
index 56e6cb43e0d3..2a8f10d22585 100644
--- a/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Startup.cs
+++ b/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Startup.cs
@@ -52,8 +52,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseRouting();
- app.UseAuthentication();
app.UseIdentityServer();
+ app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
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
+ {
+