Nessun IUserTokenProvider è registrato


101

Di recente ho aggiornato il Asp.Net Identity Coremio modulo di domanda dalla 1.0 alla 2.0.

Ci sono nuove funzionalità che volevo provare GenerateEmailConfirmationToken, ecc.

Sto usando questo progetto come riferimento.

Quando l'utente prova a registrarsi, ottengo un errore durante l'esecuzione del metodo Post di 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);
}

In linea

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

Ottengo un errore dicendo:

No IUserTokenProvider is registered.

Per ora, volevo solo vedere che tipo di codice genera. C'è qualche cambiamento che devo apportare alla mia ApplicationUserclasse che eredita dalla IdentityUserclasse?

O c'è qualcosa che devo cambiare per far funzionare quelle funzioni?


1
Esiste un modo per verificare se un utente esiste in base a campi diversi dall'indirizzo e-mail? Ad esempio, se avessi due campi chiamati CustomerNumber e Postcode per gli utenti che sarebbero già presenti nel database per impedire a chiunque di registrarsi
Jay

Risposte:


127

Devi specificare a UserTokenProviderper generare un token.

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"));

È inoltre necessario leggere questo articolo: Aggiunta dell'autenticazione a due fattori a un'applicazione che utilizza ASP.NET Identity .


5
cosa sono "Sample"e "EmailConfirmation"? un testo che può essere qualsiasi cosa?
Cybercop

2
"Sample" = AppName, "EmailConfirmation" = scopo (come i nomi dei parametri)
meziantou

5
Sì, ma dovrai usare lo stesso per generare e convalidare i token
meziantou

1
Il collegamento è OK. UserManager
Metti

questo causa "Impossibile caricare il tipo" System.Security.Cryptography.DpapiDataProtector "dall'assembly in .netcore
TAHA SULTAN TEMURI

25

In ASP.NET Core è oggi possibile configurare un servizio predefinito in Startup.cs come questo:

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

Non è necessario chiamare il DpapiDataProtectionProvidero qualcosa del genere. DefaultTokenProviders () si occuperà della chiamata a GenerateEmailConfirmationToken da UserManager.


21

Oltre alla risposta accettata, vorrei aggiungere che questo approccio non funzionerà nei siti Web di Azure, riceverai CryptographicException invece di un token.

Per risolverlo per Azure, implementa il tuo IDataProtector: vedi questa risposta

Leggermente più in dettaglio nel post del blog


13

La mia soluzione:

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

Il mio problema con questo codice è stato risolto.
Buona fortuna amici.


using Microsoft.Owin.Security.DataProtection;
Amin Ghaderi

Ho dovuto usare DataProtectorTokenProvider <IdentityUser, string> invece di <User, string> per entrambi i generici. Anche l'ID utente in GeneratePasswordResetToken è l'ID della stringa guida e non il nome utente o l'e-mail.
Dan Randolph

7

Nel caso qualcun altro commetta lo stesso errore che ho fatto io. Ho provato a creare una funzione come quella qui sotto e abbastanza sicuro l'errore "No IUserTokenProvider è registrato". era andato. Tuttavia, non appena ho provato a utilizzare il collegamento generato da "callbackUrl", ho ricevuto l'errore "Token non valido". Affinché funzioni, è necessario ottenere HttpContext UserManager. Se stai utilizzando un'applicazione ASP.NET MVC 5 standard con account utente individuali, puoi farlo come di seguito.

Codice che funziona:

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

Primo tentativo che non funziona, No IUserTokenProvider is registered.è andato ma l'URL creato ottiene 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("useremail@gmail.com");
             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();
     }

5

Come per pisker sopra

In startup.cs puoi usare

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

In .net core 2.0 potrebbe essere necessario aggiungere a startup.cs:

using Microsoft.AspNetCore.Identity;

Questo ha funzionato bene per me.


1
Penso che sia importante ricordare che questa è una soluzione Asp .NET Core, non funzionerà con Asp .NET Framework.
Machado

3

Durante la modifica dei file Identity di .NET Core, mi sono imbattuto in questo errore:

NotSupportedException: non è registrato alcun IUserTwoFactorTokenProvider denominato "Default".

Il

Microsoft.AspNetCore.Identity.UserManager.GenerateUserTokenAsync

la funzione non poteva generare un token perché nessun provider era disponibile al momento della registrazione di un nuovo utente. Tuttavia, questo errore ha una soluzione semplice!

Se sei come me, hai cambiato AddDefaultIdentitynel Startup.csfile in AddIdentity. Volevo implementare il mio utente ereditato dall'utente di base. In questo modo ho perso i provider di token predefiniti. La soluzione era aggiungerli di nuovo con AddDefaultTokenProviders().

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

Dopo quella correzione, tutto ha funzionato di nuovo!

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


1

Ho ricevuto lo stesso errore dopo aver aggiornato Identity e ho scoperto che era perché stavo usando Unity.

Vedi questo thread di domande sulla soluzione: registra IAuthenticationManager con Unity

Anche di seguito per una rapida consultazione:

Ecco cosa ho fatto per rendere Unity piacevole con ASP.NET Identity 2.0:

Ho aggiunto quanto segue al RegisterTypesmetodo nella 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());

1
Ho seguito questo, ma non ha funzionato (per GeneratePasswordResetToken- ma ho ricevuto lo stesso errore di "Nessun IUserTokenProvider è registrato"). Dopo aver aggiunto container.RegisterType<ApplicationUserManager>( new InjectionFactory(c => HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>()));a UnityConfig.cs, ha funzionato.


0

in IdentityConfig.cs, aggiungi la tua opzione a due fattori:

        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"));
        }
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.