I have a MVC and a web API projects, authenticated using ASP.NET MVC Web API Identity (OWIN Security).
I added an email confirmation to the Register
function that works properly but I'm not sure how to check if emailConfirmed = true
before logging in because there is no an explicit Login function on Web API Identity, it's implicit.
I know Microsoft has a good reason to deeply encapsulate the authorization functionality, but isn't there a way to achieve that?
Please advise.
This is my Register function:
[AllowAnonymous]
[Route("Register")]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
try
{
var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
var callbackUrl = new Uri(Url.Link("ConfirmEmailRoute", new { userId = user.Id, code = code }));
var email = new Email();
email.To = user.Email;
email.From = "[email protected]";
email.Subject = "Please confirm your account";
email.Body = "Please confirm your account by clicking this link: <a href=\"" + callbackUrl + "\">link</a>";
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
var data = JsonConvert.SerializeObject(email);
WebClient client = new WebClient();
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
var resp = client.UploadString(@"http:...", data);
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
return Ok();
}
After a lot of researches I have found the answer.
I added the following code that checks if the emailconfirmed = true
:
var userid = userManager.FindByEmail(context.UserName).Id;
if (!userManager.IsEmailConfirmed(userid))
{
context.SetError("invalid_grant", "Email registration wasn't confirmed.");
return;
}
To the GrantResourceOwnerCredentials
function in the ApplicationOAuthProvider.cs
class (under the Provider folder).
This is the entire function:
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
////Added code here
var userid = userManager.FindByEmail(context.UserName).Id;
if (!userManager.IsEmailConfirmed(userid))
{
context.SetError("invalid_grant", "Email registration wasn't confirmed.");
return;
}
////
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
OAuthDefaults.AuthenticationType);
ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = CreateProperties(user.UserName);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
That works perfectly and prevents the user from logging in before he confirmed the registration email.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With