Come aggiornare un'attestazione in ASP.NET Identity?


95

Sto usando l'autenticazione OWIN per il mio progetto MVC5. Questo è il mioSignInAsync

 private async Task SignInAsync(ApplicationUser user, bool isPersistent)
        {
            var AccountNo = "101";
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
            identity.AddClaim(new Claim(ClaimTypes.UserData, AccountNo));
            AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent, RedirectUri="Account/Index"}, identity);
        }

Come puoi vedere, l'ho aggiunto AccountNoall'elenco dei reclami.

Ora, come posso aggiornare questa rivendicazione a un certo punto nella mia domanda? Finora ho questo:

 public string AccountNo
        {

            get
            {
                var CP = ClaimsPrincipal.Current.Identities.First();
                var Account= CP.Claims.FirstOrDefault(p => p.Type == ClaimTypes.UserData);
                return Account.Value;
            }
            set
            {
                var CP = ClaimsPrincipal.Current.Identities.First();
                var AccountNo= CP.Claims.FirstOrDefault(p => p.Type == ClaimTypes.UserData).Value;
                CP.RemoveClaim(new Claim(ClaimTypes.UserData,AccountNo));
                CP.AddClaim(new Claim(ClaimTypes.UserData, value));
            }

        }

quando provo a rimuovere il reclamo, ottengo questa eccezione:

Non è stato possibile rimuovere il reclamo " http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata : 101". Non fa parte di questa identità o è un'affermazione di proprietà del Principal che contiene questa identità. Ad esempio, il Principal sarà proprietario dell'attestazione durante la creazione di un GenericPrincipal con ruoli. I ruoli verranno esposti tramite l'identità passata nel costruttore, ma non effettivamente posseduta dall'identità. Esiste una logica simile per un RolePrincipal.

Qualcuno potrebbe aiutarmi a capire come aggiornare il reclamo?


Se si stanno memorizzando le informazioni sull'utente in un reclamo e si desidera aggiornare il reclamo, una volta che le informazioni sull'utente sono state modificate, è possibile chiamare: SignInManager.SignInAsyncper aggiornare il valore del reclamo. Vedi questa domanda
Hooman Bahreini

Risposte:


125

Ho creato un metodo di estensione per aggiungere / aggiornare / leggere attestazioni in base a una data ClaimsIdentity

namespace Foobar.Common.Extensions
{
    public static class Extensions
    {
            public static void AddUpdateClaim(this IPrincipal currentPrincipal, string key, string value)
            {
                var identity = currentPrincipal.Identity as ClaimsIdentity;
                if (identity == null)
                    return;

                // check for existing claim and remove it
                var existingClaim = identity.FindFirst(key);
                if (existingClaim != null)
                    identity.RemoveClaim(existingClaim);

                // add new claim
                identity.AddClaim(new Claim(key, value));
                var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
                authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(new ClaimsPrincipal(identity), new AuthenticationProperties() { IsPersistent = true });
            }

            public static string GetClaimValue(this IPrincipal currentPrincipal, string key)
            {
                var identity = currentPrincipal.Identity as ClaimsIdentity;
                if (identity == null)
                    return null;

                var claim = identity.Claims.FirstOrDefault(c => c.Type == key);
                return claim.Value;
            }
    }
}

e poi per usarlo

using Foobar.Common.Extensions;

namespace Foobar.Web.Main.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            // add/updating claims
            User.AddUpdateClaim("key1", "value1");
            User.AddUpdateClaim("key2", "value2");
            User.AddUpdateClaim("key3", "value3");
        }

        public ActionResult Details()
        {
            // reading a claim
            var key2 = User.GetClaim("key2");           
        }
    }
}

Infine. Avevo un'altra soluzione a questo e sembrava funzionare ... principalmente. Ma alla fine sono passato a questo metodo poiché sembra funzionare sempre. Grazie!
saml

3
Qualcuno ha la stessa soluzione per Asp.Net One Core?
Martín

Questo sembra funzionare solo per l'applicazione corrente. Vorrei aggiornare il cookie emesso dal server SSO in modo che anche altre app possano accedervi. Qualche idea su come? Grazie
Chiunque

@ Chiunque Poiché il cookie è firmato dal server SSO per mostrare che non è stato manomesso (e quindi ci si può fidare), sarei sorpreso se ci fosse un modo per ottenere questo risultato poiché sarebbe una manomissione.
Mog0

