问题
I recently updated Asp.Net Identity Core of my application form 1.0 to 2.0.
There are new features which I wanted to try like GenerateEmailConfirmationToken, etc.
I'm using this project as a reference.
When the user tries to register, I get error during the execution of Post method of 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 the line
var code = _userManager.GenerateEmailConfirmationToken(user.Id);
I get error saying:
No IUserTokenProvider is registered.
For now, I just wanted to see what kind of code it generates.
Is there some change I need to make to my ApplicationUser class that inherits from IdentityUser class?
Or is there something I need to change to get those function work?
回答1:
You have to specify a UserTokenProvider to generate a 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"));
You should also read this article: Adding Two Factor Authentication to an Application Using ASP.NET Identity.
回答2:
In ASP.NET Core it's nowadays possible to configure a default service in the Startup.cs like this:
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddDefaultTokenProviders();
There is no need to call the DpapiDataProtectionProvideror anything like that. The DefaultTokenProviders() will take care of the call to GenerateEmailConfirmationToken from the UserManager.
回答3:
In addition to the accepted answer, I'd like to add that this approach will not work in Azure Web-Sites, you'd get CryptographicException instead of a token.
To get it fixed for Azure, implement your own IDataProtector: see this answer
Slightly more detail in blog-post
回答4:
My solution :
var provider = new DpapiDataProtectionProvider("YourAppName");
UserManager.UserTokenProvider = new DataProtectorTokenProvider<User, string>(provider.Create("UserToken"))
as IUserTokenProvider<User, string>;
My problem with this code solved.
Good luck friends.
回答5:
In case anyone else makes the same mistake that I did. I tried to make a function like the one below and sure enough the error "No IUserTokenProvider is registered." was gone. However as soon as I tried to use the link generated from "callbackUrl" I got the error "Invalid token." In order for it to work you need to get the HttpContext UserManager. If you are using a standard ASP.NET MVC 5 application with individual user accounts you can do it like below..
Code that works:
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();
}
First try that does not work, No IUserTokenProvider is registered. is gone but the URL created gets 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();
}
回答6:
As per pisker above
In startup.cs you can use
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddDefaultTokenProviders();
In .net core 2.0 you may need to add to the startup.cs:
using Microsoft.AspNetCore.Identity;
This worked fine for me.
回答7:
While modifying .NET Core's Identity files, I stumbled upon this error:
NotSupportedException: No IUserTwoFactorTokenProvider named 'Default' is registered.
The
Microsoft.AspNetCore.Identity.UserManager.GenerateUserTokenAsync
function couldn't generate a token because no provider was available upon registering a new user. This error has an easy fix though!
If you're like me, you changed AddDefaultIdentity in the Startup.cs file to AddIdentity. I wanted to implement my own user that inherited from the base user. By doing this I lost the default token providers. The fix was to add them back with AddDefaultTokenProviders().
services.AddIdentity<User, UserRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
After that fix, everything worked again!
source: https://mattferderer.com/NotSupportedException-No-IUserTwoFactorTokenProvider-tuser-named-default-registered
回答8:
You may also be intrested in looking here:
How to implement a TokenProvider in ASP.NET Identity 1.1 nightly build?
to use the default token provider implementation from Microsoft.Identity.Owin package
回答9:
I got the same error after updating Identity, and found that it was because I was using Unity.
See this question thread on the solution: Register IAuthenticationManager with Unity
Also below for quick reference:
Here is what I did to make Unity play nice with ASP.NET Identity 2.0:
I added the following to the
RegisterTypesmethod in theUnityConfigclass: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());
回答10:
in IdentityConfig.cs, Add your twofactor option:
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"));
}
来源:https://stackoverflow.com/questions/22629936/no-iusertokenprovider-is-registered