Online Tool Consumer now supports Twitter, Facebook, Google, and Microsoft Live login

My sample tool consumer web site is based on the ASP.NET MVC 4 Web Application Template. I chose to start with a template so I could get right to the stuff that I find interesting and not worry too much about the navigation plumbing. The template includes several cool features such as a layout that adapts well to mobile devices and compatibility with Azure web sites.

Last night I took advantage of another feature of the template: built in support for OpenID and OAuth. That means you can now log in using your Twitter, Facebook or Google account. If you already have an account on the Consumer site, go to your Account page and simply add your Twitter, Facebook or Google account. It will be connected to your existing account and then you can log in directly or with your external account. If you don’t have an account on the Consumer site, you can create one without registering first by logging in with the external account. You will be registered in the process.

Adding the support was easy: 1. Sign up for developer accounts (typically that just meant adding developer role to my existing account), 2. Register the Consumer web site on Azure, 3. Copy and paste the keys and secrets into App_Start\AuthConfig.cs (you won’t find them in the source code…I don’t want to share my secrets). That took about 20 minutes, then 2 more to build and publish the site to Azure.

Once that was working, I made a few changes to AccountController to better integrate the experience. First, I changed ExternalLoginConfirmation so that if a new account is created in Consumer (i.e. the user is logging in for the first time using an external system and creating an account on the fly) the new user gets the Teacher role (so they can create assignments) and they are redirected to their Profile page so they can select their schools and choose their privacy settings.

OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
if (OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false))
{
    // Add the user to Teacher role by default
    Roles.AddUserToRole(model.UserName, UserRoles.TeacherRole);
}
return RedirectToAction("Edit", "User", routeValues: new { id = WebSecurity.GetUserId(model.UserName) });

The second change was to get the user’s name and email address from the external system. To do that I look in the AuthenticationResult captured by ExternalLoginCallback. OAuthWebSecurity puts all the data that is sent with the callback into a dictionary called ExtraData. I look in that dictionary for name and email keys. If I find any, I add them to the RegisterExternalLoginModel so ExternalLoginConfirmation can use them to create a new account.

First collect the name and email address in ExternalLoginCallback

if (result.ExtraData.ContainsKey("email"))
    email = result.ExtraData["email"];
if (result.ExtraData.ContainsKey("firstname"))
    firstname = result.ExtraData["firstname"];
if (result.ExtraData.ContainsKey("lastname"))
    lastname = result.ExtraData["lastname"];
if (result.ExtraData.ContainsKey("name"))
{
    var name = result.ExtraData["name"];
    var names = name.Split(' ');
    if (names.Length == 1)
        lastname = name;
    if (names.Length > 1)
    {
        firstname = names[0];
        lastname = string.Join(" ", names.Skip(1).ToList());
    }
}

return View("ExternalLoginConfirmation", 
    new RegisterExternalLoginModel 
    { 
        UserName = result.UserName, 
        ExternalLoginData = loginData,
        Email = email,
        Firstname = firstname,
        Lastname = lastname
    });

Then use them in ExternalLoginConfirmation if a new account is created

// Insert name into the profile table
user = new User 
{ 
    UserName = model.UserName,
    Email = model.Email,
    FirstName = model.Firstname,
    LastName = model.Lastname
};
db.Users.Add(user);

All the changes are checked into CodePlex. I’m really happy I started with a template. The entire process of signing up for accounts, enabling OpenID/OAuth, and customizing the integration took about an hour. I don’t see how that would be possible without starting from a solid base.

This entry was posted in Uncategorized and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.