'How to get access token in LeftNavigation in Shared folder that was returned through using AddMsalAuthentication in program.cs for authentication
In Blazor WASM, I want to display or hide some of the menu based on user roles. For that I need Access Token once user authenticate and I will pass that token to Graph API to get user details.
I am using
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
options.ProviderOptions.DefaultAccessTokenScopes.Add("https://graph.microsoft.com/User.Read");
options.ProviderOptions.LoginMode = "redirect";
});
in program.cs file to authenticate the user.
if i use below code on index.razor page, i am getting the token
var tokenResult = await AuthenticationService.RequestAccessToken();
if (tokenResult.TryGetToken(out var token))
{
-----
}
but i want that token on LeftNavigation.razor in shared folder, so that i can show or hide the menu as per user access rights.
Error after adding suggesting solution
Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: Object reference not set to an instance of an object. System.NullReferenceException: Object reference not set to an instance of an object. at Test.Web.Shared.LeftNavigation.OnInitialized() in C:\Users\pgoel\source\repos\Test\Test.Web\Shared\LeftNavigation.razor.cs:line 78 at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
Below is Program.cs file
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Test.SharedServices;
using Test.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.Authentication.WebAssembly.Msal;
using System.Net.Http;
using Test.Web.Data;
using Toolbelt.Blazor.Extensions.DependencyInjection;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddTelerikBlazor();
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
//graph api
builder.Services.AddHttpClient("GraphAPI",
client => client.BaseAddress = new Uri("https://graph.microsoft.com"))
.AddHttpMessageHandler<GraphAPIAuthorizationMessageHandler>();
// adding CustomAuthorizationMessageHandler
builder.Services.AddScoped<CustomAuthorizationMessageHandler>();
builder.Services.AddHttpClient("Test API", (sp, client) =>
{
client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
client.EnableIntercept(sp);
}).AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
builder.Services.AddScoped(sp =>
sp.GetRequiredService<IHttpClientFactory>().CreateClient("Test API"));
builder.Services.AddHttpClientInterceptor();
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
options.ProviderOptions.DefaultAccessTokenScopes.Add("https://graph.microsoft.com/User.Read");
options.ProviderOptions.LoginMode = "redirect";
});
builder.Services.AddGraphClient("https://graph.microsoft.com/User.Read");
builder.Services.AddScoped<HttpInterceptorService>();
builder.Services.AddScoped<GraphAPIAuthorizationMessageHandler>();
builder.Services.AddAuthorizationCore();
builder.Services.AddBlazoredLocalStorage();
var host = builder.Build();
var authenticationService = host.Services.GetRequiredService<UserAuth>();
await authenticationService.Initialize();
await builder.Build().RunAsync();
Solution 1:[1]
You should be able to do something like this in NavMenu
to trigger a re-render when the Authentication State changes:
@inject AuthenticationStateProvider authenticationStateProvider
@implements IDisposable
....
@code {
private ClaimsPrincipal user = new ClaimsPrincipal();
protected override void OnInitialized()
=> this.authenticationStateProvider.AuthenticationStateChanged += this.OnStateChanged;
private async void OnStateChanged(Task<AuthenticationState> state)
{
var authState = await state;
this.user = authState.User;
await this.InvokeAsync(this.StateHasChanged);
}
public void Dispose()
=> this.authenticationStateProvider.AuthenticationStateChanged -= this.OnStateChanged;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | MrC aka Shaun Curtis |