Click here to Skip to main content
15,886,664 members
Articles / Web Development / ASP.NET

Implement Facebook Login with OpenID Selector in MVC3

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
3 Sep 2012CPOL2 min read 24.4K   14   2
How to use the OpenId selector tool in an ASP.NET MVC3 application

In my last post, I explained how we can implement Facebook login with OpenId selector tool. In this post, I will explain how we can use that tool in an ASP.NET MVC3 application.

  1. Open Visual Studio 2010 go to File > New > Project > Web > ASP.NET MVC 3 application:

    Then choose Internet Application. Be sure to have Razor as your View engine and click OK:

  2. Download DotNetOpenAuth DLL and Updated OpenID Selector files that we will use.
    1. Add the DotNetOpenAuth.dll to references in your site.
    2. Copy all contents of openid-selector\css folder to the 'Content' folder.
    3. Copy images, images.large, images.small folders to the site 'Content' folder.
    4. Copy openid-jquery.js, openid-en.js files from openid-selector\js folder to 'Scripts' folder.

    Your Solution Explorer will look like this (see the highlighted portion):

  3. Go to Views > Shared > _Layout.cshtml and replace the <head> with this new head with new styles and scripts:
    HTML
    <head>
        <meta charset="utf-8" />
        <title>@ViewBag.Title</title>
        <link href="@Url.Content("~/Content/Site.css")" 
        rel="stylesheet" type="text/css" />
        <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" 
        type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" 
        type="text/javascript"></script>
        <link href="@Url.Content("~/Content/openid-shadow.css")" 
        rel="stylesheet" type="text/css" />
        <link href="@Url.Content("~/Content/openid.css")" 
        rel="stylesheet" type="text/css" />
        <script src="@Url.Content("~/Scripts/openid-jquery.js")" 
        type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/openid-en.js")" 
        type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" 
    type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" 
    type="text/javascript"></script>
     <script type="text/javascript" 
     src="https://connect.facebook.net/en_US/all.js"> </script>
       
        <script type="text/javascript">
            $(document).ready(function () {
                openid.init('openid_identifier');
            });
        </script>
    </head>
  4. Go to Models > AccountModels.cs, navigate to public class LogOnModel and Add OpenID attribute that we will use to hold the returned OpenID from OpenID-Selector.

    Your class will look like this:

    C#
    public class LogOnModel
    {
        [Display(Name = "OpenID")]
        public string OpenID { get; set; }
    
        [Required]
        [Display(Name = "User name")]
        public string UserName { get; set; }
    
        [Required]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }
    
        [Display(Name = "Remember me?")]
        public bool RememberMe { get; set; }
    }
    
  5. Go to Models > AccountModels.cs and add the following class to it:
    C#
    public class UserDetailsModel
    {
        public string OpenID { get; set; }
        public string ProviderUrl { get; set; }
        public string FriendlyIdentifier { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Dob { get; set; }
        public string Gender { get; set; }
        public string Email { get; set; }
    }
    
  6. Go to Views > Account > LogOn.cshtml. Replace all the markup with this one. This will integrate updated OpenID-Selector to LogOn View:
    HTML
    @model FBOpenIDMVC3.Models.LogOnModel
    
    @{
        ViewBag.Title = "Log On";    
    }
    <h2>
        Log On</h2>
    <p>
        Please enter your username and password. 
        @Html.ActionLink("Register", "Register")
        if you don't have an account.
    </p>
    <script type="text/javascript">
        $(document).ready(function () {
            // Init the SDK upon load
            window.fbAsyncInit = function () {
                FB.init({
                    appId: '188220747944294', // App ID
                    channelUrl: '//' + window.location.hostname + 
                    '/channel', // Path to your Channel File
                    scope: 'id,name,first_name,last_name,gender,email',
                    status: true, // check login status
                    cookie: true, // enable cookies to allow the server to access the session
                    xfbml: true   // parse XFBML
                });
            };
        });
        /*This Method will be invoked on lick on Facebook button*/
        function FBLogin() {
            FB.login(FBCallBack);
        }
        function FBCallBack(response) {
            if (response.authResponse) {
                // user has auth'd your app and is logged into Facebook
                FB.api('/me?fields=id,name,first_name,
                last_name,gender,email,birthday', function (userDetail) {
                    if (userDetail.name) {
                        var url = '@Url.Action("ShowUserDetails", 
                        "Account", new { OpenID = "_id_", 
                        FriendlyIdentifier = "_id_", 
                        FirstName = "_first_", LastName = "_last_", 
                        Dob = "_birthday_", Gender = 
                        "_gender_", Email = "_email_" })';
                        url = url.replace('_id_', userDetail.id);
                        url = url.replace('_id_', userDetail.id);
                        url = url.replace('_first_', userDetail.first_name);
                        url = url.replace('_last_', userDetail.last_name);
                        url = url.replace('_birthday_', userDetail.birthday);
                        url = url.replace('_gender_', userDetail.gender);
                        url = url.replace('_email_', userDetail.email);
                        window.location.href = url;
                    }
                });
            }
        }
        </script>  
    <form action="Authenticate?ReturnUrl=@HttpUtility.UrlEncode
    (Request.QueryString["ReturnUrl"])" 
    method="post" id="openid_form">
    <input type="hidden" name="action" value="verify" />
    <div>    
        <fieldset>
            <legend>Login using OpenID</legend>
            <div class="openid_choice">
                <p>
                    Please click your account provider:</p>
                <div id="openid_btns">
                </div>
            </div>
            <div id="openid_input_area">
                @Html.TextBox("openid_identifier")
                <input type="submit" value="Log On" />
            </div>
            <noscript>
                <p>
                    OpenID is service that allows you to 
                    log-on to many different websites using a single
                    indentity. Find out 
                    <a href="http://openid.net/what/">more about OpenID</a> and
                    <a href="http://openid.net/get/">how 
                    to get an OpenID enabled account</a>.</p>
            </noscript>
            <div>
                @if (Model != null)
                {
                    if (String.IsNullOrEmpty(Model.UserName))
                    {
                    <div class="editor-label">
                        @Html.LabelFor(model => model.OpenID)
                    </div>
                    <div class="editor-field">
                        @Html.DisplayFor(model => model.OpenID)
                    </div>
                    <p class="button">
                        @Html.ActionLink("New User ,Register", 
                        "Register", new { OpenID = Model.OpenID })
                    </p>
                    }
                    else
                    {
                        //user exist 
                    <p class="buttonGreen">
                        <a href="@Url.Action("Index", 
                        "Home")">Welcome , @Model.UserName, Continue..." </a>
                    </p>
                    }
                }
            </div>
        </fieldset>
    </div>
    </form>
    
    @Html.ValidationSummary(true, "Login was unsuccessful. 
    Please correct the errors and try again.")
    @using (Html.BeginForm())
    {
        <div>
            <fieldset>
                <legend>Or Login Normally</legend>
                <div class="editor-label">
                    @Html.LabelFor(m => m.UserName)
                </div>
                <div class="editor-field">
                    @Html.TextBoxFor(m => m.UserName)
                    @Html.ValidationMessageFor(m => m.UserName)
                </div>
                <div class="editor-label">
                    @Html.LabelFor(m => m.Password)
                </div>
                <div class="editor-field">
                    @Html.PasswordFor(m => m.Password)
                    @Html.ValidationMessageFor(m => m.Password)
                </div>
                <div class="editor-label">
                    @Html.CheckBoxFor(m => m.RememberMe)
                    @Html.LabelFor(m => m.RememberMe)
                </div>
                <p >
                    <input type="submit" value="Log On" />
                </p>
            </fieldset>
        </div>
    }
  7. Update the value of img_path in openid-jquery.js to '../Content/images/'.
  8. Now let us run the project, then click the [Log On] link, you will get something like this page:

  9. Now to implement Open ID using DotnetOpenAuth, Go to Controllers > AccountController.cs and add these usings:
    C#
    using DotNetOpenAuth.Messaging;
    using DotNetOpenAuth.OpenId;
    using DotNetOpenAuth.OpenId.RelyingParty;
    using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;

    Then, add the following code to AccountController.cs:

    C#
    private static OpenIdRelyingParty openid = new OpenIdRelyingParty();
    
    [ValidateInput(false)]
    public ActionResult Authenticate(string returnUrl)
    {
        var response = openid.GetResponse();
        if (response == null)
        {
            //Let us submit the request to OpenID provider
            Identifier id;
            if (Identifier.TryParse(Request.Form["openid_identifier"], out id))
            {
                try
                {
                    var request = openid.CreateRequest
                    (Request.Form["openid_identifier"]);
                    var fetch = new FetchRequest();
                    fetch.Attributes.Add(new AttributeRequest
                    (WellKnownAttributes.Contact.Email, true));
                    fetch.Attributes.Add(new AttributeRequest
                    (WellKnownAttributes.BirthDate.WholeBirthDate, true));
                    fetch.Attributes.Add(new AttributeRequest
                    (WellKnownAttributes.Person.Gender, true));
                    fetch.Attributes.Add(new AttributeRequest
                    (WellKnownAttributes.Name.First, true));
                    fetch.Attributes.Add(new AttributeRequest
                    (WellKnownAttributes.Name.Last, true));
                    request.AddExtension(fetch);
                    return request.RedirectingResponse.AsActionResult();
                }
                catch (ProtocolException ex)
                {
                    ViewBag.Message = ex.Message;
                    return View("LogOn");
                }
            }
    
            ViewBag.Message = "Invalid identifier";
            return View("LogOn");
        }
    
        //Let us check the response
        switch (response.Status)
        {
    
            case AuthenticationStatus.Authenticated:
                var fetch = response.GetExtension<FetchResponse>();
                var sFirstName = "";
                var sEmail = "";
                var sLastName = "";
                var sGender = "";
                var sDob = "";
                if (fetch != null)
                {
                    foreach (var vAtrrib in fetch.Attributes)
                    {
                        switch (vAtrrib.TypeUri)
                        {
                            case WellKnownAttributes.Name.First:
                                var firstNames = fetch.Attributes
                                [WellKnownAttributes.Name.First].Values;
                                sFirstName = firstNames.Count > 0 ? firstNames[0] : null;
                                break;
                            case WellKnownAttributes.Contact.Email:
                                var emailAddresses = fetch.Attributes
                                [WellKnownAttributes.Contact.Email].Values;
                                sEmail = emailAddresses.Count > 0 ? emailAddresses[0] : null;
                                break;
                            case WellKnownAttributes.Name.Last:
                                var lastNames = fetch.Attributes
                                [WellKnownAttributes.Name.Last].Values;
                                sLastName = lastNames.Count > 0 ? lastNames[0] : null;
                                break;
                            case WellKnownAttributes.Person.Gender:
                                var genders = fetch.Attributes
                                [WellKnownAttributes.Person.Gender].Values;
                                sGender = genders.Count > 0 ? genders[0] : null;
                                break;
                            case WellKnownAttributes.BirthDate.WholeBirthDate:
                                var doBs = fetch.Attributes
                                [WellKnownAttributes.BirthDate.WholeBirthDate].Values;
                                sDob = doBs.Count > 0 ? doBs[0] : null;
                                break;
                        }
                    }
                }
                var sFriendlyLogin = response.FriendlyIdentifierForDisplay;
                var lm = new UserDetailsModel
                {
                    OpenID = response.ClaimedIdentifier,
                    FriendlyIdentifier = sFriendlyLogin,
                    FirstName = sFirstName,
                    LastName = sLastName,
                    Dob = sDob,
                    Gender = sGender,
                    Email = sEmail
                };
                FormsService.SignIn(sEmail, false);
                return View("ShowUserDetails", lm);
    
            case AuthenticationStatus.Canceled:
                ViewBag.Message = "Canceled at provider";
                return View("LogOn");
            case AuthenticationStatus.Failed:
                ViewBag.Message = response.Exception.Message;
                return View("LogOn");
        }
    
        return new EmptyResult();
    }
    
    public ActionResult ShowUserDetails(UserDetailsModel objUserDetails)
    {
        return View(objUserDetails);
    }
    [HttpPost]
    public ActionResult ShowUserDetails(string OpenID,
    string FriendlyIdentifier, string FirstName, string LastName,
    string Dob, string Gender, string Email)
    {
        var objUserDetails = new UserDetailsModel()
        {
            OpenID = OpenID,
            FriendlyIdentifier = FriendlyIdentifier,
            FirstName = FirstName,
            LastName = LastName,
            Dob = Dob,
            Gender = Gender,
            Email = Email,
        };
        return View(objUserDetails);
    }
    
  10. Right click on Views--> Accounts and click Add-->View to add new view like this:

  11. Add the following code in this View:
    C#
    public class UserDetailsModel
    {
        public string OpenID { get; set; }
        public string ProviderUrl { get; set; }
        public string FriendlyIdentifier { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Dob { get; set; }
        public string Gender { get; set; }
        public string Email { get; set; }
    }
    
  12. Now run the project click [Log On] link and click a provider like Google. It may ask you to sign in or ask you to allow access to your information. You will get a page like this:

Congratulations! Now you have integrated OpenID login with Facebook login to your project.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
India India
Hi There, I am an IT professional with 14 years of experience in architecting, designing and building IT solutions for complex business needs in form of mobile & web applications using Microsoft technologies. Currently working in an multinational company in India as Solutions Architect. The articles here are sourced from my blog : http://techierathore.com/

Comments and Discussions

 
QuestionFacebook butoon unclikable Pin
Shashi Kant Yadav25-Oct-13 1:44
Shashi Kant Yadav25-Oct-13 1:44 
AnswerRe: Facebook butoon unclikable Pin
S Ravi Kumar (TechieRathore)10-Nov-13 20:35
professionalS Ravi Kumar (TechieRathore)10-Nov-13 20:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.