[Blazor][Wasm] Auth cleanups (#20587)

* Avoid using query parameter when passing messages to the error UI.
* Adds an additional parameter to automatically perform the redirect.
* Fix provisioning additional tokens in MACWA.
* Fix create solution with spaces
* Cleanup Msal startup APIs.
* Rename UserFactory -> AccountClaimsPrincipalFactory
This commit is contained in:
Javier Calvarro Nelson 2020-04-07 01:07:17 +02:00 committed by GitHub
parent 3224092fdd
commit f34ef732d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 88 additions and 66 deletions

View File

@ -22,7 +22,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
/// <param name="configure">A callback to configure the <see cref="RemoteAuthenticationOptions{MsalProviderOptions}"/>.</param>
/// <returns>The <see cref="IServiceCollection"/>.</returns>
public static IServiceCollection AddMsalAuthentication(this IServiceCollection services, Action<RemoteAuthenticationOptions<MsalProviderOptions>> configure)
public static IRemoteAuthenticationBuilder<RemoteAuthenticationState, RemoteUserAccount> AddMsalAuthentication(this IServiceCollection services, Action<RemoteAuthenticationOptions<MsalProviderOptions>> configure)
{
return AddMsalAuthentication<RemoteAuthenticationState>(services, configure);
}
@ -34,11 +34,10 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
/// <param name="configure">A callback to configure the <see cref="RemoteAuthenticationOptions{MsalProviderOptions}"/>.</param>
/// <returns>The <see cref="IServiceCollection"/>.</returns>
public static IServiceCollection AddMsalAuthentication<TRemoteAuthenticationState>(this IServiceCollection services, Action<RemoteAuthenticationOptions<MsalProviderOptions>> configure)
public static IRemoteAuthenticationBuilder<TRemoteAuthenticationState, RemoteUserAccount> AddMsalAuthentication<TRemoteAuthenticationState>(this IServiceCollection services, Action<RemoteAuthenticationOptions<MsalProviderOptions>> configure)
where TRemoteAuthenticationState : RemoteAuthenticationState, new()
{
AddMsalAuthentication<TRemoteAuthenticationState, RemoteUserAccount>(services, configure);
return services;
return AddMsalAuthentication<TRemoteAuthenticationState, RemoteUserAccount>(services, configure);
}
/// <summary>
@ -49,14 +48,24 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
/// <param name="configure">A callback to configure the <see cref="RemoteAuthenticationOptions{MsalProviderOptions}"/>.</param>
/// <returns>The <see cref="IServiceCollection"/>.</returns>
public static IServiceCollection AddMsalAuthentication<TRemoteAuthenticationState, TAccount>(this IServiceCollection services, Action<RemoteAuthenticationOptions<MsalProviderOptions>> configure)
public static IRemoteAuthenticationBuilder<TRemoteAuthenticationState, TAccount> AddMsalAuthentication<TRemoteAuthenticationState, TAccount>(this IServiceCollection services, Action<RemoteAuthenticationOptions<MsalProviderOptions>> configure)
where TRemoteAuthenticationState : RemoteAuthenticationState, new()
where TAccount : RemoteUserAccount
{
services.AddRemoteAuthentication<RemoteAuthenticationState, TAccount, MsalProviderOptions>(configure);
services.AddRemoteAuthentication<TRemoteAuthenticationState, TAccount, MsalProviderOptions>(configure);
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<RemoteAuthenticationOptions<MsalProviderOptions>>, MsalDefaultOptionsConfiguration>());
return services;
return new MsalRemoteAuthenticationBuilder<TRemoteAuthenticationState, TAccount>(services);
}
}
internal class MsalRemoteAuthenticationBuilder<TRemoteAuthenticationState, TRemoteUserAccount> : IRemoteAuthenticationBuilder<TRemoteAuthenticationState, TRemoteUserAccount>
where TRemoteAuthenticationState : RemoteAuthenticationState, new()
where TRemoteUserAccount : RemoteUserAccount
{
public MsalRemoteAuthenticationBuilder(IServiceCollection services) => Services = services;
public IServiceCollection Services { get; }
}
}

View File