2
var claim = identity.Claims.First (c => c.Type == key); return claim.Value; dovrebbe essere var claim = identity.Claims.FirstOrDefault (c => c.Type == key); reclamo di ritorno? .Value;
liuhongbo

57

Puoi crearne uno nuovo ClaimsIdentitye quindi eseguire l'aggiornamento dei reclami con tale.

set {
    // get context of the authentication manager
    var authenticationManager = HttpContext.GetOwinContext().Authentication;

    // create a new identity from the old one
    var identity = new ClaimsIdentity(User.Identity);

    // update claim value
    identity.RemoveClaim(identity.FindFirst("AccountNo"));
    identity.AddClaim(new Claim("AccountNo", value));

    // tell the authentication manager to use this new identity
    authenticationManager.AuthenticationResponseGrant = 
        new AuthenticationResponseGrant(
            new ClaimsPrincipal(identity),
            new AuthenticationProperties { IsPersistent = true }
        );
}

4
È possibile aggiornare l'attestazione, ma è comunque necessario disconnettere e accedere l'utente con l'identità aggiornata.
user3210546

3
no, non disconnette l'utente, stiamo solo aggiornando il cookie dell'utente
Irshu

5
Ricorda che questo aggiorna solo l'identità. Se si desidera archiviare questi reclami e caricarli automaticamente su richiesta, è necessario che anche l'amministratore dell'utente li rimuova e li aggiorni. Mi ci è voluto del tempo! :(
Dennis van der Stelt,

3
E se non dispongo affatto dei cookie e utilizzo solo accessToken? Nel mio caso i reclami sono gli stessi sulla richiesta successiva come prima del cambiamento. L'unico modo per aggiornare i reclami che ho è disconnettere l'utente e chiedergli di accedere nuovamente :-(
Nozim Turakulov

1
Questo sembra funzionare solo per l'applicazione corrente. Vorrei aggiornare il cookie emesso dal server SSO in modo che anche altre app possano accedervi. Qualche idea su come? Grazie
Chiunque

18

Un altro approccio (asincrono), utilizzando Identity's UserManager e SigninManager per riflettere la modifica nel cookie di identità (e per rimuovere facoltativamente le attestazioni dalla tabella db AspNetUserClaims):

// Get User and a claims-based identity
ApplicationUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
var Identity = new ClaimsIdentity(User.Identity);

// Remove existing claim and replace with a new value
await UserManager.RemoveClaimAsync(user.Id, Identity.FindFirst("AccountNo"));
await UserManager.AddClaimAsync(user.Id, new Claim("AccountNo", value));

// Re-Signin User to reflect the change in the Identity cookie
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);

// [optional] remove claims from claims table dbo.AspNetUserClaims, if not needed
var userClaims = UserManager.GetClaims(user.Id);
if (userClaims.Any())
{
  foreach (var item in userClaims)
  {
    UserManager.RemoveClaim(user.Id, item);
  }
}

L'indizio qui, per me, era quello di fare SignInAsync() dopo aver impostato i reclami.
H Dog

Grazie per il suggerimento sulla rimozione delle rivendicazioni dal DB. Mi ha fatto capire che avevo bisogno di pulire dopo me stesso.
Uber Schnoz

13

Utilizzando l'ultima Asp.Net Identity con .net core 2.1, sono in grado di aggiornare le attestazioni degli utenti con la seguente logica.

  1. Registra un in UserClaimsPrincipalFactorymodo che ogni volta che SignInManagercanta l'utente, le attestazioni vengano create.

    services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, UserClaimService>();
    
  2. Implementa un'usanza UserClaimsPrincipalFactory<TUser, TRole>come di seguito

    public class UserClaimService : UserClaimsPrincipalFactory<ApplicationUser, ApplicationRole>
    {
        private readonly ApplicationDbContext _dbContext;
    
        public UserClaimService(ApplicationDbContext dbContext, UserManager<ApplicationUser> userManager, RoleManager<ApplicationRole> roleManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor)
        {
            _dbContext = dbContext;
        }
    
        public override async Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
        {
            var principal = await base.CreateAsync(user);
    
            // Get user claims from DB using dbContext
    
            // Add claims
            ((ClaimsIdentity)principal.Identity).AddClaim(new Claim("claimType", "some important claim value"));
    
            return principal;
        }
    }
    
  3. Più avanti nella tua applicazione, quando modifichi qualcosa nel DB e vorresti riflettere questo sul tuo utente autenticato e connesso, le seguenti righe ottengono questo:

    var user = await _userManager.GetUserAsync(User);
    await _signInManager.RefreshSignInAsync(user);
    

