- Creating a Visual Studio 2022 Project using the Blazor Server App Template and then use the following settings for the Blazor Server App.
After the solution is created I edit the appsettings.json file that that is included in the project with my EntraID application information.
Build and Run the application.
The application requests authentication via my EntraID tenant. I sign in successfully.
On have the following Code Block on my main razor page:
@code {
private string? authMessage;
private string? surname;
private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();
private async Task GetClaimsPrincipalData()
{
var authState = await AuthenticationStateProvider
.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity is not null && user.Identity.IsAuthenticated)
{
authMessage = $"{user.Identity.Name} is authenticated.";
claims = user.Claims;
surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
}
else
{
authMessage = "The user is NOT authenticated.";
}
}
When invoked GetClaimsPrincipalData Task successfully returns the an Authentication State with all of the claims in it. In my program.cs file the template added the following line to add the Authentication.
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
I am successfully authenticated to my EntraID App and I have a valid Authentication state. What I attempting to do is make a Graph Call using this already existing authentication state.
This approach may be completely flawed. My goal is to be able make the authenticated graph calls.
Using the example from learn.microsoft.com the (cited below in my original post) I was attempting to add a graph client so my razor pages could make Microsoft Graph Calls.
I am using the following Guide:
To create a Blazor Application that can access Microsoft Graph. As described in this article I have created the GraphClientExtensions.cs method, and I have Added the AddGraphClient using the WebApplication Builder.
The solution builds without errors. However, at runtime the appended error is thrown. Would anyone have some guidance on what I have missed in configuring this application?
Thanks for any guidance you may have.
Using Jalpa's suggestion, I added the builder.Services.AddMsalAuthentication call to the program.cs. Here is the complete program.cs from my Blazor Project.
using BlazorWithGraphSandbox.Data;
using BlazorWithGraphSandbox.Extensions;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
// Create Web Application Builder
var builder = WebApplication.CreateBuilder(args);
// Add authentication providers
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddMsalAuthentication<RemoteAuthenticationState, RemoteUserAccount>
(options => { builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication); });
// Add the default authorization policy
builder.Services.AddAuthorization(options =>
{
options.FallbackPolicy = options.DefaultPolicy;
});
// Add the GraphClient Extension Service
var baseUrl = builder.Configuration.GetSection("MicrosoftGraph")["BaseUrl"];
var scopes = builder.Configuration.GetSection("MicrosoftGraph:Scopes").Get<List<string>>();
builder.Services.AddGraphClient(baseUrl, scopes);
// Add Controllers
builder.Services.AddControllersWithViews()
.AddMicrosoftIdentityUI();
// Add the Razor Pages
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor().AddMicrosoftIdentityConsentHandler();
// Build the Web Application
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
Again this compiles but at runtime the following error is thrown:
InvalidOperationException: JavaScript interop calls cannot be issued at this time. This is because the component is being statically rendered. When prerendering is enabled, JavaScript interop calls can only be performed during the OnAfterRenderAsync lifecycle method.
This line is called out as problematic from the _Host.cshtml:
BlazorWIthGraphSandbox.Pages.Pages__Host.b__14_1() in _Host.cshtml
<component type="typeof(App)" render-mode="ServerPrerendered" />
Changing the render-mode to "Server" causes a blank page to be rendered.
Original Appended Error (Prior to Japal's suggested fix)
System.AggregateException HResult=0x80131500 Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.Kiota.Abstractions.Authentication.IAuthenticationProvider Lifetime: Scoped ImplementationType: BlazorGraphSandbox.Extensions.GraphClientExtensions+GraphAuthenticationProvider': Unable to resolve service for type 'Microsoft.AspNetCore.Components.WebAssembly.Authentication.IAccessTokenProvider' while attempting to activate 'BlazorGraphSandbox.Extensions.GraphClientExtensions+GraphAuthenticationProvider'.) Source=Microsoft.Extensions.DependencyInjection StackTrace: at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options) at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options) at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build() at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build() at BlazorGraphSandbox.Program.Main(String[] args) in BlazorGraphSandbox\Program.cs:line 27
This exception was originally thrown at this call stack: Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier, System.Type, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain, System.Reflection.ParameterInfo[], bool) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Microsoft.Extensions.DependencyInjection.ServiceLookup.ResultCache, Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier, System.Type, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Microsoft.Extensions.DependencyInjection.ServiceDescriptor, Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain, int) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Microsoft.Extensions.DependencyInjection.ServiceDescriptor, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain) Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(Microsoft.Extensions.DependencyInjection.ServiceDescriptor)
Inner Exception 1: InvalidOperationException: Error while validating the service descriptor 'ServiceType: Microsoft.Kiota.Abstractions.Authentication.IAuthenticationProvider Lifetime: Scoped ImplementationType: BlazorGraphSandbox.Extensions.GraphClientExtensions+GraphAuthenticationProvider': Unable to resolve service for type 'Microsoft.AspNetCore.Components.WebAssembly.Authentication.IAccessTokenProvider' while attempting to activate 'BlazorGraphSandbox.Extensions.GraphClientExtensions+GraphAuthenticationProvider'.
Inner Exception 2: InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Components.WebAssembly.Authentication.IAccessTokenProvider' while attempting to activate 'BlazorGraphSandbox.Extensions.GraphClientExtensions+GraphAuthenticationProvider'.
