From 64fa32b23cce137561917a0c4a38789cbcc7323f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 11 May 2021 01:58:55 +0300 Subject: [PATCH] Resolved #8972: Blazor WASM: Support applications without authentication. --- .../Themes/Basic/AppWithoutAuth.razor | 14 ++++++ .../Web/Security/AbpComponentsClaimsCache.cs | 23 ++++++--- .../BasicThemeToolbarContributor.cs | 13 ++++- .../Themes/Basic/LoginDisplay.razor | 27 ++-------- .../Themes/Basic/LoginDisplay.razor.cs | 49 ++++++++++++++++--- .../AspNetCore/Components/AbpComponentBase.cs | 24 +++++++++ ...delRemoteServiceHttpClientAuthenticator.cs | 18 +++++-- 7 files changed, 124 insertions(+), 44 deletions(-) create mode 100644 framework/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/AppWithoutAuth.razor diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/AppWithoutAuth.razor b/framework/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/AppWithoutAuth.razor new file mode 100644 index 0000000000..e9bf522595 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/AppWithoutAuth.razor @@ -0,0 +1,14 @@ +@using Microsoft.Extensions.Options +@using Volo.Abp.AspNetCore.Components.Web.Theming.Routing +@inject IOptions RouterOptions + + + + + + +

Sorry, there's nothing at this address.