Ciò assicura che l'utente possa vedere le informazioni aggiornate senza richiedere nuovamente l'accesso. L'ho inserito appena prima di restituire il risultato nel controller in modo che al termine dell'operazione, tutto venga aggiornato in modo sicuro.

Invece di modificare le attestazioni esistenti e creare condizioni di competizione per cookie sicuri, ecc., Devi solo accedere l'utente in silenzio e aggiornare lo stato :)


Grazie, ho affrontato lo stesso problema e questa soluzione funziona meglio per l'aggiornamento delle attestazioni per un utente firmato.
ameya

Grazie! ha affrontato lo stesso problema anche in net core 3.1
Kevin Tran

7

Ottengo anche quell'eccezione e ho chiarito le cose in questo modo

var identity = User.Identity as ClaimsIdentity;
var newIdentity = new ClaimsIdentity(identity.AuthenticationType, identity.NameClaimType, identity.RoleClaimType);
newIdentity.AddClaims(identity.Claims.Where(c => false == (c.Type == claim.Type && c.Value == claim.Value)));
// the claim has been removed, you can add it with a new value now if desired
AuthenticationManager.SignOut(identity.AuthenticationType);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, newIdentity);

4

Ho compilato alcune risposte da qui nella classe ClaimsManager riutilizzabile con le mie aggiunte.

I reclami sono stati mantenuti, il cookie dell'utente aggiornato, l'accesso aggiornato.

Tieni presente che ApplicationUser può essere sostituito con IdentityUser se non hai personalizzato il precedente. Anche nel mio caso deve avere una logica leggermente diversa nell'ambiente di sviluppo, quindi potresti voler rimuovere la dipendenza IWebHostEnvironment.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using YourMvcCoreProject.Models;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Hosting;

namespace YourMvcCoreProject.Identity
{
    public class ClaimsManager
    {
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly SignInManager<ApplicationUser> _signInManager;
        private readonly IWebHostEnvironment _env;
        private readonly ClaimsPrincipalAccessor _currentPrincipalAccessor;

        public ClaimsManager(
            ClaimsPrincipalAccessor currentPrincipalAccessor,
            UserManager<ApplicationUser> userManager,
            SignInManager<ApplicationUser> signInManager,
            IWebHostEnvironment env)
        {
            _currentPrincipalAccessor = currentPrincipalAccessor;
            _userManager = userManager;
            _signInManager = signInManager;
            _env = env;
        }

        /// <param name="refreshSignin">Sometimes (e.g. when adding multiple claims at once) it is desirable to refresh cookie only once, for the last one </param>
        public async Task AddUpdateClaim(string claimType, string claimValue, bool refreshSignin = true)
        {
            await AddClaim(
                _currentPrincipalAccessor.ClaimsPrincipal,
                claimType,
                claimValue, 
                async user =>
                {
                    await RemoveClaim(_currentPrincipalAccessor.ClaimsPrincipal, user, claimType);
                },
                refreshSignin);
        }

        public async Task AddClaim(string claimType, string claimValue, bool refreshSignin = true)
        {
            await AddClaim(_currentPrincipalAccessor.ClaimsPrincipal, claimType, claimValue, refreshSignin);
        }

        /// <summary>
        /// At certain stages of user auth there is no user yet in context but there is one to work with in client code (e.g. calling from ClaimsTransformer)
        /// that's why we have principal as param
        /// </summary>
        public async Task AddClaim(ClaimsPrincipal principal, string claimType, string claimValue, bool refreshSignin = true)
        {
            await AddClaim(
                principal,
                claimType,
                claimValue, 
                async user =>
                {
                    // allow reassignment in dev
                    if (_env.IsDevelopment()) 
                        await RemoveClaim(principal, user, claimType);

                    if (GetClaim(principal, claimType) != null)
                        throw new ClaimCantBeReassignedException(claimType);                
                },
                refreshSignin);
        }

        public async Task RemoveClaims(IEnumerable<string> claimTypes, bool refreshSignin = true)
        {
            await RemoveClaims(_currentPrincipalAccessor.ClaimsPrincipal, claimTypes, refreshSignin);
        }

        public async Task RemoveClaims(ClaimsPrincipal principal, IEnumerable<string> claimTypes, bool refreshSignin = true)
        {
            AssertAuthenticated(principal);
            foreach (var claimType in claimTypes)
            {
                await RemoveClaim(principal, claimType);
            }
            // reflect the change in the Identity cookie
            if (refreshSignin)
                await _signInManager.RefreshSignInAsync(await _userManager.GetUserAsync(principal));
        }