@ -332,8 +332,8 @@ export class AuthenticationService {
return AuthenticationService.instance.getUser();
}
public static getAccessToken() {
return AuthenticationService.instance.getAccessToken();
public static getAccessToken(options: AccessTokenRequestOptions) {
return AuthenticationService.instance.getAccessToken(options);
}
public static signIn(state: unknown) {

View File

@ -23,9 +23,9 @@ namespace Microsoft.Extensions.DependencyInjection
this IRemoteAuthenticationBuilder<TRemoteAuthenticationState, TAccount> builder)
where TRemoteAuthenticationState : RemoteAuthenticationState, new()
where TAccount : RemoteUserAccount
where TUserFactory : UserFactory<TAccount>
where TUserFactory : AccountClaimsPrincipalFactory<TAccount>
{
builder.Services.Replace(ServiceDescriptor.Scoped<UserFactory<TAccount>, TUserFactory>());
builder.Services.Replace(ServiceDescriptor.Scoped<AccountClaimsPrincipalFactory<TAccount>, TUserFactory>());
return builder;
}
@ -40,7 +40,7 @@ namespace Microsoft.Extensions.DependencyInjection
public static IRemoteAuthenticationBuilder<TRemoteAuthenticationState, RemoteUserAccount> AddUserFactory<TRemoteAuthenticationState, TUserFactory>(
this IRemoteAuthenticationBuilder<TRemoteAuthenticationState, RemoteUserAccount> builder)
where TRemoteAuthenticationState : RemoteAuthenticationState, new()
where TUserFactory : UserFactory<RemoteUserAccount> => builder.AddUserFactory<TRemoteAuthenticationState, RemoteUserAccount, TUserFactory>();
where TUserFactory : AccountClaimsPrincipalFactory<RemoteUserAccount> => builder.AddUserFactory<TRemoteAuthenticationState, RemoteUserAccount, TUserFactory>();
/// <summary>
/// Replaces the existing <see cref="UserFactory{TAccount}"/> with the user factory defined by <typeparamref name="TUserFactory"/>.
@ -50,6 +50,6 @@ namespace Microsoft.Extensions.DependencyInjection
/// <returns>The <see cref="IRemoteAuthenticationBuilder{RemoteAuthenticationState, Account}"/>.</returns>
public static IRemoteAuthenticationBuilder<RemoteAuthenticationState, RemoteUserAccount> AddUserFactory<TUserFactory>(
this IRemoteAuthenticationBuilder<RemoteAuthenticationState, RemoteUserAccount> builder)
where TUserFactory : UserFactory<RemoteUserAccount> => builder.AddUserFactory<RemoteAuthenticationState, RemoteUserAccount, TUserFactory>();
where TUserFactory : AccountClaimsPrincipalFactory<RemoteUserAccount> => builder.AddUserFactory<RemoteAuthenticationState, RemoteUserAccount, TUserFactory>();
}
}

View File

