using System.Security.Claims; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.Identity.Web; using Microsoft.Identity.Web.UI; WebApplicationBuilder builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services .AddRazorComponents() .AddInteractiveServerComponents(); builder.Services.AddCascadingAuthenticationState(); builder.Services .AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(options => { builder.Configuration.Bind("AzureAdB2C", options); options.Events = new OpenIdConnectEvents { OnTicketReceived = async context => { if (context.Principal != null) { IHttpContextAccessor httpContextAccessor = context.HttpContext.RequestServices.GetRequiredService(); ITokenAcquisition tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService(); async Task GetAccessToken() { try { ClaimsPrincipal user = context.Principal; if (user?.Identity == null || !user.Identity.IsAuthenticated) { return null; } string scope = "https://.onmicrosoft.com//user.read"; // Get access token for user string accessToken = await tokenAcquisition.GetAccessTokenForUserAsync([scope], user: user); // Check if the access token is null or empty if (string.IsNullOrWhiteSpace(accessToken)) { return null; } return accessToken; } catch (Exception ex) { return null; } } // Get access token string accessToken = await GetAccessToken(); // Set the user on the HTTP context httpContextAccessor.HttpContext.User = context.Principal; // Yield the task await Task.Yield(); } }, OnRedirectToIdentityProvider = async context => { // Invoked before redirecting to the identity provider to authenticate. // This can be used to set ProtocolMessage.State // that will be persisted through the authentication process. // The ProtocolMessage can also be used to add or customize // parameters sent to the identity provider. // Yield the task await Task.Yield(); }, OnSignedOutCallbackRedirect = async context => { // Handle the sign-out callback context.HttpContext.Response.Redirect(context.Options.SignedOutRedirectUri); // Suppress the default redirect. context.HandleResponse(); IHttpContextAccessor httpContextAccessor = context.HttpContext.RequestServices.GetRequiredService(); // Clear the user from the HTTP context httpContextAccessor.HttpContext.User = null; // Yield the task await Task.Yield(); }, OnAuthenticationFailed = async context => { // Yield the task await Task.Yield(); } }; }) .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); builder.Services.AddAuthenticationCore(); builder.Services.AddControllersWithViews().AddMicrosoftIdentityUI(); builder.Services.AddLocalization(options => options.ResourcesPath = nameof(Resources)); builder.Services.Configure(options => { options.SetDefaultCulture("en-GB") .AddSupportedCultures(["en-GB"]) .AddSupportedUICultures(["en-GB"]); }); builder.Services.AddServerSideBlazor().AddMicrosoftIdentityConsentHandler(); // Build the web application. WebApplication app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseWebAssemblyDebugging(); } else { app.UseExceptionHandler("/error", createScopeForErrors: true); // 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.UseAntiforgery(); app.UseRequestLocalization(); app.MapRazorComponents().AddInteractiveServerRenderMode(); app.Run();