Since last week I have been learning and working with ASP.NET MVC Beta. I found a lot of interesting and easy-to-use things which convinced me that it is a good choice for web development. The Membership Framework is one of those.
Unfortunately a more-than-common feature like user e-mail verification is not built-in so I had to do it myself. Here are the three easy steps you should follow in order to add this functionality to your site:
Store the user as unapproved
We create the new user as usual, except for the value isApproved which we should set to false. This indicates that the user is on the database but is inactive and cannot log in (until we verify his or her e-mail).
1: // Attempt to register the user 2: MembershipCreateStatus createStatus; 3: MembershipUser newUser = Provider.CreateUser(username, password, email, pwQuestion, pwAnswer, false, null, out createStatus); 4: 5: if (newUser != null) 6: { 7: // The user was created successfully, we send the verification e-mail. 8: SendVerificationMail(newUser); 9: return Content("Your account have been created. Please check your e-mail to activate it."); 10: } 11: else 12: { 13: // There were errors, show them to the user. 14: ModelState.AddModelError("_FORM", ErrorCodeToString(createStatus)); 15: }
Prepare the verification e-mail
The most important thing in this part is to provide the user with a link to verify his or her account. The link must be difficult for anyone to create. In this example we will use the global unique identifier or guid which is a good trade-off between security and code simplicity. For more information about GUIDs you can check MSDN. We will see a way to enhance security later.
1: private void SendVerificationMail(MembershipUser user) 2: { 3: MailMessage email = new MailMessage( 4: "info@yourSite.com", 5: user.Email 6: ); 7: 8: Guid guid = (Guid)user.ProviderUserKey; 9: email.Subject = "Welcome!"; 10: email.Body = "Activation link: yourSite/controller/action/" + guid.ToString(); 11: 12: SmtpClient smtp = new SmtpClient("your_smtp"); 13: smtp.Credentials = CredentialCache.DefaultNetworkCredentials; 14: 15: try { 16: smtp.Send(email); 17: } 18: catch (Exception exc){ 19: // Handle exception 20: } 21: }
Note that the link points to some controller and action we have not defined yet. We can use an existing controller (maybe the AccounController) or a new one. We might also use a different URL routing, though I decided to keep the default for simplicity.
Verifying the link
One more step and we are ready to go live! Now we should receive the request and verify that the GUID is the right one. If everything is OK we approve the user.
1: public ActionResult Verify(string id) 2: { 3: Guid guid = new Guid(id); 4: MembershipUser user = Membership.GetUser(guid); 5: if (user != null && user.IsApproved == false) 6: { 7: user.IsApproved = true; 8: Membership.UpdateUser(user); 9: FormsAuth.SetAuthCookie(user.UserName, false); 10: } 11: else { 12: // Wrong GUID or user was already approved 13: } 14: 15: return View(); 16: }
And that’s all! Quite an interesting feature in very few and easy steps.
Enhancing security
Though using a Global Unique Identifier provides a quite secure environment sometimes Security is such an important matter that we should think in adding some more complications to those good hackers out there :-P.
A good option would be adding another parameter to the action, like an MD5 hash applied to the email or username, or a combination. Useful help is, again, on MSDN.