        public async Task RemoveClaim(string claimType, bool refreshSignin = true)
        {
            await RemoveClaim(_currentPrincipalAccessor.ClaimsPrincipal, claimType, refreshSignin);
        }

        public async Task RemoveClaim(ClaimsPrincipal principal, string claimType, bool refreshSignin = true)
        {
            AssertAuthenticated(principal);
            var user = await _userManager.GetUserAsync(principal);
            await RemoveClaim(principal, user, claimType);
            // reflect the change in the Identity cookie
            if (refreshSignin)
                await _signInManager.RefreshSignInAsync(user);
        }

        private async Task AddClaim(ClaimsPrincipal principal, string claimType, string claimValue, Func<ApplicationUser, Task> processExistingClaims, bool refreshSignin)
        {
            AssertAuthenticated(principal);
            var user = await _userManager.GetUserAsync(principal);
            await processExistingClaims(user);
            var claim = new Claim(claimType, claimValue);
            ClaimsIdentity(principal).AddClaim(claim);
            await _userManager.AddClaimAsync(user, claim);
            // reflect the change in the Identity cookie
            if (refreshSignin)
                await _signInManager.RefreshSignInAsync(user);
        }

        /// <summary>
        /// Due to bugs or as result of debug it can be more than one identity of the same type.
        /// The method removes all the claims of a given type.
        /// </summary>
        private async Task RemoveClaim(ClaimsPrincipal principal, ApplicationUser user, string claimType)
        {
            AssertAuthenticated(principal);
            var identity = ClaimsIdentity(principal);
            var claims = identity.FindAll(claimType).ToArray();
            if (claims.Length > 0)
            {
                await _userManager.RemoveClaimsAsync(user, claims);
                foreach (var c in claims)
                {
                    identity.RemoveClaim(c);
                }
            }
        }

        private static Claim GetClaim(ClaimsPrincipal principal, string claimType)
        {
            return ClaimsIdentity(principal).FindFirst(claimType);    
        }    

        /// <summary>
        /// This kind of bugs has to be found during testing phase
        /// </summary>
        private static void AssertAuthenticated(ClaimsPrincipal principal)
        {
            if (!principal.Identity.IsAuthenticated)
                throw new InvalidOperationException("User should be authenticated in order to update claims");
        }

        private static ClaimsIdentity ClaimsIdentity(ClaimsPrincipal principal)
        {
            return (ClaimsIdentity) principal.Identity;
        }
    }


    public class ClaimCantBeReassignedException : Exception
    {
        public ClaimCantBeReassignedException(string claimType) : base($"{claimType} can not be reassigned")
        {
        }
    }

public class ClaimsPrincipalAccessor
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public ClaimsPrincipalAccessor(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public ClaimsPrincipal ClaimsPrincipal => _httpContextAccessor.HttpContext.User;
}

// to register dependency put this into your Startup.cs and inject ClaimsManager into Controller constructor (or other class) the in same way as you do for other dependencies    
public class Startup
{
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<ClaimsPrincipalAccessor>();
        services.AddTransient<ClaimsManager>();
    }
}

}


2

quando uso MVC5 e aggiungo qui l'attestazione.

public async Task<ClaimsIdentity> GenerateUserIdentityAsync(PATAUserManager manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        userIdentity.AddClaim(new Claim(ClaimTypes.Role, this.Role));

        return userIdentity;
    }

quando controllo il risultato dell'attestazione nella funzione SignInAsync, non riesco comunque a ottenere il valore del ruolo. Ma...

al termine di questa richiesta, posso accedere a Ruolo in un'altra azione (un'altra richiesta).

 var userWithClaims = (ClaimsPrincipal)User;
        Claim CRole = userWithClaims.Claims.First(c => c.Type == ClaimTypes.Role);

quindi, penso che forse causa asincrona IEnumerable aggiornato dietro il processo.


1

È possibile aggiornare le attestazioni per l'utente corrente implementando una CookieAuthenticationEventsclasse e eseguendo l'override ValidatePrincipal. Lì puoi rimuovere la vecchia rivendicazione, aggiungere quella nuova e quindi sostituire l'entità utilizzando CookieValidatePrincipalContext.ReplacePrincipal. Ciò non influisce sulle attestazioni archiviate nel database. Questo utilizza ASP.NET Core Identity 2.2.

public class MyCookieAuthenticationEvents : CookieAuthenticationEvents
{
    string newAccountNo = "102";

