I need to GenerateEmailConfirmationTokenAsync, and must implement IUserTokenProvider. I drive class UserManager : AbpUserManager<Tenant, Role, User>, IUserTokenProvider<User, long>
implememted the interface public Task<string> GenerateAsync(string purpose, UserManager<User, long> manager, User user) { Guid resetToken = Guid.NewGuid(); user.PasswordResetToken = resetToken; manager.UpdateAsync(user); return Task.FromResult<string>(resetToken.ToString()); }
public Task<bool> IsValidProviderForUserAsync(UserManager<User, long> manager, User user)
{
if (manager == null) throw new ArgumentNullException();
else
{
return Task.FromResult<bool>(manager.SupportsUserPassword);
}
}
public Task NotifyAsync(string token, UserManager<User, long> manager, User user)
{
return Task.FromResult<int>(0);
}
public Task<bool> ValidateAsync(string purpose, string token, UserManager<User, long> manager, User user)
{
return Task.FromResult<bool>(user.PasswordResetToken.ToString() == token);
}
added a property PasswordResetToken to User : AbpUser<Tenant, User>
But get Error, DbContext' context has changed since the database was created. Could you explain how to implement IUserTokenProvider, for usermanager
9 Answer(s)
-
0
It seems that you changed User entity and you need to add code first migration. Did you try "add-migration" command?
-
0
yes, I changed User entity and added Add-Migration ...and update-database -verbos... updated database wirh update-database -verbos... , its woriking now but get Error for this statement:
var pass = _userManager.ResetPassword(user.Id, resetToken.ToString(), new PasswordHasher().HashPassword("1q2w3e4r"));
the error is No IUserTokenProvider is registered.
-
0
now it works <a class="postlink" href="http://stackoverflow.com/questions/22629936/no-iusertokenprovider-is-registered">http://stackoverflow.com/questions/2262 ... registered</a>
UserManager.UserTokenProvider = new DataProtectorTokenProvider<User, long>(provider.Create("EmailConfirmation")) as IUserTokenProvider<User, long>; var code = await _userManager.GenerateEmailConfirmationTokenAsync(user.Id);
-
0
For hosting on Azure websites, the DpapiDataProtectionProvider cannot be used.
Taken from this source: [http://goo.gl/ScdYP5])
Here is the solution that worked for me in ABP:
Added to Startup.cs
//Global internal static IDataProtectionProvider DataProtectionProvider { get; private set; }
Added to Configuration
public void Configuration(IAppBuilder app) { ... DataProtectionProvider = app.GetDataProtectionProvider(); }
Instantiated in Account Controller :
var dataProtectionProvider = Startup.DataProtectionProvider; _userManager.UserTokenProvider = new DataProtectorTokenProvider<User, long>(dataProtectionProvider.Create("ASP.NET Identity")) as IUserTokenProvider<User, long>; var resetcode = await _userManager.GeneratePasswordResetTokenAsync(user.Id); var emailcode = await _userManager.GenerateEmailConfirmationTokenAsync(user.Id); //use either token as needed ...
-
0
Is it possible to have this logic in the Application layer? I would much rather have the email confirmation tokens being generated there then having clients do it.
-
0
Hi,
@TInman, thanks a lot for your solution, it is really helpful. @djfuzzy, I think you can gneerate tokens in the application layer, because you can use UserManager in application layer. But you need to set userManager's UserTokenProvider in web layer (probably in your web module).
-
0
<cite>ismcagdas: </cite> @djfuzzy, I think you can gneerate tokens in the application layer, because you can use UserManager in application layer. But you need to set userManager's UserTokenProvider in web layer (probably in your web module).
How would this work for clients of the Web API? It sounds like having the Application layer being dependent on the Web layer defies the SOLID principles of programming. I don't want to have each client having to generate the token.
-
0
Hi @difuzzy,
What do you mean by clients of Web API? Browsers, mobile apps.. which calls Web API services remotely. If so, no problem, token provider will be valid since it's assigned in Web/WebApi layer, in Startup class: <a class="postlink" href="https://github.com/aspnetzero/aspnet-zero/blob/dev/src/MyCompanyName.AbpZeroTemplate.Web/App_Start/Startup.cs#L43">https://github.com/aspnetzero/aspnet-ze ... tup.cs#L43</a>
Beside that, if you worry about "good layering", you're right. Because, if you develop a Desktop application and want to use application layer (and don't use web/webapi layer), then tokenprovider will not be defined and you will get exception if you generate password reset token using UserManager.GeneratePasswordResetTokenAsync. That means, a functionality in application layer, indirectly depends on the web layer and it has not a built-in fallback mechanism (to allow work without web layer).
Why we did it like that? Because this is the most common way of getting a valid data protection validator, OWIN provides it to us. We haven't searched for another solution.
So, it's actually not a problem for you, but if you care about it, please create an issue here and we search for a better way: <a class="postlink" href="https://github.com/aspnetboilerplate/module-zero/issues/new">https://github.com/aspnetboilerplate/mo ... issues/new</a>
Thanks a lot.
-
0
<cite>hikalkan: </cite> Hi @difuzzy,
What do you mean by clients of Web API? Browsers, mobile apps.. which calls Web API services remotely. If so, no problem, token provider will be valid since it's assigned in Web/WebApi layer, in Startup class: <a class="postlink" href="https://github.com/aspnetzero/aspnet-zero/blob/dev/src/MyCompanyName.AbpZeroTemplate.Web/App_Start/Startup.cs#L43">https://github.com/aspnetzero/aspnet-ze ... tup.cs#L43</a>
Beside that, if you worry about "good layering", you're right. Because, if you develop a Desktop application and want to use application layer (and don't use web/webapi layer), then tokenprovider will not be defined and you will get exception if you generate password reset token using UserManager.GeneratePasswordResetTokenAsync. That means, a functionality in application layer, indirectly depends on the web layer and it has not a built-in fallback mechanism (to allow work without web layer).
Why we did it like that? Because this is the most common way of getting a valid data protection validator, OWIN provides it to us. We haven't searched for another solution.
So, it's actually not a problem for you, but if you care about it, please create an issue here and we search for a better way: <a class="postlink" href="https://github.com/aspnetboilerplate/module-zero/issues/new">https://github.com/aspnetboilerplate/mo ... issues/new</a>
Thanks a lot.
No that all makes sense. You're right, I should be able to generate a token in WebAPI. I should be good to go. Thanks!