IdentityServer3: Some Claims not being returned from identity server
Finally found the solution for this problem.
First, I moved the creation of claims to the overridden GetProfileDataAsync (in my UserService class). Here's my implementation of it:
public override Task GetProfileDataAsync(ProfileDataRequestContext context) { var identity = new ClaimsIdentity(); UserInfo user = null; if (!string.IsNullOrEmpty(context.Subject.Identity.Name)) user = _facade.Get(context.Subject.Identity.Name); else { // get the sub claim var claim = context.Subject.FindFirst(item => item.Type == "sub"); if (claim != null) { Guid userId = new Guid(claim.Value); user = _facade.Get(userId); } } if (user != null) { identity.AddClaims(new[] { new Claim(Constants.ClaimTypes.PreferredUserName, user.Username), new Claim(Constants.ClaimTypes.Email, user.EmailAddress) // .. other claims }); }context.IssuedClaims = identity.Claims; //<- MAKE SURE you add the claims here return Task.FromResult(identity.Claims); }
Make sure that we pass the claims to the "context.IssueClaims" inside the GetProfileDataAsync() before returning the task.
And for those interested on how my AuthenticateLocalAsync() looks like:
var user = _facade.Get(context.UserName); if (user == null) return Task.FromResult(0); var isPasswordCorrect = BCrypt.Net.BCrypt.Verify(context.Password, user.Password); if (isPasswordCorrect) { context.AuthenticateResult = new AuthenticateResult(user.Id.ToString(), user.Username); } return Task.FromResult(0);
I raised a similar issue in IdentityServer3 GitHub project page that contains the explanation on why I encountered my issue. Here's the link:https://github.com/IdentityServer/IdentityServer3/issues/1938
My solution was to add a list of claims to my scope configuration in order to return those claims. The wiki's documentation here described it.
For an in-memory client all I did was something like this:
public class Scopes{ public static IEnumerable<Scope> Get() { return new Scope[] { StandardScopes.OpenId, StandardScopes.Profile, StandardScopes.Email, StandardScopes.Roles, StandardScopes.OfflineAccess, new Scope { Name = "yourScopeNameHere", DisplayName = "A Nice Display Name", Type = ScopeType.Identity, Emphasize = false, Claims = new List<ScopeClaim> { new ScopeClaim("yourClaimNameHere", true), new ScopeClaim("anotherClaimNameHere", true) } } }; }}
I am not using the identity server, however I am using the Windows Identity Foundation, which I believe is what IdentityServer uses. In order to access the claims I use:
((ClaimsIdentity)User.Identity).Claims