@ -177,7 +177,6 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
await ProcessLogInCallback();
break;
case RemoteAuthenticationActions.LogInFailed:
_message = GetErrorMessage();
break;
case RemoteAuthenticationActions.Profile:
if (ApplicationPaths.RemoteProfilePath == null)
@ -209,7 +208,6 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
await ProcessLogOutCallback();
break;
case RemoteAuthenticationActions.LogOutFailed:
_message = GetErrorMessage();
break;
case RemoteAuthenticationActions.LogOutSucceeded:
break;
@ -235,8 +233,8 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
await NavigateToReturnUrl(GetReturnUrl(result.State, returnUrl));
break;
case RemoteAuthenticationStatus.Failure:
var uri = Navigation.ToAbsoluteUri($"{ApplicationPaths.LogInFailedPath}?message={Uri.EscapeDataString(result.ErrorMessage)}").ToString();
await NavigateToReturnUrl(uri);
_message = result.ErrorMessage;
Navigation.NavigateTo(ApplicationPaths.LogInFailedPath);
break;
case RemoteAuthenticationStatus.OperationCompleted:
default:
@ -297,8 +295,8 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
case RemoteAuthenticationStatus.OperationCompleted:
break;
case RemoteAuthenticationStatus.Failure:
var uri = Navigation.ToAbsoluteUri($"{ApplicationPaths.LogOutFailedPath}?message={Uri.EscapeDataString(result.ErrorMessage)}").ToString();
await NavigateToReturnUrl(uri);
_message = result.ErrorMessage;
Navigation.NavigateTo(ApplicationPaths.LogOutFailedPath);
break;
default:
throw new InvalidOperationException($"Invalid authentication result status.");
@ -363,8 +361,6 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
private ValueTask RedirectToProfile() => JS.InvokeVoidAsync("location.replace", Navigation.ToAbsoluteUri(ApplicationPaths.RemoteProfilePath).PathAndQuery);
private string GetErrorMessage() => QueryStringHelper.GetParameter(new Uri(Navigation.Uri).Query, "message");
private static void DefaultLogInFragment(RenderTreeBuilder builder)
{
builder.OpenElement(0, "p");

View File

@ -10,18 +10,21 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
/// </summary>
public class AccessTokenResult
{
private AccessToken _token;
private readonly AccessToken _token;
private readonly NavigationManager _navigation;
/// <summary>
/// Initializes a new instance of <see cref="AccessTokenResult"/>.
/// </summary>
/// <param name="status">The status of the result.</param>
/// <param name="token">The <see cref="AccessToken"/> in case it was successful.</param>
/// <param name="navigation">The <see cref="NavigationManager"/> to perform redirects.</param>
/// <param name="redirectUrl">The redirect uri to go to for provisioning the token.</param>
public AccessTokenResult(AccessTokenResultStatus status, AccessToken token, string redirectUrl)
public AccessTokenResult(AccessTokenResultStatus status, AccessToken token, NavigationManager navigation, string redirectUrl)
{
Status = status;
_token = token;
_navigation = navigation;
RedirectUrl = redirectUrl;
}
@ -53,5 +56,27 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
return false;
}
}
/// <summary>
/// Determines whether the token request was successful and makes the <see cref="AccessToken"/> available for use when it is.
/// </summary>
/// <param name="accessToken">The <see cref="AccessToken"/> if the request was successful.</param>
/// <param name="redirect">Whether or not to redirect automatically when failing to provision a token.</param>
/// <returns><c>true</c> when the token request is successful; <c>false</c> otherwise.</returns>
public bool TryGetToken(out AccessToken accessToken, bool redirect)
{
if (TryGetToken(out accessToken))
{
return true;
}
else
{
if (redirect)
{
_navigation.NavigateTo(RedirectUrl);
}
return false;
}
}
}
}

View File

@ -12,12 +12,12 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
/// Converts <see cref="RemoteUserAccount" /> into a <see cref="ClaimsPrincipal"/>.
/// </summary>
/// <typeparam name="TAccount">The account type.</typeparam>
public class UserFactory<TAccount> where TAccount : RemoteUserAccount
public class AccountClaimsPrincipalFactory<TAccount> where TAccount : RemoteUserAccount
{
private readonly IAccessTokenProviderAccessor _accessor;
#pragma warning disable PUB0001 // Pubternal type in public API
public UserFactory(IAccessTokenProviderAccessor accessor) => _accessor = accessor;
public AccountClaimsPrincipalFactory(IAccessTokenProviderAccessor accessor) => _accessor = accessor;
/// <summary>
/// Gets or sets the <see cref="IAccessTokenProvider"/>.

View File

@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
/// <summary>
/// Gets the <see cref="UserFactory{TAccount}"/> to map accounts to <see cref="ClaimsPrincipal"/>.
/// </summary>
protected UserFactory<TAccount> UserFactory { get; }
protected AccountClaimsPrincipalFactory<TAccount> UserFactory { get; }
/// <summary>
/// Gets the options for the underlying JavaScript library handling the authentication operations.
@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
IJSRuntime jsRuntime,
IOptions<RemoteAuthenticationOptions<TProviderOptions>> options,
NavigationManager navigation,
UserFactory<TAccount> userFactory)
AccountClaimsPrincipalFactory<TAccount> userFactory)
{
JsRuntime = jsRuntime;
Navigation = navigation;
@ -159,7 +159,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
result.RedirectUrl = redirectUrl.ToString();
}
return new AccessTokenResult(parsedStatus, result.Token, result.RedirectUrl);
return new AccessTokenResult(parsedStatus, result.Token, Navigation, result.RedirectUrl);
}
/// <inheritdoc />
@ -184,7 +184,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
result.RedirectUrl = redirectUrl.ToString();
}
return new AccessTokenResult(parsedStatus, result.Token, result.RedirectUrl);
return new AccessTokenResult(parsedStatus, result.Token, Navigation, result.RedirectUrl);
}
private Uri GetRedirectUrl(string customReturnUrl)

View File

@ -47,7 +47,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.TryAddScoped<IAccessTokenProviderAccessor, AccessTokenProviderAccessor>();
services.TryAddScoped<SignOutSessionStateManager>();
services.TryAddScoped<UserFactory<TAccount>>();
services.TryAddScoped<AccountClaimsPrincipalFactory<TAccount>>();
return new RemoteAuthenticationBuilder<TRemoteAuthenticationState, TAccount>(services);
}

