Aucun IUserTokenProvider n'est enregistré

101

J'ai récemment mis à jour Asp.Net Identity Core mon formulaire de candidature 1.0 à 2.0.

Il y a de nouvelles fonctionnalités que je voulais essayer GenerateEmailConfirmationToken, etc.

J'utilise ça projet comme référence.

Lorsque l'utilisateur tente de s'inscrire, j'obtiens une erreur lors de l'exécution de la méthode Post de Register

private readonly UserManager<ApplicationUser> _userManager;     

public ActionResult Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var ifUserEXists = _userManager.FindByName(model.EmailId);
        if (ifUserEXists == null) return View(model);
        var confirmationToken = _userRepository.CreateConfirmationToken();//this is how i'm generating token currently.                
        var result = _userRepository.CreateUser(model,confirmationToken);
        var user = _userManager.FindByName(model.EmailId);
        if (result)
        {
            var code = _userManager.GenerateEmailConfirmationToken(user.Id);//error here
            _userRepository.SendEmailConfirmation(model.EmailId, model.FirstName, confirmationToken);
            //Information("An email is sent to your email address. Please follow the link to activate your account.");
            return View("~/Views/Account/Thank_You_For_Registering.cshtml");
        }     
    }
    
    //Error("Sorry! email address already exists. Please try again with different email id.");
    ModelState.AddModelError(string.Empty, Resource.AccountController_Register_Sorry__User_already_exists__please_try_again_);
    return View(model);
}

Dans la ligne

 var code = _userManager.GenerateEmailConfirmationToken(user.Id);

Je reçois une erreur en disant:

No IUserTokenProvider is registered.

Pour l'instant, je voulais juste voir quel type de code cela génère. Y a-t-il un changement que je dois apporter à ma ApplicationUserclasse qui hérite deIdentityUser classe?

Ou dois-je changer quelque chose pour que ces fonctions fonctionnent?

Cybercop
la source
1
Existe-t-il un moyen de vérifier si un utilisateur existe sur la base d'autres champs que l'adresse e-mail? Par exemple, si j'avais deux champs appelés CustomerNumber et Postcode pour les utilisateurs qui existeraient déjà dans la base de données pour empêcher tout le monde de s'inscrire
Jay

Réponses:

127

Vous devez spécifier a UserTokenProviderpour générer un jeton.

using Microsoft.Owin.Security.DataProtection;
using Microsoft.AspNet.Identity.Owin;
// ...

var provider = new DpapiDataProtectionProvider("SampleAppName");

var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>());

userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(
    provider.Create("SampleTokenName"));

Vous devez également lire cet article: Ajout de l'authentification à deux facteurs à une application utilisant l'identité ASP.NET .

meziantou
la source
5
que sont "Sample"et "EmailConfirmation"? un texte qui peut être n'importe quoi?
Cybercop
2
"Sample" = AppName, "EmailConfirmation" = purpose (comme les noms de paramètres)
meziantou
5
Oui, mais vous devrez utiliser la même chose pour générer et valider des jetons
meziantou
1
Le lien est OK. Vous mettez ce code là où vous initialisez leUserManager
meziantou
cela provoque 'Impossible de charger le type' System.Security.Cryptography.DpapiDataProtector 'de l'assembly dans .netcore
TAHA SULTAN TEMURI
25

Dans ASP.NET Core, il est désormais possible de configurer un service par défaut dans Startup.cs comme ceci:

services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddDefaultTokenProviders();

Il n'est pas nécessaire d'appeler le DpapiDataProtectionProviderou quelque chose comme ça. DefaultTokenProviders () s'occupera de l'appel à GenerateEmailConfirmationToken depuis le UserManager.

Pisker
la source
21

En plus de la réponse acceptée, j'aimerais ajouter que cette approche ne fonctionnera pas dans les sites Web Azure, vous obtiendrez CryptographicException au lieu d'un jeton.

Pour le résoudre pour Azure, implémentez votre propre IDataProtector: voir cette réponse

Un peu plus de détails dans l' article de blog

trailmax
la source
13

Ma solution:

    var provider = new DpapiDataProtectionProvider("YourAppName");
    UserManager.UserTokenProvider = new DataProtectorTokenProvider<User, string>(provider.Create("UserToken")) 
        as IUserTokenProvider<User, string>;

Mon problème avec ce code est résolu.
Bonne chance les amis.

Amin Ghaderi
la source
en utilisant Microsoft.Owin.Security.DataProtection;
Amin Ghaderi
J'ai dû utiliser DataProtectorTokenProvider <IdentityUser, string> au lieu de <User, string> pour les deux génériques. L'ID utilisateur dans GeneratePasswordResetToken est également l'ID de chaîne guid et non le nom d'utilisateur ou l'e-mail.
Dan Randolph
7

