User.Identity.Name is always null when using AspNetIdentity with IdentityServer3
Asked Answered
C

2

10

I've been trying to setup a new IdentityServer3 with AspNetIdentity for a few days now. I'm able to login using my existing Identity DB and that's all good but I can never get the User.Identity.Name to contain data. I've tried multiple attempts at adding custom claims & scopes and adding scopes to clients.

Finally, I loaded up the IdentityServer3 Sample repository and tested it out with the webforms client project since it already used the User.Identity.Name in it's About page.

Using WebForms sample client + AspNetIdentity sample server = User.Identity.Name is always null Using WebForms sample client + SelfHost with Seq sample server = User.Identity.Name with data I've tried other sample host projects that all populate the User.Identity.Name value just fine.

Now, on the client side I've written a workaround to pull the 'preferred_username' claim value and set the 'name' claim with it.

var id = new claimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
id.AddClaims(userInfoResponse.GetClaimsIdentity().Claims);

//set the User.Identity.Name value
var name = id.Claims.Where(x => x.Type == "name").Select(x => x.Value).FirstOrDefault() ??
           id.Claims.Where(x => x.Type == "preferred_username").Select(x => x.Value).FirstOrDefault();
id.AddClaim(new Claim("name", name));

My questions are:

  1. Why doesn't the AspNetIdentity package fill this by default?
  2. And what do I need to change on the server side so that I don't need to change the client?
Civilly answered 24/2, 2017 at 14:59 Comment(3)
Did you ever find a 'better' solution to this issue?Enisle
We're keeping that solution in place. It works. We have other custom claims that we add at that time as well. We did not have enough time to dig into the differences between the examples I posted.Civilly
@Civilly How does the variable userInfoResponse get it's value in the above workaround?Redouble
M
3
public static IEnumerable<ApiResource> GetApis()
{
   return new ApiResource[]
   {
      new ApiResource("MyApi", "My Admin API")
      {
          UserClaims =  { JwtClaimTypes.Name, JwtClaimTypes.Email }
      }
   };
}

In Identityserver4 you can add the UserClaims to your resource. Fixed it for me.

Methacrylate answered 28/3, 2019 at 14:57 Comment(0)
S
0

On IdentityServer4 you can implement IProfileService on server and add the Claim in GetProfileDataAsync

public class AspNetIdentityProfileService : IProfileService
{
    protected UserManager<ApplicationUser> _userManager;

    public AspNetIdentityProfileService(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        //Processing
        var user = _userManager.GetUserAsync(context.Subject).Result;

        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, user.UserName),
        };

        context.IssuedClaims.AddRange(claims);

        //Return
        return Task.FromResult(0);
    }

    public Task IsActiveAsync(IsActiveContext context)
    {
        //Processing
        var user = _userManager.GetUserAsync(context.Subject).Result;

        context.IsActive = (user != null) && ((!user.LockoutEnd.HasValue) || (user.LockoutEnd.Value <= DateTime.Now));

        //Return
        return Task.FromResult(0);
    }
}

Then add "AddProfileService()" to your ConfigureServices method.

services.AddIdentityServer(...)
    ...
    .AddProfileService<AspNetIdentityProfileService>();
Safelight answered 6/8, 2018 at 11:30 Comment(1)
The problem with that solution is that you get the UserName from IdpUsers which is not necessary the same as the ProviderKey - in a SSO environment you would probably prefer to have both the provider key and the SID returned to the client.Hindermost

© 2022 - 2024 — McMap. All rights reserved.