    public override Task ValidatePrincipal(CookieValidatePrincipalContext context)
    {
        // first remove the old claim
        var claim = context.Principal.FindFirst(ClaimTypes.UserData);
        if (claim != null)
        {
            ((ClaimsIdentity)context.Principal.Identity).RemoveClaim(claim);
        }

        // add the new claim
        ((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim(ClaimTypes.UserData, newAccountNo));

        // replace the claims
        context.ReplacePrincipal(context.Principal);
        context.ShouldRenew = true;

        return Task.CompletedTask;
    }
}

Devi registrare la classe degli eventi in Startup.cs:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddScoped<MyCookieAuthenticationEvents>();

    services.ConfigureApplicationCookie(o =>
    {
        o.EventsType = typeof(MyCookieAuthenticationEvents);
    });
}

Puoi iniettare servizi nella classe events per accedere al nuovo AccountNovalore ma come da avviso in questa pagina dovresti evitare di fare qualcosa di troppo costoso:

avvertimento

L'approccio qui descritto viene attivato a ogni richiesta. La convalida dei cookie di autenticazione per tutti gli utenti a ogni richiesta può comportare una notevole riduzione delle prestazioni dell'app.


grazie, questo ha funzionato benissimo per me in asp.net core 3.1!
darkezm0

0

Per rimuovere i dettagli del reclamo dal database possiamo utilizzare il codice seguente. Inoltre, dobbiamo accedere di nuovo per aggiornare i valori dei cookie

 // create a new identity 
            var identity = new ClaimsIdentity(User.Identity);

            // Remove the existing claim value of current user from database
            if(identity.FindFirst("NameOfUser")!=null)
                await UserManager.RemoveClaimAsync(applicationUser.Id, identity.FindFirst("NameOfUser"));

            // Update customized claim 
            await UserManager.AddClaimAsync(applicationUser.Id, new Claim("NameOfUser", applicationUser.Name));

            // the claim has been updates, We need to change the cookie value for getting the updated claim
            AuthenticationManager.SignOut(identity.AuthenticationType);
            await SignInManager.SignInAsync(Userprofile, isPersistent: false, rememberBrowser: false);

            return RedirectToAction("Index", "Home");

0

Cookie multipli, reclami multipli

public class ClaimsCookie
    {
        private readonly ClaimsPrincipal _user;
        private readonly HttpContext _httpContext;
        public ClaimsCookie(ClaimsPrincipal user, HttpContext httpContext = null)
        {
            _user = user;
            _httpContext = httpContext;
        }

        public string GetValue(CookieName cookieName, KeyName keyName)
        {
            var principal = _user as ClaimsPrincipal;
            var cp = principal.Identities.First(i => i.AuthenticationType == ((CookieName)cookieName).ToString());
            return cp.FindFirst(((KeyName)keyName).ToString()).Value;
        }
        public async void SetValue(CookieName cookieName, KeyName[] keyName, string[] value)
        {
            if (keyName.Length != value.Length)
            {
                return;
            }
            var principal = _user as ClaimsPrincipal;
            var cp = principal.Identities.First(i => i.AuthenticationType == ((CookieName)cookieName).ToString());
            for (int i = 0; i < keyName.Length; i++)
            {
                if (cp.FindFirst(((KeyName)keyName[i]).ToString()) != null)
                {
                    cp.RemoveClaim(cp.FindFirst(((KeyName)keyName[i]).ToString()));
                    cp.AddClaim(new Claim(((KeyName)keyName[i]).ToString(), value[i]));
                }

            }
            await _httpContext.SignOutAsync(CookieName.UserProfilCookie.ToString());
            await _httpContext.SignInAsync(CookieName.UserProfilCookie.ToString(), new ClaimsPrincipal(cp),
                new AuthenticationProperties
                {
                    IsPersistent = bool.Parse(cp.FindFirst(KeyName.IsPersistent.ToString()).Value),
                    AllowRefresh = true
                });
        }
        public enum CookieName
        {
            CompanyUserProfilCookie = 0, UserProfilCookie = 1, AdminPanelCookie = 2
        }
        public enum KeyName
        {
            Id, Name, Surname, Image, IsPersistent
        }
    }

0
    if (HttpContext.User.Identity is ClaimsIdentity identity)
        {
            identity.RemoveClaim(identity.FindFirst("userId"));
            identity.AddClaim(new Claim("userId", userInfo?.id.ToString()));
            await HttpContext.SignInAsync(
                CookieAuthenticationDefaults.AuthenticationScheme,
                new ClaimsPrincipal(HttpContext.User.Identity));
        }

