23 Sep

Create an ASP.NET MVC 5 App with Facebook and Google OAuth2 and OpenID Sign-on (C#)

This tutorial shows you how to build an ASP.NET MVC 5 web application that enables users to log in usingOAuth 2.0 or OpenID with credentials from an external authentication provider, such as Facebook, Twitter, Microsoft, or Google. For simplicity, this tutorial focuses on working with credentials from Facebook and Google.
Enabling these credentials in your web sites provides a significant advantage because millions of users already have accounts with these external providers. These users may be more inclined to sign up for your site if they do not have to create and remember a new set of credentials.
The tutorial also shows how to add profile data for the user, and how to use the Membership API to add roles.

Getting Started

Start by installing and running Visual Studio Express 2013 RC for Web or Visual  Studio 2013 RC.
Click New Project from the Start page, or you can use the menu and select File,  and then New Project.

Creating Your First Application

 Click New Project, then select Visual C#  on the left, then Web and then select ASP.NET  Web Application. Name your  project “MvcAuth” and then click OK.

In the New ASP.NET Project dialog, click MVC and then click Configure Authentication.

In the Configure Authentication  dialog, keep the default  Individual User Accounts, and  then click OK.

Back in the New ASP.NET Project dialog, Click  Create Project. Press F5  or Control F5 to run the  application. In the image below, the  port number is 1234. When you run the application, you’ll see a  different port number.
Depending on the size of your browser window,  you might need to click the navigation icon to see the Home,AboutContactRegister and Log in links.

Enable the Google OpenID provider
Open the App_StartStartup.Auth.cs file and remove the comment  characters in //app.UseGoogleAuthentication();  to  enable Google authentication.
public void ConfigureAuth(IAppBuilder app)
{
   
// Enable the application to use a cookie to store information for the signed in user
    app
.UseApplicationSignInCookie();
    
   
// Enable the application to use a cookie to temporarily store information about a user logging in with a third party login provider
    app
.UseExternalSignInCookie();

   
// Uncomment the following lines to enable logging in with third party login providers
   
//app.UseMicrosoftAccountAuthentication(
   
//    clientId: "",
   
//    clientSecret: "");

   
//app.UseTwitterAuthentication(
   
//   consumerKey: "",
   
//   consumerSecret: "");

   
//app.UseFacebookAuthentication(
   
//   appId: "",
   
//   appSecret: "");

   
app.UseGoogleAuthentication();
}
Press Control F5 to build and run the application. Click the Log in  link.
Under Use another service to log in, click Google.
You will be redirected to the google site where you will enter your  credentials. After you enter your credentials,  you will be prompted to give the following permissions to the web application you just created:
  • View basic information about your account.
  • View your email address
Click Accept.
You will now be redirected back to the Register page of  MvcAuth application where you can register your Google account with the MvcAuth  application.  Notice the URL in the image above contains openid2.  Unlike OAuth2providers, OpenID  providers don’t require you to create an application with the authentication  provider.
Click Register to add the user name and your  Google account information to the MvcAuth application.
Next you are redirected back to the home page where you  can see your name and a Log off link.
That’s all you need to add Google as an identity provider.

Setting up SSL in the Project

To connect to Facebook, you will need to set up IIS-Express to use SSL. Even  though Google doesn’t require you to use SSL to log in, it’s a security best  practice to require SSL in your application.  It’s important to keep using SSL after login and not drop back to HTTP, your login cookie is just as  secret as your username and password, and without using SSL  you’re sending  it in clear-text across the wire. Besides, you’ve already taken the time to  perform the handshake and secure the channel (which is the bulk of what makes  HTTPS slower than HTTP) before the MVC pipeline is run, so redirecting back to  HTTP after you’re logged in won’t make the current request or future requests  much faster.
  1. In Solution Explorer, click the MvcAuth  project.
  2. Enter the F4 key to show the project properties. Alternatively, from the View menu you can select theProperties Window.
  3. Change SSL Enabled to True.
  4. Copy the SSL URL (which will be https://localhost:44300/ unless you’ve created other SSL projects).
  5. In Solution Explorer, right click the MvcAuth project and select Properties.
  6. Select the Web tab, and then paste the SSL URL into the Project Url  box. Save the file (Ctl+S). You will need this URL to configure  Facebook.

Creating the app in Facebook and connecting the app to the project

 For Facebook OAuth2 authentication, you need to copy to your project some settings from an application that you create in Facebook.
  1. In your browser, navigate to https://developers.facebook.com/apps and log in by entering your Facebook credentials.
  2. If you aren’t already registered as a Facebook developer, click Register as a Developer and follow the directions to register.
  3. Click Create New App.
  4. Enter an App Name and then click Continue.
    This must be unique across Facebook. The App Namespace is the part of the URL that your App will use to access  the Facebook application for authentication (for example, https://apps.facebook.com/{App Namespace}). If you don’t specify an App Namespace, the App ID will be used for the URL. The App ID is a long system-generated number that you will see in the next step.
  5. On the Basic Settings page for the app, set the Site  URL.
    You’ll use the App ID and  App Secret settings in the next step.
    In the image above,  Sandbox Mode is enabled, therefore you will only be able to authenticate using the email alias you have registered. Other users and test  accounts will not be able to register. You can grant other Facebook accounts  access to the application on the Facebook Developer Roles  tab. Attempting to authenticate with a non-registered account when the  application is in sandbox mode will produce the following error:

    Value cannot be null. Parameter name: id

    Description: An unhandled  exception occurred during the execution of the current web request. Please  review the stack trace for more information about the error and where it  originated in the code. 

  6. In Visual Studio, open App_StartStartup.Auth.cs.
  7. Copy and paste the AppId and App Secret  into the UseFacebookAuthentication method. Be sure to remove the comment  characters. The AppId and App Secret values shown below are samples and will not work.
    public void ConfigureAuth(IAppBuilder app)
    {
       
    // Enable the application to use a cookie to store information for the signed in user
       
    // and to use a cookie to temporarily store information about a user logging in with a third party login provider
        app
    .UseSignInCookies();

       
    // Uncomment the following lines to enable logging in with third party login providers
       
    //app.UseMicrosoftAccountAuthentication(
       
    //    clientId: "",
       
    //    clientSecret: "");

       
    //app.UseTwitterAuthentication(
       
    //   consumerKey: "",
       
    //   consumerSecret: "");

       
    app.UseFacebookAuthentication(
           appId
    : "000000000000000",
           appSecret
    : "000000000000000");


        app
    .UseGoogleAuthentication();
    }
  8. Click Save Changes.
  9. Press CTRL+F5 to run the application.
When you run the application in Internet Explorer (IE), Firefox, or Page Inspector, you get a security certificate warning. This is because the  certificates used by IIS Express are not trusted by browsers. You can dismiss these  warnings on your development machine. When you deploy the application to Windows  Azure, the SSL certificates are trusted and you won’t get any warnings. In IE, click Continue to this website (not recommended). In Chrome, click Proceed anyway.

Under Use another service to log in. click Facebook.
Enter your Facebook credentials.
You will be prompted to grant permission for the application to access your profile and friend list.
You are now logged in. You can now register this account with the application.
When you register, an entry is added to the Users table of the  membership database.

Examine the Membership Data

In the View menu, click Server Explorer.
Expand DefaultConnection (MvcAuth), expand Tables, right click AspNetUsers and click Show Table Data.

Adding Profile Data to the User Class

In this section you’ll add birth date and home town to the user data during  registration, as  shown in the following image.
Open the ModelsIdentityModels.cs file and add birth date and home  town properties:
using Microsoft.AspNet.Identity.EntityFramework;
using System;

namespace MvcAuth.Models
{
   
public class ApplicationUser : User
   
{
       
public string HomeTown { get; set; }
       
public DateTime ? BirthData { get; set; }

   
}

   
public class ApplicationDbContext : IdentityDbContextWithCustomUser<ApplicationUser>
   
{
   
}
}
Open the  ModelsAccountViewModels.cs file  and the set  birth date and home town properties inExternalLoginConfirmationViewModel.
public class ExternalLoginConfirmationViewModel
{
   
[Required]
   
[Display(Name = "User name")]
   
public string UserName { get; set; }
   
public string HomeTown { get; set; }
   
public DateTime ? BirthData { get; set; }

}
Open the ControllersAccountController.cs file and update the ExternalLoginConfirmation action method as shown:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
{
   
if (User.Identity.IsAuthenticated)
   
{
       
return RedirectToAction("Manage");
   
}

   
if (ModelState.IsValid)
   
{
       
// Get the information about the user from the external login provider
       
var user = new ApplicationUser()
       
{
           
UserName = model.UserName,
           
BirthData = model.BirthData,
           
HomeTown = model.HomeTown
       
};

       IdentityResult result = await IdentityManager.Authentication.CreateAndSignInExternalUserAsync(
           
// AuthenticationManager, new User(model.UserName));
           
AuthenticationManager, user);

       
if (result.Success)
       
{
           
return RedirectToLocal(returnUrl);
       
}
       
else
       
{
           
AddErrors(result);
       
}
   
}

   
ViewBag.ReturnUrl = returnUrl;
   
return View(model);
}
Change the AccountController constructor to pass an ApplicationDbContext parameter:
public AccountController()
{
   
IdentityManager = new AuthenticationIdentityManager(
       
new IdentityStore(new ApplicationDbContext()));
}
Add birth date and home town to the ViewsAccountExternalLoginConfirmation.cshtml  file:
@model MvcAuth.Models.ExternalLoginConfirmationViewModel
@{
    ViewBag.Title = "Register";
}


   



@ViewBag.Title.

   

Associate your @ViewBag.LoginProvider account. @using (Html.BeginForm(“ExternalLoginConfirmation”, “Account”, new { ReturnUrl = ViewBag.ReturnUrl })) {     @Html.AntiForgeryToken()     @Html.ValidationSummary(true)    

       

Association Form       

class=“text-success”>            You’ve successfully authenticated with @ViewBag.LoginProvider

.             Please enter a user name for this site below and click the Register button to finish             logging in.                 @Html.LabelFor(m => m.UserName)         @Html.TextBoxFor(m => m.UserName)         @Html.ValidationMessageFor(m => m.UserName)        
/>                @Html.LabelFor(m => m.HomeTown)         @Html.TextBoxFor(m => m.HomeTown)         @Html.ValidationMessageFor(m => m.HomeTown)        
/>           @Html.LabelFor(m => m.BirthData)         @Html.TextBoxFor(m => m.BirthData)         @Html.ValidationMessageFor(m => m.BirthData)        
/>
        type=“submit” class=“btn” value=“Register” />   
} @section Scripts {     @Scripts.Render(“~/bundles/jqueryval”) }

Delete the membership database so you can again register your Facebook account with your application and verify you can add the new birth date and home town profile information.
From Solution Explorer, click the Show All Files icon, then right click Add_Dataaspnet-MvcAuth-.mdfand click Delete.
From the Tools menu, click Library Package Manger,  then click Package Manager Console (PMC). Enter the following  commands in the PMC.
  1. Enable-Migrations
  2. Add-Migration BirthDate
  3. Update-Database
Run the application and use FaceBook to log in and register a user. 

The Membership Database

In this section you will examine the membership database and use the new membership API to add a user and a role.
Open the  MvcAuthGlobal.asax.cs file and replace the contents with  the following:
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

using System.Threading.Tasks;
using MvcAuth.Models;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using System.Threading;
using Microsoft.AspNet.Identity.EntityFramework;


namespace MvcAuth
{
public class MvcApplication : System.Web.HttpApplication
{
async Task AddRoleAndUser()
{
AuthenticationIdentityManager IdentityManager = new AuthenticationIdentityManager(
new IdentityStore(new ApplicationDbContext()));

var role = new Role("Role1");
IdentityResult result = await IdentityManager.Roles.CreateRoleAsync(role, CancellationToken.None);
if (result.Success == false)
return false;

var user = new ApplicationUser() { UserName = "user1" };
result
= await IdentityManager.Users.CreateLocalUserAsync(user, "Password1");
if (result.Success == false)
return false;

result
= await IdentityManager.Roles.AddUserToRoleAsync(user.Id, role.Id, CancellationToken.None);
return result.Success;
}


protected async void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
bool x = await AddRoleAndUser();
}
}
}
Set a break point in the AddRoleAndUser method, and then press  F5 to debug the application.  If IIS Express is running and the application  has not timed out, the Application_Start method will not be called  and the break point will not be hit. To restart IIS Express, you can either exit  and restart Visual Studio, or you can right click the IIS Express icon in the  task notification area and click Exit.
Step through the  AddRoleAndUser method. The first time  this method is called, the new user and role are created. On subsequent calls,  the method will return false on the CreateRoleAsync call (because “Role1” exists). The  AddRoleAndUser code above shows how to use the new membership API and is  not meant to be the mechanism for adding new users and roles.

Examine the Membership Data

In the View menu, click Server Explorer.
Right click AspNetUsers and click Show Table Data.
In addition to the Facebook and Google accounts you added, you can see the  user1 account you added using the membership API. The Discriminator column was added by Entity Framework because the ApplicationUserclass is derived from the User class. You can read about this in Implementing Inheritance with the Entity Framework in an ASP.NET MVC App.

Require Authorization

Open the ControllersHomeController.cs file and add the following Authorize attribute to the About method.
[Authorize(Roles = "Role1")]
public ActionResult About()
{
   
ViewBag.Message = "Your application description page.";
   
return View();
}
The Authorize attribute will prevent users who are not members of the Role1 role from accessing this method. A user who is not a member of the Role1  role will be redirected to the Login page (where they  have a chance to login as a user who is a member of the Role1 role.)
Run the application and navigate to the About method.   Using the Facebook or Google account you created, you will be redirected to the  Login page. Login in as  user1 (password “Password1”) and you  will be able to access the About page.

Remove Local ASP.NET Membership Registration

The current local ASP.NET membership registration in the project does not  provide support for password resets and it does not verify that a human is  registering (for example with a CAPTCHA). Once a user is authenticated using one of the third party  providers, they can register and the third party provider has support for  password reset.
Remove or comment out the Register link in the ViewsShared_LoginPartial.cshtml  file.
{
   
<ul class="nav pull-right">
       
@*<li>@Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li>*@
       


  • @Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>
       
    </ul>
    }
     In the AccountController, replace the contents of the GET and POST Register methods  with the followingredirect:
    return RedirectToAction("Index", "Home");
     This will prevent bots and  anonymous users from registering.

    Logging off your App and Logging in With Another Account

    If you use the Log off link in your ASP.NET MVC app, then  select Log in, and then Use another service to long in  and select Facebook, you will be immediately logged in to the  Facebook account you had previously logged out of.  In order to log out you must navigate to Facebook using the selected  browser, and log out of Facebook.

    Resetting the Membership Database to Test Registration

    If you’d like to test the registration code you’ll need to delete the entries  in the membership database. An easy way to do this is with the following commands in the Package Manager Console.

    Update-Database -TargetMigration:0
    Update-Database 

    Next Steps

    For an excellent explanation of how ASP.NET External Authentication Services  work, see Robert McMurray’sExternal Authentication Services. Robert’s article also goes into detail in  enabling Microsoft and Twitter authentication.
    Share this

    Leave a reply