tugberkugurlu / AspNet.Identity.RavenDB

Fully asynchronous, new and sweet ASP.NET Identity implementation for RavenDB
MIT License
42 stars 28 forks source link

Cannot ConfirmEmail with new 2.0 #31

Open jakvike opened 10 years ago

jakvike commented 10 years ago

I am attempting to ConfirmEmail. I have implemented Registration but when i confirm the email, I receive 'Cannot set the confirmation status of the e-mail because user doesn't have an e-mail as RavenUserEmail document.'

I then attempted to extend RavenUser by creating a new class that inherits from RavenUser. Within this class i have a property RavenUserEmail and create it when I create the RavenUser within the Registration. When i attempt to Confirm the email, I receive an error 'Cannot set the confirmation status of the e-mail because user doesn't have an e-mail.'

This is the code within my AccountController:

// GET: /Account/ConfirmEmail [AllowAnonymous] public async Task ConfirmEmail(string userId, string code) { var result = await UserManager.ConfirmEmailAsync(userId, code); return View(); }

Chaddeus commented 10 years ago

I get the same exact error.

I initialize my IAsyncDocumentSession like so:

ravenSession.Advanced.UseOptimisticConcurrency = true;
RavenSession = ravenSession;

var provider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("Example");
UserManager = new UserManager<ApplicationUser>(new RavenUserStore<ApplicationUser>(ravenSession))
{
    UserTokenProvider =
        new Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider<ApplicationUser>(
            provider.Create("EmailConfirmation"))
};

A new user is created like so:

var user = new ApplicationUser(model.UserName) {
    DateRegistered = DateTime.UtcNow,
    DateLastConnected = DateTime.UtcNow
};
user.SetEmail(model.Email);

var result = await UserManager.CreateAsync(user, model.Password);

I generate the email with callback url to confirm email like so:

var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code }, Request.Url.Scheme);

SendVerificationEmail(user, callbackUrl);

The SendVerification() method is simply a wrapper, I use Mandrill to send my emails. The callback url is created fine, and the email is received by users fine too.

However, when a user clicks the callback url, they get the following error:

Cannot set the confirmation status of the e-mail because user doesn't have an e-mail as RavenUserEmail document.

The code to verify email is quite simple:

var result = await UserManager.ConfirmEmailAsync(userId, code);

if (result.Succeeded)
    return View("ConfirmEmail");
Chaddeus commented 10 years ago

Got some time to dig into this... turns out you need to create the RavenUserEmail yourself. In your AccountController,when you register a user, create the RavenUserEmail at the same time:

var email = new RavenUserEmail(user.Email, user.Id);
await RavenSession.StoreAsync(email);
await RavenSession.SaveChangesAsync();

Keep in mind that when/if you need to delete a user, you'll need to delete the RavenUserEmail document too.

*\ Perhaps this should be handled by the CreateAsync() and DeleteAsync() methods?