7
Di solito è meglio spiegare una soluzione invece di pubblicare solo alcune righe di codice anonimo. Puoi leggere Come scrivo una buona risposta e anche Spiegare risposte interamente basate su codice
Anh Pham

0

Sto usando un'app .net core 2.2 e ho utilizzato la seguente soluzione: nel mio statup.cs

public void ConfigureServices(IServiceCollection services)
        {
        ...
           services.AddIdentity<IdentityUser, IdentityRole>(options =>
               {
                  ...
               })
               .AddEntityFrameworkStores<AdminDbContext>()
               .AddDefaultTokenProviders()
               .AddSignInManager();

utilizzo

  private readonly SignInManager<IdentityUser> _signInManager;


        public YourController(
                                    ...,
SignInManager<IdentityUser> signInManager)
        {
           ...
            _signInManager = signInManager;
        }

 public async Task<IActionResult> YourMethod() // <-NOTE IT IS ASYNC
        {
                var user = _userManager.FindByNameAsync(User.Identity.Name).Result;
                var claimToUse = ClaimsHelpers.CreateClaim(ClaimTypes.ActiveCompany, JsonConvert.SerializeObject(cc));
                var claimToRemove = _userManager.GetClaimsAsync(user).Result
                    .FirstOrDefault(x => x.Type == ClaimTypes.ActiveCompany.ToString());
                if (claimToRemove != null)
                {
                    var result = _userManager.ReplaceClaimAsync(user, claimToRemove, claimToUse).Result;
                    await _signInManager.RefreshSignInAsync(user); //<--- THIS
                }
                else ...
              

-1

Il metodo di estensione ha funzionato alla grande per me con un'eccezione che se l'utente si disconnette da lì esistevano ancora i vecchi set di attestazioni, quindi con una piccola modifica poiché passando usermanager attraverso tutto funziona alla grande e non è necessario disconnettersi e accedere. Non posso rispondere direttamente perché la mia reputazione è stata insultata :(

public static class ClaimExtensions
{
    public static void AddUpdateClaim(this IPrincipal currentPrincipal,    string key, string value, ApplicationUserManager userManager)
    {
        var identity = currentPrincipal.Identity as ClaimsIdentity;
        if (identity == null)
            return;

        // check for existing claim and remove it
        var existingClaim = identity.FindFirst(key);
        if (existingClaim != null)
        {
            RemoveClaim(currentPrincipal, key, userManager);
        }

        // add new claim
        var claim = new Claim(key, value);
        identity.AddClaim(claim);
        var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
        authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(new ClaimsPrincipal(identity), new AuthenticationProperties() { IsPersistent = true });
        //Persist to store
        userManager.AddClaim(identity.GetUserId(),claim);

    }

    public static void RemoveClaim(this IPrincipal currentPrincipal, string key, ApplicationUserManager userManager)
    {
        var identity = currentPrincipal.Identity as ClaimsIdentity;
        if (identity == null)
            return ;

        // check for existing claim and remove it
        var existingClaims = identity.FindAll(key);
        existingClaims.ForEach(c=> identity.RemoveClaim(c));

        //remove old claims from store
        var user = userManager.FindById(identity.GetUserId());
        var claims =  userManager.GetClaims(user.Id);
        claims.Where(x => x.Type == key).ToList().ForEach(c => userManager.RemoveClaim(user.Id, c));

    }

    public static string GetClaimValue(this IPrincipal currentPrincipal, string key)
    {
        var identity = currentPrincipal.Identity as ClaimsIdentity;
        if (identity == null)
            return null;

        var claim = identity.Claims.First(c => c.Type == key);
        return claim.Value;
    }

    public static string GetAllClaims(this IPrincipal currentPrincipal, ApplicationUserManager userManager)
    {
        var identity = currentPrincipal.Identity as ClaimsIdentity;
        if (identity == null)
            return null;

        var claims = userManager.GetClaims(identity.GetUserId());
        var userClaims = new StringBuilder();
        claims.ForEach(c => userClaims.AppendLine($"<li>{c.Type}, {c.Value}</li>"));
        return userClaims.ToString();
    }


}

-2

Ecco qui:

            var user = User as ClaimsPrincipal;
            var identity = user.Identity as ClaimsIdentity;
            var claim = (from c in user.Claims
                         where c.Type == ClaimTypes.UserData
                         select c).Single();
            identity.RemoveClaim(claim);

preso da qui.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.