View File

@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
testJsRuntime,
options,
new TestNavigationManager(),
new UserFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
new AccountClaimsPrincipalFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
var state = new RemoteAuthenticationState();
testJsRuntime.SignInResult = new InternalRemoteAuthenticationResult<RemoteAuthenticationState>
@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
testJsRuntime,
options,
new TestNavigationManager(),
new UserFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
new AccountClaimsPrincipalFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
var state = new RemoteAuthenticationState();
testJsRuntime.SignInResult = new InternalRemoteAuthenticationResult<RemoteAuthenticationState>
@ -86,7 +86,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
testJsRuntime,
options,
new TestNavigationManager(),
new UserFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
new AccountClaimsPrincipalFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
var state = new RemoteAuthenticationState();
testJsRuntime.CompleteSignInResult = new InternalRemoteAuthenticationResult<RemoteAuthenticationState>
@ -117,7 +117,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
testJsRuntime,
options,
new TestNavigationManager(),
new UserFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
new AccountClaimsPrincipalFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
var state = new RemoteAuthenticationState();
testJsRuntime.CompleteSignInResult = new InternalRemoteAuthenticationResult<RemoteAuthenticationState>
@ -144,7 +144,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
testJsRuntime,
options,
new TestNavigationManager(),
new UserFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
new AccountClaimsPrincipalFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
var state = new RemoteAuthenticationState();
testJsRuntime.SignOutResult = new InternalRemoteAuthenticationResult<RemoteAuthenticationState>
@ -175,7 +175,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
testJsRuntime,
options,
new TestNavigationManager(),
new UserFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
new AccountClaimsPrincipalFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
var state = new RemoteAuthenticationState();
testJsRuntime.SignOutResult = new InternalRemoteAuthenticationResult<RemoteAuthenticationState>
@ -202,7 +202,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
testJsRuntime,
options,
new TestNavigationManager(),
new UserFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
new AccountClaimsPrincipalFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
var state = new RemoteAuthenticationState();
testJsRuntime.CompleteSignOutResult = new InternalRemoteAuthenticationResult<RemoteAuthenticationState>
@ -233,7 +233,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
testJsRuntime,
options,
new TestNavigationManager(),
new UserFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
new AccountClaimsPrincipalFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
var state = new RemoteAuthenticationState();
testJsRuntime.CompleteSignOutResult = new InternalRemoteAuthenticationResult<RemoteAuthenticationState>
@ -260,7 +260,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
testJsRuntime,
options,
new TestNavigationManager(),
new UserFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
new AccountClaimsPrincipalFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
var state = new RemoteAuthenticationState();
testJsRuntime.GetAccessTokenResult = new InternalAccessTokenResult
@ -298,7 +298,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
testJsRuntime,
options,
new TestNavigationManager(),
new UserFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
new AccountClaimsPrincipalFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
var state = new RemoteAuthenticationState();
testJsRuntime.GetAccessTokenResult = new InternalAccessTokenResult
@ -338,7 +338,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
testJsRuntime,
options,
new TestNavigationManager(),
new UserFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
new AccountClaimsPrincipalFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
var state = new RemoteAuthenticationState();
testJsRuntime.GetAccessTokenResult = new InternalAccessTokenResult
@ -379,7 +379,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
testJsRuntime,
options,
new TestNavigationManager(),
new UserFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
new AccountClaimsPrincipalFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()));
testJsRuntime.GetUserResult = default;
@ -571,7 +571,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
}
}
internal class TestUserFactory : UserFactory<CoolRoleAccount>
internal class TestUserFactory : AccountClaimsPrincipalFactory<CoolRoleAccount>
{
public TestUserFactory(IAccessTokenProviderAccessor accessor) : base(accessor)
{

View File

@ -113,10 +113,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
await renderer.Dispatcher.InvokeAsync<object>(() => remoteAuthenticator.SetParametersAsync(parameters));
// Assert
Assert.Equal(
"https://www.example.com/base/authentication/login-failed?message=There was an error trying to log in",
jsRuntime.LastInvocation.args[0]);
Assert.Equal("https://www.example.com/base/authentication/login-failed", remoteAuthenticator.Navigation.Uri.ToString());
}
[Fact]
@ -368,9 +365,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
await renderer.Dispatcher.InvokeAsync<object>(() => remoteAuthenticator.SetParametersAsync(parameters));
// Assert
Assert.Equal(
"https://www.example.com/base/authentication/logout-failed?message=There was an error trying to log out",
jsRuntime.LastInvocation.args[0]);
Assert.Equal("https://www.example.com/base/authentication/logout-failed", remoteAuthenticator.Navigation.Uri.ToString());
}
[Fact]
@ -603,7 +598,8 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
{
public TestNavigationManager(string baseUrl, string currentUrl) => Initialize(baseUrl, currentUrl);
protected override void NavigateToCore(string uri, bool forceLoad) => Uri = uri;
protected override void NavigateToCore(string uri, bool forceLoad)
=> Uri = System.Uri.IsWellFormedUriString(uri, UriKind.Absolute) ? uri : new Uri(new Uri(BaseUri), uri).ToString();
}
private class TestSignOutSessionStateManager : SignOutSessionStateManager
@ -667,7 +663,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
IJSRuntime jsRuntime,
IOptions<RemoteAuthenticationOptions<OidcProviderOptions>> options,
TestNavigationManager navigationManager) :
base(jsRuntime, options, navigationManager, new UserFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()))
base(jsRuntime, options, navigationManager, new AccountClaimsPrincipalFactory<RemoteUserAccount>(Mock.Of<IAccessTokenProviderAccessor>()))
{
}