Au cas où quelqu'un d'autre ferait la même erreur que moi. J'ai essayé de créer une fonction comme celle ci-dessous et bien sûr l'erreur "Aucun IUserTokenProvider n'est enregistré." était parti. Cependant, dès que j'ai essayé d'utiliser le lien généré à partir de "callbackUrl", j'ai eu l'erreur "Jeton non valide". Pour que cela fonctionne, vous devez obtenir le UserManager HttpContext. Si vous utilisez une application ASP.NET MVC 5 standard avec des comptes d'utilisateurs individuels, vous pouvez le faire comme ci-dessous.

Code qui fonctionne:

public ActionResult Index()
     {
         //Code to create ResetPassword URL
         var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
         var user = userManager.FindByName("[email protected]");
         string code = userManager.GeneratePasswordResetToken(user.Id);
         var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
         return View();
     }

Premier essai qui ne fonctionne pas, No IUserTokenProvider is registered.est parti mais l'URL créée obtient Invalid token..

public ActionResult NotWorkingCode()
     {
             //DOES NOT WORK - When used the error "Invalid token." will always trigger.
             var provider = new DpapiDataProtectionProvider("ApplicationName");
             var userManager = new ApplicationUserManager(new UserStore<ApplicationUser>(new ApplicationDbContext()));
             userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("ASP.NET Identity"));
             var user = userManager.FindByName("[email protected]");
             string code = userManager.GeneratePasswordResetToken(user.Id);
             var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
             //DOES NOT WORK - When used the error "Invalid token." will always trigger.
         return View();
     }
Ogglas
la source
5

Selon pisker ci-dessus

Dans startup.cs, vous pouvez utiliser

services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddDefaultTokenProviders();

Dans .net core 2.0, vous devrez peut-être ajouter à startup.cs:

using Microsoft.AspNetCore.Identity;

CA marchait bien pour moi.

ScottC
la source
1
Je pense qu'il est important de se rappeler qu'il s'agit d'une solution Asp .NET Core, elle ne fonctionnera pas avec Asp .NET Framework.
Machado
3

Lors de la modification des fichiers d'identité de .NET Core, je suis tombé sur cette erreur:

NotSupportedException: aucun IUserTwoFactorTokenProvider nommé 'Default' n'est enregistré.

le

Microsoft.AspNetCore.Identity.UserManager.GenerateUserTokenAsync

n'a pas pu générer de jeton car aucun fournisseur n'était disponible lors de l'enregistrement d'un nouvel utilisateur. Cette erreur a cependant une solution facile!

Si vous êtes comme moi, vous avez changé AddDefaultIdentityle Startup.csfichier en AddIdentity. Je voulais implémenter mon propre utilisateur hérité de l'utilisateur de base. En faisant cela, j'ai perdu les fournisseurs de jetons par défaut. Le correctif était de les rajouter avec AddDefaultTokenProviders().

        services.AddIdentity<User, UserRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

Après ce correctif, tout a fonctionné à nouveau!

source: https://mattferderer.com/NotSupportedException-No-IUserTwoFactorTokenProvider-tuser-named-default-registered

Yawar Ali
la source
1

J'ai eu la même erreur après la mise à jour d'Identity et j'ai constaté que c'était parce que j'utilisais Unity.

Voir ce fil de question sur la solution: Enregistrer IAuthenticationManager avec Unity

Aussi ci-dessous pour une référence rapide:

Voici ce que j'ai fait pour que Unity fonctionne bien avec ASP.NET Identity 2.0:

J'ai ajouté ce qui suit à la RegisterTypesméthode dans la UnityConfigclasse:

container.RegisterType<DbContext, ApplicationDbContext>(new HierarchicalLifetimeManager());
container.RegisterType<UserManager<ApplicationUser>>(new HierarchicalLifetimeManager());
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new HierarchicalLifetimeManager());
container.RegisterType<AccountController>(new InjectionConstructor());
Rob
la source
1
J'ai suivi cela, mais cela n'a pas fonctionné (pour GeneratePasswordResetToken- mais j'ai eu la même erreur de "Aucun IUserTokenProvider n'est enregistré"). Après avoir ajouté container.RegisterType<ApplicationUserManager>( new InjectionFactory(c => HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>()));à UnityConfig.cs, cela a fonctionné.
0

dans IdentityConfig.cs, ajoutez votre option à deux facteurs:

        manager.RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider<ApplicationUser>
        {
            MessageFormat = "Your security code is {0}"
        });
        manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<ApplicationUser>
        {
            Subject = "Security Code",
            BodyFormat = "Your security code is {0}"
        });
        //config sms service 
        manager.SmsService = new Services.SMS();
        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
Mohammad Reza Mrg
la source