+
+
+
\ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs index 281b2f7ded..787bf5cb6e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs @@ -1,5 +1,6 @@ using System.Security.Claims; using System.Threading.Tasks; +using JetBrains.Annotations; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; @@ -14,21 +15,29 @@ namespace Volo.Abp.AspNetCore.Components.Web.Security { public ClaimsPrincipal Principal { get; private set; } + [CanBeNull] private readonly AuthenticationStateProvider _authenticationStateProvider; - public AbpComponentsClaimsCache(IClientScopeServiceProviderAccessor clientScopeServiceProviderAccessor) + public AbpComponentsClaimsCache( + IClientScopeServiceProviderAccessor serviceProviderAccessor) { - _authenticationStateProvider = clientScopeServiceProviderAccessor.ServiceProvider.GetRequiredService(); - _authenticationStateProvider.AuthenticationStateChanged += async (task) => + _authenticationStateProvider = serviceProviderAccessor.ServiceProvider.GetService(); + if (_authenticationStateProvider != null) { - Principal = (await task).User; - }; + _authenticationStateProvider.AuthenticationStateChanged += async (task) => + { + Principal = (await task).User; + }; + } } public virtual async Task InitializeAsync() { - var authenticationState = await _authenticationStateProvider.GetAuthenticationStateAsync(); - Principal = authenticationState.User; + if (_authenticationStateProvider != null) + { + var authenticationState = await _authenticationStateProvider.GetAuthenticationStateAsync(); + Principal = authenticationState.User; + } } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/BasicThemeToolbarContributor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/BasicThemeToolbarContributor.cs index ab2a73a8dd..b853670d39 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/BasicThemeToolbarContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/BasicThemeToolbarContributor.cs @@ -1,7 +1,10 @@ using System.Threading.Tasks; +using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic; using Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars; using Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic; +using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme { @@ -12,7 +15,15 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme if (context.Toolbar.Name == StandardToolbars.Main) { context.Toolbar.Items.Add(new ToolbarItem(typeof(LanguageSwitch))); - context.Toolbar.Items.Add(new ToolbarItem(typeof(LoginDisplay))); + + //TODO: Can we find a different way to understand if authentication was configured or not? + var authenticationStateProvider = context.ServiceProvider + .GetService(); + + if (authenticationStateProvider != null) + { + context.Toolbar.Items.Add(new ToolbarItem(typeof(LoginDisplay))); + } } return Task.CompletedTask; diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor index eebfb501a5..1b084a60ce 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor @@ -1,13 +1,12 @@ -@using Microsoft.AspNetCore.Components.WebAssembly.Authentication -@using Microsoft.Extensions.Localization +@using Microsoft.Extensions.Localization @using Volo.Abp.Users @using Volo.Abp.MultiTenancy @using global::Localization.Resources.AbpUi +@inherits AbpComponentBase @inject ICurrentUser CurrentUser @inject ICurrentTenant CurrentTenant @inject IJSRuntime JsRuntime @inject NavigationManager Navigation -@inject SignOutSessionStateManager SignOutManager @inject IStringLocalizer UiLocalizer @@ -38,24 +37,4 @@ @UiLocalizer["Login"] - -@code{ - - private async Task NavigateToAsync(string uri, string target = null) - { - if (target == "_blank") - { - await JsRuntime.InvokeVoidAsync("open", uri, target); - } - else - { - Navigation.NavigateTo(uri); - } - } - - private async Task BeginSignOut() - { - await SignOutManager.SetSignOutState(); - await NavigateToAsync("authentication/logout"); - } -} + \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs index addef3dc80..0ec9caa23c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs @@ -1,8 +1,11 @@ using System; using System.Threading.Tasks; +using JetBrains.Annotations; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Routing; +using Microsoft.AspNetCore.Components.WebAssembly.Authentication; +using Microsoft.JSInterop; using Volo.Abp.UI.Navigation; namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic @@ -11,23 +14,32 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic { [Inject] protected IMenuManager MenuManager { get; set; } - - [Inject] - protected AuthenticationStateProvider AuthenticationStateProvider { get; set; } - protected ApplicationMenu Menu { get; set; } + [CanBeNull] + protected AuthenticationStateProvider AuthenticationStateProvider; + + [CanBeNull] + protected SignOutSessionStateManager SignOutManager; + protected ApplicationMenu Menu { get; set; } + protected override async Task OnInitializedAsync() { Menu = await MenuManager.GetAsync(StandardMenus.User); Navigation.LocationChanged += OnLocationChanged; - AuthenticationStateProvider.AuthenticationStateChanged += async (task) => + LazyGetService(ref AuthenticationStateProvider); + LazyGetService(ref SignOutManager); + + if (AuthenticationStateProvider != null) { - Menu = await MenuManager.GetAsync(StandardMenus.User); - await InvokeAsync(StateHasChanged); - }; + AuthenticationStateProvider.AuthenticationStateChanged += async (task) => + { + Menu = await MenuManager.GetAsync(StandardMenus.User); + await InvokeAsync(StateHasChanged); + }; + } } protected virtual void OnLocationChanged(object sender, LocationChangedEventArgs e) @@ -39,5 +51,26 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic { Navigation.LocationChanged -= OnLocationChanged; } + + private async Task NavigateToAsync(string uri, string target = null) + { + if (target == "_blank") + { + await JsRuntime.InvokeVoidAsync("open", uri, target); + } + else + { + Navigation.NavigateTo(uri); + } + } + + private async Task BeginSignOut() + { + if (SignOutManager != null) + { + await SignOutManager.SetSignOutState(); + await NavigateToAsync("authentication/logout"); + } + } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs index bc4db53002..163b2217fa 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs @@ -108,6 +108,18 @@ namespace Volo.Abp.AspNetCore.Components return reference; } + + protected TService LazyGetService(ref TService reference) => LazyGetService(typeof(TService), ref reference); + + protected TRef LazyGetService(Type serviceType, ref TRef reference) + { + if (reference == null) + { + reference = (TRef)ScopedServices.GetService(serviceType); + } + + return reference; + } protected TService LazyGetNonScopedRequiredService(ref TService reference) => LazyGetNonScopedRequiredService(typeof(TService), ref reference); @@ -120,6 +132,18 @@ namespace Volo.Abp.AspNetCore.Components return reference; } + + protected TService LazyGetNonScopedService(ref TService reference) => LazyGetNonScopedService(typeof(TService), ref reference); + + protected TRef LazyGetNonScopedService(Type serviceType, ref TRef reference) + { + if (reference == null) + { + reference = (TRef)NonScopedServices.GetService(serviceType); + } + + return reference; + } [Inject] protected IServiceProvider NonScopedServices { get; set; } diff --git a/framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo/Abp/Http/Client/IdentityModel/WebAssembly/AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator.cs b/framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo/Abp/Http/Client/IdentityModel/WebAssembly/AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator.cs index c86fc095c7..3f74918d98 100644 --- a/framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo/Abp/Http/Client/IdentityModel/WebAssembly/AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator.cs +++ b/framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo/Abp/Http/Client/IdentityModel/WebAssembly/AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator.cs @@ -1,6 +1,9 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using IdentityModel.Client; +using JetBrains.Annotations; using Microsoft.AspNetCore.Components.WebAssembly.Authentication; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; using Volo.Abp.Http.Client.Authentication; using Volo.Abp.IdentityModel; @@ -8,16 +11,18 @@ using Volo.Abp.IdentityModel; namespace Volo.Abp.Http.Client.IdentityModel.WebAssembly { [Dependency(ReplaceServices = true)] - public class AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator : IdentityModelRemoteServiceHttpClientAuthenticator + public class AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator + : IdentityModelRemoteServiceHttpClientAuthenticator { + [CanBeNull] protected IAccessTokenProvider AccessTokenProvider { get; } public AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator( IIdentityModelAuthenticationService identityModelAuthenticationService, - IAccessTokenProvider accessTokenProvider) + IServiceProvider serviceProvider) : base(identityModelAuthenticationService) { - AccessTokenProvider = accessTokenProvider; + AccessTokenProvider = serviceProvider.GetService(); } public override async Task Authenticate(RemoteServiceHttpClientAuthenticateContext context) @@ -37,6 +42,11 @@ namespace Volo.Abp.Http.Client.IdentityModel.WebAssembly protected virtual async Task GetAccessTokenFromAccessTokenProviderOrNullAsync() { + if (AccessTokenProvider == null) + { + return null; + } + var result = await AccessTokenProvider.RequestAccessToken(); if (result.Status != AccessTokenResultStatus.Success) {