Friday, August 31, 2012

Implement Facebook Login with OpenID Selector in MVC3

In My last post, I explained how we can implement Facebook login with OpenId selector tool. In this post I will explain you 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.
      A- Add the DotNetOpenAuth.dll to references in your site.
      B- Copy all contents of openid-selector\css folder to the 'Content' folder .
      C- Copy images, images.large, images.small folders to the site 'Content' folder.
      D- Copy openid-jquery.js, openid-en.js files from  openid-selector\js folder to 'Scripts' folder

Your Solution Explorer  will look like this (See Highlighted Portion)  :



 3- Go to Views > Shared > _Layout.cshtml and replace the <head> with this new head with new styles and scripts:
<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 it to hold the returned OpenID from OpenID-Selector
  your class will look like this:
    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 following class to it:
    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: 
 
 
@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 like this page:
9- Now to implement Open ID using DotnetOpenAuth, Go to Controllers > 
AccountController.cs and Add these using:
 
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.RelyingParty;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
Then Add the following code to AccountController.cs:
        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 following code in this View:
    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 had integrated OpenID login with facebook login to your project.

Download Code from here



12 comments:

  1. Great Job Ravi! I never knew that Facebook login can also be implemented by open Id selector in MVC3. The usefulness and significance of this article is overwhelming. Thanks again and good luck! Web Development - Zeemo

    ReplyDelete

  2. this blog is really useful and it is very interesting thanks for sharing , it is really good and exclusive.

    dotnet Training in Chennai

    ReplyDelete
  3. This site has lots of advantage.I found many interesting things from this site. It helps me in many ways.Thanks for posting this again.
    Android Training in Chennai

    ReplyDelete
  4. This is really too useful and has more ideas from your blog. Keep sharing many techniques. We are waiting for your new blog and for useful information.................For More details about Oracle Fusion Financials Course Please Click Here.

    ReplyDelete
  5. Thanks for appreciating. Really means and inspires a lot to hear from you guys.I have bookmarked it and I am looking forward to reading new articles. Keep up the good work..Believe me, This is very helpful for me.
    Fleet Management Software
    Manufacturing ERP
    Logistic ERP
    Logistics Software
    Human resources management software

    ReplyDelete
  6. Fertility is the natural capability to produce offspring. As a measure, fertility rate is the number of offspring born per mating pair, individual or population.Human fertility depends on factors of nutrition, sexual behavior, consanguinity, culture, instinct, endocrinology, timing, economics, way of life, and emotions.Greate thinks of a fertility center for humans.

    Fertility Center in OMR

    ReplyDelete
  7. This professional hacker is absolutely reliable and I strongly recommend him for any type of hack you require. I know this because I have hired him severally for various hacks and he has never disappointed me nor any of my friends who have hired him too, he can help you with any of the following hacks:

    -Phone hacks (remotely)
    -Credit repair
    -Bitcoin recovery (any cryptocurrency)
    -Make money from home (USA only)
    -Social media hacks
    -Website hacks
    -Erase criminal records (USA & Canada only)
    -Grade change
    -funds recovery

    Email: onlineghosthacker247@ gmail .com

    ReplyDelete
  8. very inspiring your blog .thanks for sharing with us . if you have need service for quickbooks then connect at Quickbooks Phone Number

    ReplyDelete
  9. very intresting blog which give informative information Thanks for sharing . if you are looking
    accounting software service for QuickBooks errors then contact me at quickbooks phone number+1 866-448-6293

    ReplyDelete
  10. this is so amazing article keep going on . please connect my service at quickbooks phone number

    ReplyDelete
  11. I want to always read your blogs. I love them Are you also searching for Nursing case study writing services? we are the best solution for you. We are best known for delivering Nursing case study writing services to students without having to break the bank

    ReplyDelete
  12. I want to always read your blogs. I love them Are you also searching for nursing dissertation writing help? we are the best solution for you. We are best known for delivering Nursing dissertation writing services to students without having to break the bank

    ReplyDelete