View File

@ -47,14 +47,10 @@ else
var tokenResult = await AuthenticationService.RequestAccessToken();
if (tokenResult.TryGetToken(out var token))
if (tokenResult.TryGetToken(out var token, redirect: true))
{
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.Value}");
forecasts = await httpClient.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
}
else
{
Navigation.NavigateTo(tokenResult.RedirectUrl);
}
}
}

View File

@ -11,7 +11,7 @@ using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;
namespace Wasm.Authentication.Client
{
public class PreferencesUserFactory : UserFactory<OidcAccount>
public class PreferencesUserFactory : AccountClaimsPrincipalFactory<OidcAccount>
{
private readonly HttpClient _httpClient;

View File

@ -6,6 +6,9 @@
<!--#if PWA -->
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
<!--#endif -->
<!--#if Hosted -->
<AssemblyName Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">`$(AssemblyName.Replace(' ', '_'))</AssemblyName>
<!--#endif -->
</PropertyGroup>
<ItemGroup>

View File

@ -2,11 +2,12 @@
<PropertyGroup>
<TargetFramework>${DefaultNetCoreTargetFramework}</TargetFramework>
<UserSecretsId Condition="'$(IndividualAuth)' == 'True' OR '$(OrganizationalAuth)' == 'True'">BlazorWasm-CSharp.Server-53bc9b9d-9d6a-45d4-8429-2a2761773502</UserSecretsId>
<UserSecretsId Condition="'$(IndividualAuth)' == 'True' OR '$(OrganizationalAuth)' == 'True'">ComponentsWebAssembly-CSharp.Server-53bc9b9d-9d6a-45d4-8429-2a2761773502</UserSecretsId>
<WebProject_DirectoryAccessLevelKey Condition="'$(OrganizationalAuth)' == 'True' AND '$(OrgReadAccess)' != 'True'">0</WebProject_DirectoryAccessLevelKey>
<WebProject_DirectoryAccessLevelKey Condition="'$(OrganizationalAuth)' == 'True' AND '$(OrgReadAccess)' == 'True'">1</WebProject_DirectoryAccessLevelKey>
<NoDefaultLaunchSettingsFile Condition="'$(ExcludeLaunchSettings)' == 'True'">True</NoDefaultLaunchSettingsFile>
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">BlazorWasm-CSharp.Server</RootNamespace>
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">ComponentsWebAssembly-CSharp.Server</RootNamespace>
<AssemblyName Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">`$(AssemblyName.Replace(' ', '_'))</AssemblyName>
</PropertyGroup>
<ItemGroup>

View File

@ -1,4 +1,4 @@
@page "/fetchdata"
@page "/fetchdata"
@*#if (!NoAuth && Hosted)
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@ -60,15 +60,11 @@ else
var tokenResult = await AuthenticationService.RequestAccessToken();
if (tokenResult.TryGetToken(out var token))
if (tokenResult.TryGetToken(out var token, redirect: true))
{
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.Value}");
forecasts = await httpClient.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
}
else
{
Navigation.NavigateTo(tokenResult.RedirectUrl);
}
#else
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");