How to get user name for Blazor server applications (EasyAuth)?

takeolexus 80 Reputation points
2023-09-21T06:31:02.0733333+00:00

I configured azure app service using EasyAuth.

I tried to get the user name in the article below, but the username was returned null.

The EasyAuth is working correctly.

https://learn.microsoft.com/en-us/aspnet/core/blazor/security/server/additional-scenarios?view=aspnetcore-7.0#circuit-handler-to-capture-users-for-custom-services

How do I get it??

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,557 questions
Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,578 questions
Azure App Service
Azure App Service
Azure App Service is a service used to create and deploy scalable, mission-critical web apps.
7,770 questions
{count} votes

Accepted answer
  1. JasonPan - MSFT 5,466 Reputation points Microsoft Vendor
    2023-09-25T14:42:05.67+00:00

    Hi @takeolexus,

    I have found a workaround for this issue, and I could share with you. And I am still waiting for app service expert's reply.

    Program.cs

    using BlazorServerEasyAuth.Data;
    using Microsoft.AspNetCore.Components;
    using Microsoft.AspNetCore.Components.Authorization;
    using Microsoft.AspNetCore.Components.Server;
    using Microsoft.AspNetCore.Components.Server.Circuits;
    using Microsoft.AspNetCore.Components.Web;
    using Microsoft.Extensions.DependencyInjection.Extensions;
    using Newtonsoft.Json.Linq;
    using System.Net;
    using System.Security.Claims;
    using System.Security.Principal;
    
    namespace BlazorServerEasyAuth
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                var builder = WebApplication.CreateBuilder(args);
    
                // Add services to the container.
                builder.Services.AddRazorPages();
                builder.Services.AddServerSideBlazor();
                builder.Services.AddSingleton<WeatherForecastService>();
    
                builder.Services.AddScoped<AuthenticationStateProvider, ServerAuthenticationStateProvider>();
    
                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.Use(async (context, next) =>
                {
                    // Create a user on current thread from provided header
                    if (context.Request.Headers.ContainsKey("X-MS-CLIENT-PRINCIPAL-ID"))
                    {
                        // Read headers from Azure
                        var azureAppServicePrincipalIdHeader = context.Request.Headers["X-MS-CLIENT-PRINCIPAL-ID"][0];
                        var azureAppServicePrincipalNameHeader = context.Request.Headers["X-MS-CLIENT-PRINCIPAL-NAME"][0];
    
                        #region extract claims via call /.auth/me
                        //invoke /.auth/me
                        var cookieContainer = new CookieContainer();
                        HttpClientHandler handler = new HttpClientHandler()
                        {
                            CookieContainer = cookieContainer
                        };
                        string uriString = $"{context.Request.Scheme}://{context.Request.Host}";
                        foreach (var c in context.Request.Cookies)
                        {
                            cookieContainer.Add(new Uri(uriString), new Cookie(c.Key, c.Value));
                        }
                        string jsonResult = string.Empty;
                        using (HttpClient client = new HttpClient(handler))
                        {
                            var res = await client.GetAsync($"{uriString}/.auth/me");
                            jsonResult = await res.Content.ReadAsStringAsync();
                        }
    
                        //parse json
                        var obj = JArray.Parse(jsonResult);
                        string user_id = obj[0]["user_id"].Value<string>(); //user_id
    
                        // Create claims id
                        List<Claim> claims = new List<Claim>();
                        foreach (var claim in obj[0]["user_claims"])
                        {
                            claims.Add(new Claim(claim["typ"].ToString(), claim["val"].ToString()));
                        }
    
                        // Set user in current context as claims principal
                        var identity = new GenericIdentity(azureAppServicePrincipalNameHeader);
                        identity.AddClaims(claims);
                        #endregion
    
                        // Set current thread user to identity
                        context.User = new GenericPrincipal(identity, null);
                    };
    
                    await next.Invoke();
                });
    
                app.UseRouting();
    
    
    
                app.MapBlazorHub();
                app.MapFallbackToPage("/_Host");
    
                app.Run();
            }
        }
    }
    

    Index.razor

    @page "/"
    @using System.Security.Claims;
    @inject AuthenticationStateProvider AuthenticationStateProvider
    
    <h1>Hello, @UserName!</h1>
    
    @code {
        private string? UserName;
    
        protected override async Task OnInitializedAsync()
        {
            var authenticationState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
            var user = authenticationState.User;
    
            if (user.Identity.IsAuthenticated)
            {
                // Find the user's name claim
                var userNameClaim = user.FindFirst(ClaimTypes.Name);
                if (userNameClaim != null)
                {
                    UserName = userNameClaim.Value;
                }
            }
        }
    }
    

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,
    Jason

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.