Nikola Sevo
Nikola Sevo

Reputation: 285

Accessing signed in user in dotnet 3.1 with HttpContextAccessor

Okey, so i'm getting impatient here. :) I'm trying to access my signed in user through HttpContext.User by accessing the IHttpContextAccessor but no user is available, nor any claims. Dotnet core 3.1 is being used here. This is basically how I understand it: Sign in user with HttpContext.SignInAsync(... and then the context is available through the IHttpContextAccessor outside controllers. Now, the context is available but cant find any accessible user information from the signin. I do see that the cookies are correctly attached to the requests but there is some transformation not being done. Does anyone know what I am missing?

            //My controller action:

            var claimsIdentity = new ClaimsIdentity("Application");
            claimsIdentity.AddClaim(emailClaim);
            ... more claims

            await HttpContext.SignInAsync(
                "Application",
                new ClaimsPrincipal(claimsIdentity)
            );


            // Startup.cs:ConfigureServices
            
             services.AddHttpContextAccessor();


            // In a MyClass

            MyClass(IHttpContextAccessor accessor)
            {
                accessor.HttpContext.Claims; // Nothing
            }

Upvotes: 0

Views: 1563

Answers (2)

Nikola Sevo
Nikola Sevo

Reputation: 285

So, it looks like I configured my cookie authentication with google incorrectly. There might have been some issue with injecting MyClass.cs as singelton aswell so that is something to look out for.

Setup based on: how to implement google login in .net core without an entityframework provider and https://dotnetthoughts.net/aspnetcore-social-authentication-without-identity/

This is my working configuration:

            // Startup.cs:ConfigureServices
            services.AddAuthentication(v => {
                v.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                v.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
            })
            .AddCookie()
            .AddGoogle(GoogleDefaults.AuthenticationScheme, options =>
            {
                IConfigurationSection googleAuthNSection =
                    Configuration.GetSection("Authentication:Google");

                options.ClientId = googleAuthNSection["ClientId"];
                options.ClientSecret = googleAuthNSection["ClientSecret"];
            });
             
            // DIs accessor
            services.AddHttpContextAccessor();


            // AuthenticationController.cs:MyAction

            var authenticateResult = await HttpContext.AuthenticateAsync(GoogleDefaults.AuthenticationScheme);

            var claimsIdentity = new ClaimsIdentity("Application");

            var surnameClaim = authenticateResult.Principal.FindFirst(ClaimTypes.Surname);

            claimsIdentity.AddClaim(surnameClaim);

            await HttpContext.SignInAsync(
               "Application",
                new ClaimsPrincipal(claimsIdentity)
            );

        return LocalRedirect(returnUrl ?? "~/");



        // In MyClass.cs

        MyClass(IHttpContextAccessor accessor)
        {
            accessor.HttpContext.Claims; // Claims available!
        }

Upvotes: 0

Brando Zhang
Brando Zhang

Reputation: 28257

As far as I know, if we has used the cookie authentication and user has already login in, we could get the claims from the httpcontext accessor.

I suggest you could firstly make sure the browser has set the authentication token via cookie to the server.

Then I suggest you could make sure you have inject myclass as the scoped not Singleton.

More details, you refer to below test codes to read the cookie.

Myclass:

public class Myclass
{
    public IHttpContextAccessor _accessor { get; set; }
     public Myclass(IHttpContextAccessor accessor)
    {
        _accessor = accessor;

      var re =  accessor.HttpContext.User.Identity as ClaimsIdentity;
        int i = 0;
    }

    public string GetName() {
        var re = _accessor.HttpContext.User.Identity as ClaimsIdentity;

        string name = re.Claims.First(x => x.Type == "name").Value;

        return name;
    }


}

Startup.cs:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie();
        services.AddHttpContextAccessor();
        services.AddScoped(typeof(Myclass));
    }

Usage:

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    public Myclass test { get; set; }

    public HomeController(ILogger<HomeController> logger, Myclass _test)
    {
        _logger = logger;
        test = _test;
    }

    public async Task<IActionResult> IndexAsync()
    {
        var claimsIdentity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
        claimsIdentity.AddClaim(new Claim("name", "aaaa"));
        await HttpContext.SignInAsync(
           CookieAuthenticationDefaults.AuthenticationScheme,
            new ClaimsPrincipal(claimsIdentity)
        );
        return View();
    }

    public async Task<IActionResult> PrivacyAsync()
    {
        var  re= test.GetName();

        return View();
    }

    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    public IActionResult Error()
    {
        return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
    }
}

Result:

enter image description here

Upvotes: 1

Related Questions