user3097695
user3097695

Reputation: 1274

Add user claims in identityserver4

I have created identityserver4 project and tried to add more claims after user log in. Here is my code

        public async Task<IActionResult> Login(LoginInputModel model)
       {
          if (ModelState.IsValid)
          {
            // validate username/password against in-memory store
                 CoreDb.Models.User user = null;
                 if (( user = await _userService.VerifyUser(model.Username, model.Password)) != null)
            {
               // var user = _users.FindByUsername(model.Username);
                await _events.RaiseAsync(new UserLoginSuccessEvent(user.Name, user.Id.ToString(), user.Name));

                // only set explicit expiration here if user chooses "remember me". 
                // otherwise we rely upon expiration configured in cookie middleware.
                   var props = new AuthenticationProperties();
                   if (AccountOptions.AllowRememberLogin && model.RememberLogin)
              {
                            props.IsPersistent = true;
                            props.ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration);
              };

                    props.Items.Add("scheme", AccountOptions.WindowsAuthenticationSchemeName);

                    // issue authentication cookie with subject ID and username
                    await HttpContext.SignInAsync(user.Id.ToString(), user.Name, "idp", props, _userService.GetUserClaims(user).ToArray());

                    //IEnumerable<ClaimsIdentity> claimsIdentity = null;
                    //var claimsIdentity = new ClaimsIdentity(_userService.GetUserClaims(user), CookieAuthenticationDefaults.AuthenticationScheme);
                    //await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));

                    // make sure the returnUrl is still valid, and if so redirect back to authorize endpoint or a local page
                    if (_interaction.IsValidReturnUrl(model.ReturnUrl) || Url.IsLocalUrl(model.ReturnUrl))
                    {
                        return Redirect(model.ReturnUrl);
                    }

                    return Redirect("~/");
                 }

                    await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials"));

                    ModelState.AddModelError("", AccountOptions.InvalidCredentialsErrorMessage);
          }

However, I do not see my claims for the user when I call my api in requirement handler although my user id is there. What is an appropriate way to add user claims?

Upvotes: 1

Views: 3012

Answers (2)

Torsten Kolb
Torsten Kolb

Reputation: 218

As Jay already mentioned, you can write your own ProfileService. If you don't use aspnetidentity you can just add the Claims in the Login method and add these lines to the GetProfileDataAsync Method of your ProfileService:

 List<Claim> claims = context.Subject.Claims.Where(x => x.Type == JwtClaimTypes.Role).ToList();

  context.IssuedClaims.AddRange(claims);

Upvotes: 1

Jay
Jay

Reputation: 1889

The claims must be added to the response context. If you are using aspnetidentity then the following approach will work for you

Ensure to include ProfileService implementation and hook up to IdentityServer at ConfigureServices

 .AddProfileService<ProfileService>();

 private readonly IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory;

In the GetProfileDataAsync, you can include your new claims

 /// <summary>
    /// This method is called whenever claims about the user are requested (e.g. during token creation or via the userinfo endpoint)
    /// </summary>
    /// <param name="context">The context.</param>
    /// <returns></returns>
    public override async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var sub = context.Subject.GetSubjectId();
        var user = await userManager.FindByIdAsync(sub);
        var principal = await claimsFactory.CreateAsync(user);
        //context.AddFilteredClaims(principal.Claims);
        context.IssuedClaims.AddRange(principal.Claims);            
        context.IssuedClaims.Add(new Claim("IP Address", coreOperations.GetCurrentRequestIPAddress()));

    }

Upvotes: 2

Related Questions