Open Closed

How to update a claim value? #2244


User avatar
0
willignicolas@gmail.com created
  • ABP Framework version: v4.3.0
  • UI type: MVC
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): no

Hello,

We want to show a popup to users only one time for a user session so we go for user claims.

We make a ClaimsPrincipalContributor and the creation process of the new claim work perfectly.

We have a applicationservice's method to get the claim value from icurrentuser or currentprincipalaccessor to know if we must or not show the popup.

Our read method use : _currentPrincipalAccessor.Principal.Identities.First().FindFirst(ClaimsConst.WelcomePopupShowedClaimName);

But when it is time to update the value of the claim when the popup has been displayed to the user we fail to get good results despite our many attempts.

For exemple if we do this code the claim seems to update but on the read method the claim still have "false" value

var claimsIdentity = _currentPrincipalAccessor.Principal.Identities.First();

claimsIdentity.AddOrReplace(new Claim(ClaimsConst.WelcomePopupShowedClaimName, "true"));

await _httpContextAccessor.HttpContext.SignOutAsync();
await _httpContextAccessor.HttpContext.SignInAsync(_currentPrincipalAccessor.Principal);

And so here is our question: How to update an existing user claim (on the call of a applicationservice's method) when the user is connected ?

Thanks for you help.

Nicolas


4 Answer(s)
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    HI,

    You can try use the Change method of currentPrincipalAccessor

    Example:

    using(_currentPrincipalAccessor.Change(...))
    {
       await _httpContextAccessor.HttpContext.SignOutAsync();
       await _httpContextAccessor.HttpContext.SignInAsync(_currentPrincipalAccessor.Principal);
    }
    
  • User Avatar
    0
    willignicolas@gmail.com created

    Thanks for your quick reply.

    I have tested your solution but the result stay the same.

    On the end of the write method the CurrentUser.GetAllClaims() (or on the currentPrincipalAccessor.principal) have the claim with the new value ("true") but when i call the read method again the value is "false".

    There is my full code of appservice :

    public virtual ShowPopupsOutputDto GetShowedPopups()
            {
                var welcomePopupClaim = _currentPrincipalAccessor.Principal.Identities.First().FindFirst(ClaimsConst.WelcomePopupShowedClaimName);
    
                var test = CurrentUser.GetAllClaims();
                return new ShowPopupsOutputDto
                {
                    ShowWelcomeConfigPopup = welcomePopupClaim == null || welcomePopupClaim.Value == "false",
                };
    
            }
    
            public virtual async Task SetShowedWelcomePopup()
            {
                var claimsIdentity = _currentPrincipalAccessor.Principal.Identities.First();
    
                claimsIdentity.AddOrReplace(new Claim(ClaimsConst.WelcomePopupShowedClaimName, "true"));
    
                using (_currentPrincipalAccessor.Change(_currentPrincipalAccessor.Principal))
                {
                    await _httpContextAccessor.HttpContext.SignOutAsync();
                    await _httpContextAccessor.HttpContext.SignInAsync(_currentPrincipalAccessor.Principal);
                }
                
                
            }
    

    And the contributor :

      public class JureezClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency
        {
            public async Task ContributeAsync(AbpClaimsPrincipalContributorContext context)
            {
                var currentTenant = context.ServiceProvider.GetRequiredService<ICurrentTenant>();
    
                var claimsIdentity = new ClaimsIdentity();
                context.ClaimsPrincipal.Identities.First().AddClaim(new Claim(ClaimsConst.WelcomePopupShowedClaimName, currentTenant.Id != null ? "false" : "true")); ;
            }
        }
    

    Thanks again for your help.

    Nicolas.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    Can you try testing with the following code? it works for me.

    
    public class IndexModel : MyProjectNamePageModel
    {
        private readonly ICurrentPrincipalAccessor _currentPrincipalAccessor;
    
        private readonly SignInManager<IdentityUser> _signInManager;
    
        private readonly IIdentityUserRepository _userRepository;
    
        public IndexModel(
            ICurrentPrincipalAccessor currentPrincipalAccessor,
            SignInManager<IdentityUser> signInManager,
            IIdentityUserRepository userRepository)
        {
            _currentPrincipalAccessor = currentPrincipalAccessor;
            _signInManager = signInManager;
            _userRepository = userRepository;
        }
    
        public async Task OnGetAsync(bool setShowedWelcomePopup)
        {
            if (CurrentUser.IsAuthenticated)
            {
                var user = await _userRepository.FindAsync(CurrentUser.GetId());
    
                if (setShowedWelcomePopup)
                {
                    await _signInManager.SignOutAsync();
                    await _signInManager.SignInAsync(user, true);
                }
            }
        }
    }
    
    public class JureezClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency
    {
        public async Task ContributeAsync(AbpClaimsPrincipalContributorContext context)
        {
            var currentTenant = context.ServiceProvider.GetRequiredService<ICurrentTenant>();
    
            context.ClaimsPrincipal.Identities.First().AddClaim(new Claim("WelcomePopupShowedClaimName", currentTenant.Id != null ? "false" : "true"));
        }
    }
    
  • User Avatar
    0
    willignicolas@gmail.com created

    Hello and thanks for your help.

    I was not able to make your code working (BTW the last edition of your post doesn't change the value of the claim so i don't anderstand how it work)

    There is the code that works (inspired by your first editon of your last post) :

    My application service :

    [Authorize]
        public class ConfigurationAppService : JureezAppService, IConfigurationAppService
        {
            private readonly ICurrentPrincipalAccessor _currentPrincipalAccessor;
            private readonly VAI.IIdentityUserRepository _userRepository;
            private readonly SignInManager<VAI.IdentityUser> _signInManager;
    
    
            public ConfigurationAppService(ICurrentPrincipalAccessor currentPrincipalAccessor,
                VAI.IIdentityUserRepository userRepository,
                SignInManager<VAI.IdentityUser> signInManager)
            {
                _currentPrincipalAccessor = currentPrincipalAccessor;
                _userRepository = userRepository;
                _signInManager = signInManager;
            }
    
            public virtual ShowPopupsOutputDto GetShowedPopups()
            {
                var welcomePopupClaim = _currentPrincipalAccessor.Principal.Identities.First().FindFirst(ClaimsConst.WelcomePopupShowedClaimName);
    
                return new ShowPopupsOutputDto
                {
                    ShowWelcomeConfigPopup = welcomePopupClaim == null || welcomePopupClaim.Value == "false",
                };
            }
    
            public virtual async Task SetShowedWelcomePopup()
            {
                var user = await _userRepository.FindAsync(CurrentUser.GetId());
    
                await _signInManager.SignOutAsync();
                await _signInManager.SignInWithClaimsAsync(user, true, new List<Claim> { new Claim(ClaimsConst.WelcomePopupShowedClaimName, "true") });
            }
    
        }
    

    No claimprincipalcontributor only the claim declaration in my module :

    Configure<AbpClaimsServiceOptions>(options =>
                {
                    options.RequestedClaims.Add(ClaimsConst.WelcomePopupShowedClaimName);
                });
    

    With this solution my claim value is truly updated and available on the read method for the rest of my user session.

    Thanks again for your time and your help.

    Nicolas

Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11