No hay ningún IUserTokenProvider registrado

101

Recientemente actualicé Asp.Net Identity Coremi formulario de solicitud 1.0 a 2.0.

Hay nuevas funciones que quería probar GenerateEmailConfirmationToken, etc.

Estoy usando este proyecto como referencia.

Cuando el usuario intenta registrarse, aparece un error durante la ejecución del método de publicación de registro

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

En la linea

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

Me sale un error que dice:

No IUserTokenProvider is registered.

Por ahora, solo quería ver qué tipo de código genera. ¿Hay algún cambio que deba hacer en mi ApplicationUserclase que herede de la IdentityUserclase?

¿O hay algo que necesito cambiar para que funcionen esas funciones?

Cybercop
fuente
1
¿Hay alguna forma de comprobar si existe un usuario basándose en otros campos además de la dirección de correo electrónico? Por ejemplo, si tuviera dos campos llamados CustomerNumber y Postcode para usuarios que ya existirían previamente en la base de datos para evitar que cualquiera se registre
Jay

Respuestas:

127

Tienes que especificar un UserTokenProviderpara generar 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"));

También debe leer este artículo: Adición de autenticación de dos factores a una aplicación que usa la identidad ASP.NET .

meziantou
fuente
5
lo que son "Sample"y "EmailConfirmation"? algún texto que puede ser cualquier cosa?
Cybercop
2
"Sample" = AppName, "EmailConfirmation" = propósito (como los nombres de los parámetros)
meziantou
5
Sí, pero tendrá que usar lo mismo para generar y validar tokens
meziantou
1
El enlace está bien. UserManager
Pones
esto causa 'No se pudo cargar el tipo' System.Security.Cryptography.DpapiDataProtector 'del ensamblaje en .netcore
TAHA SULTAN TEMURI
25

En ASP.NET Core hoy en día es posible configurar un servicio predeterminado en Startup.cs como este:

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

No es necesario llamar al DpapiDataProtectionProviderni nada por el estilo. DefaultTokenProviders () se encargará de la llamada a GenerateEmailConfirmationToken desde UserManager.

pisker
fuente
21

Además de la respuesta aceptada, me gustaría agregar que este enfoque no funcionará en los sitios web de Azure, obtendría CryptographicException en lugar de un token.

Para arreglarlo para Azure, implemente su propio IDataProtector: vea esta respuesta

Un poco más de detalle en la publicación del blog

trailmax
fuente
13

Mi solución :

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

Mi problema con este código resuelto.
Buena suerte amigos.

Amin Ghaderi
fuente
utilizando Microsoft.Owin.Security.DataProtection;
Amin Ghaderi
Tuve que usar DataProtectorTokenProvider <IdentityUser, string> en lugar de <User, string> para ambos genéricos. Además, el ID de usuario en GeneratePasswordResetToken es el ID de la cadena de guid y no el nombre de usuario o el correo electrónico.
Dan Randolph
7

En caso de que alguien más cometa el mismo error que yo. Intenté hacer una función como la que se muestra a continuación y, efectivamente, el error "No se ha registrado ningún IUserTokenProvider". se había ido. Sin embargo, tan pronto como traté de usar el enlace generado desde "callbackUrl", recibí el error "Token no válido". Para que funcione, debe obtener HttpContext UserManager. Si está utilizando una aplicación ASP.NET MVC 5 estándar con cuentas de usuario individuales, puede hacerlo como se muestra a continuación.

Código que funciona:

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();
     }

Primero intente que no funciona, No IUserTokenProvider is registered.se ha ido pero se obtiene la URL creada 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
fuente
5

Según pisker arriba

En startup.cs puedes usar

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

En .net core 2.0, es posible que deba agregar a startup.cs:

using Microsoft.AspNetCore.Identity;

Esto funcionó bien para mi.

ScottC
fuente
1
Creo que es importante recordar que esta es una solución Asp .NET Core, no funcionará con Asp .NET Framework.
Machado
3

Al modificar los archivos de identidad de .NET Core, me encontré con este error:

NotSupportedException: No está registrado ningún IUserTwoFactorTokenProvider llamado 'Predeterminado'.

los

Microsoft.AspNetCore.Identity.UserManager.GenerateUserTokenAsync

La función no pudo generar un token porque no había ningún proveedor disponible al registrar un nuevo usuario. ¡Sin embargo, este error tiene una solución fácil!

Si eres como yo, cambiaste AddDefaultIdentityel Startup.csarchivo a AddIdentity. Quería implementar mi propio usuario que heredó del usuario base. Al hacer esto, perdí los proveedores de tokens predeterminados. La solución fue volver a agregarlos con AddDefaultTokenProviders().

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

Después de esa solución, ¡todo volvió a funcionar!

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

Yawar Ali
fuente
1

Recibí el mismo error después de actualizar Identity y descubrí que era porque estaba usando Unity.

Vea este hilo de preguntas sobre la solución: Registre IAuthenticationManager con Unity

También a continuación para referencia rápida:

Esto es lo que hice para que Unity funcionara bien con ASP.NET Identity 2.0:

Agregué lo siguiente al RegisterTypesmétodo en la UnityConfigclase:

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());
Robar
fuente
1
Seguí esto, pero no funcionó (para GeneratePasswordResetToken- pero obtuve el mismo error de "No hay IUserTokenProvider registrado"). Después de añadir container.RegisterType<ApplicationUserManager>( new InjectionFactory(c => HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>()));a UnityConfig.cs, funcionó.
0

en IdentityConfig.cs, agregue su opción de dos factores:

        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
fuente