Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Identity not set in login request

I'm using ASP.NET identity with a ClaimsIdentity to authenticate my users. When a user is authenticated, the property User.Identity contains a ClaimsIdentity instance.

However, this is not the case during the Login request:

    public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
    {
        if (!ModelState.IsValid)
        {
            return View(model);
        }

        var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, false, shouldLockout: false);
        switch (result)
        {
            case SignInStatus.Success:
                var identity = User.Identity;

------------>   // identity is of type WindowsIdentity  <------------

                return RedirectToLocal(returnUrl);

As you can see, even though the login was successful, the property User.Identity is not yet set to the ClaimsIdentity instance. I think this is plausible, it means that the SignInManager does not update the property, so we have to wait until the next request to see the result of the login.

However, I have to do additional logic after the method PasswordSignInAsync, so I need a way to get the ClaimsIdentity instance in the .Success branch of the switch statement.

While inspecting the SignInManager in the debugger, I saw that it is of type Microsoft.Owin.Security.AuthenticationManager, which has the property SignInEntry.Item1 which contains the ClaimsIdentity I'm looking for.

However, the type Microsoft.Owin.Security.AuthenticationManager is not public, so the only way seems to be a hack using reflection.

Is there an better way?

like image 211
cheesus Avatar asked Mar 03 '15 12:03

cheesus


People also ask

What is UserManager in ASP.NET Core?

The ASP.NET Identity UserManager class is used to manage users e.g. registering new users, validating credentials and loading user information. It is not concerned with how user information is stored. For this it relies on a UserStore (which in our case uses Entity Framework).

How do you add the identity file in an existing ASP Net Web API core application?

Now, open the Startup configurations and add below code under ConfigureServices. This code will setup the database context. The second line configures the database which should be used for identity. AddIdentity(IServiceCollection) adds the default identity system configuration for the specified User and Role types.


2 Answers

I agree that it's too bad that the PasswordSignInAsync doesn't return the user instance as an out parameter. If you look the source code, you can see that it uses this.UserManager.FindByNameAsync(userName) to find the user by userName, and then uses this.UserManager.CheckPasswordAsync(user, password) to validate the password, but the user is stored in a local variable.

I think this should be proposed as an improvement to the SignInManager class.

A possible (and inefficient) workaround is to query for the user again and then create the claims identity yourselft in the same way SignInManager.SignInAsync does:

        ApplicationUser user = await UserManager.FindByNameAsync(model.Email);
        ClaimsIdentity claimsIdentity = await SignInManager.CreateUserIdentityAsync(user);
like image 67
Augusto Barreto Avatar answered Sep 20 '22 18:09

Augusto Barreto


The identity is exposed through the AuthenticationResponseGrant property:

ClaimsIdentity identity = SignInManager.AuthenticationManager.AuthenticationResponseGrant.Identity;
like image 40
Phil Avatar answered Sep 18 '22 18:09

Phil