Customizing social login buttons in Asp.Net MVC 5

Introduction

In Asp.Net Mvc 5, support for Oauth 2.0  comes in bundled into most of the default web application project types in Visual Studio via Microsoft Owin. Adding Oauth 2.0 support to a new project, is as good as just editing the Startup.Ath.cs file located in the App_Start folder of your project. You do this by adding your own clientId and clientSecret which you get when you register your application with the different Oauth providers available. The most used of these providers are Facebook, Google and Twitter.

When all of the setup in the Start.Auth.cs is done and finished your login page will look something like the image below depending on how many providers you have added.

Default Buttons
Default Buttons

This will work fine and your users will have the option to be able to login into your application using their social network account of choice. But if you survey a lot of websites on the internet nowadays which support login using Oauth, you will find that their layout looks much nicer and are well presented. My favourite, being a soccer fan, is the English Premier League fantasy premier league website. It has support for logging in using Facebook, Twitter and Google.

Fantasy PL login page
Fantasy PL login page

Compare this to the default layout you get from the Visual Studio project template above. I am no expert in UX and graphic design but I think the fantasy football one looks way much better.

In this article I am going to demonstrate how you can achieve a similar layout by customizing the Login and Register pages in a basic MVC5 web application project. Lets begin.

Create a new Asp.Net MVC5 project

In Visual Studio 2015, create a web application with Individual accounts authentication option selected.

 

New Project
New Project
Individual User Accounts
Individual user accounts selected

Once Visual Studio has finished creating the project, head over to the App_Start folder and find the Start.Auth.cs  file. Edit the file to include the Oauth providers you have registered with. For testing purposes, test123 is enough for the social buttons to show.

 app.UseMicrosoftAccountAuthentication(
clientId: "test123",
clientSecret: "test123");

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

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

app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
{
ClientId = "test123",
ClientSecret = "test123"
});

After adding your appliation OAuth clientIds’ and secrets’, add font-awesome, we will need it for the social icons. In Package Manager Console:
install-package fontawesome
Also do not forget to add the font-awesome.css file to styles bundle. In the App_Start folder, edit the styles bundle to include Font Awesome:

            bundles.Add(new StyleBundle("~/Content/css").Include(
                      "~/Content/bootstrap.css",
                      "~/Content/font-awesome.css",
                      "~/Content/site.css"));

Editing the views

Now that we have added Oauth support to our application it is time modify the layout and make it better. Head over to the Views folder, in the Account child folder find the _ExternalLoginsListPartial.cshtml partial view. Modify the html so that it looks like the following:


@using Microsoft.Owin.Security
@model custom_social_buttons.Models.ExternalLoginListViewModel

<div class="text-center split-div">
    <hr class="split-hr"/>
    <span class="split-span">or sign up with</span>
</div>
@{
    var loginProviders = Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes();
    if (loginProviders.Count() != 0)
    {
        using (Html.BeginForm("ExternalLogin", "Account", new {Model.ReturnUrl}))
        {
            @Html.AntiForgeryToken()
            <div id="socialLoginList">
                <p>
                    @foreach (var p in loginProviders)
                    {
                        if (p.AuthenticationType == "Google")
                        {
                            <div class="col-md-4">
                                <button type="submit" class="btn btn-block btn-google" id="@p.AuthenticationType" name="provider">

                                    <i class="fa fa-google-plus fa-align-left social-icon" style=""></i>Google
                                </button>
                            </div>
                        }
                        else if (p.AuthenticationType == "Facebook")
                        {
                            <div class="col-md-4">
                                <button class="btn-block btn btn-facebook" type="submit" id="@p.AuthenticationType" name="provider">

                                    <i class="fa fa-facebook fa-align-left social-icon"></i>Facebook
                                </button>
                            </div>
                        }
                        else if (p.AuthenticationType == "Twitter")
                        {
                            <div class="col-md-4">
                                <button class="btn-block btn btn-twitter" type="submit" id="@p.AuthenticationType" name="provider">

                                    <i class="fa fa-twitter fa-align-left social-icon"></i>Twitter
                                </button>
                            </div>
                        }
                        else
                        {
                            <div class="col-md-4">
                                <button class="btn-block btn btn-linkedin" type="submit" id="@p.AuthenticationType" name="provider">

                                    <i class="fa fa-life-buoy fa-align-left social-icon"></i>
                                    Sign in with @p.Caption

                                </button>
                            </div>
                        }
                    }
                </p>

            </div>
        }
    }
}

Whilst you are still in the Account folder edit the Login.cshtml view so the html looks like below.

@using custom_social_buttons.Models
@model custom_social_buttons.Models.LoginViewModel
@{
    ViewBag.Title = "Log in";
}
<div class="row">
    <div class="col-md-6 col-md-offset-3">
        <h3 class="text-center">@ViewBag.Title.</h3>
        <section id="loginForm">
            @using (Html.BeginForm("Login", "Account", new {ViewBag.ReturnUrl}, FormMethod.Post, new {@class = "form-horizontal", role = "form"}))
            {
                @Html.AntiForgeryToken()
                <h4 class="text-center">Use a local account to log in.</h4>
                <hr/>
                @Html.ValidationSummary(true, "", new {@class = "text-danger"})
                <div class="form-group">
                    @Html.LabelFor(m => m.Email, new {@class = "control-label"})
                    @Html.TextBoxFor(m => m.Email, new {@class = "form-control"})
                    @Html.ValidationMessageFor(m => m.Email, "", new {@class = "text-danger"})
                </div>
                <div class="form-group">
                    @Html.LabelFor(m => m.Password, new {@class = "control-label"})
                    @Html.PasswordFor(m => m.Password, new {@class = "form-control"})
                    @Html.ValidationMessageFor(m => m.Password, "", new {@class = "text-danger"})
                </div>

                <div class="col-xs-12 col-md-6 text-left remember-me">
                    <label class="checkbox">
                        @Html.CheckBoxFor(m => m.RememberMe)
                        @Html.LabelFor(m => m.RememberMe)
                    </label>
                </div>

                <div class="form-group">
                    <input type="submit" value="Log in" class="btn btn-block btn-primary"/>
                </div>
                <div class="form-group">
                    @Html.ActionLink("Register as a new user", "Register", null, new {@class = "btn  btn-block btn-default"})
                </div>
            }
        </section>
        <section id="socialLoginForm">
            @Html.Partial("_ExternalLoginsListPartial", new ExternalLoginListViewModel {ReturnUrl = ViewBag.ReturnUrl})
        </section>
    </div>
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

And optionally the Register.cshtml view to the following:

@using custom_social_buttons.Models
@model custom_social_buttons.Models.RegisterViewModel
@{
    ViewBag.Title = "Register";
}

<div class="row">
    <div class="col-md-offset-3 col-md-6">
        <h3 class="text-center">@ViewBag.Title.</h3>
        <section id="registerForm">
            @using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
            {
                @Html.AntiForgeryToken()
                <h4 class="text-center">Create a new account.</h4>
                <hr />
                @Html.ValidationSummary("", new { @class = "text-danger" })
                <div class="form-group">
                    @Html.LabelFor(m => m.Email, new { @class = "control-label" })
                    @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
                </div>
                <div class="form-group">
                    @Html.LabelFor(m => m.Password, new { @class = "control-label" })
                    @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
                </div>
                <div class="form-group">
                    @Html.LabelFor(m => m.ConfirmPassword, new { @class = "control-label" })
                    @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
                </div>
                <div class="form-group">
                    <input type="submit" class="btn btn-block btn-primary" value="Register" />
                </div>
            }
        </section>
        <section id="socialLoginForm">
            @Html.Partial("_ExternalLoginsListPartial", new ExternalLoginListViewModel { ReturnUrl = ViewBag.ReturnUrl })
        </section>
        
    </div>
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

The CSS

Finally we would add the css magic that enhance the look and feel of our account pages. Go to Content folder and replace all its contents with the following:


body {
    padding-bottom: 20px;
    padding-top: 50px;
}

/* Set padding to keep content from hitting the edges */

.body-content {
    padding-left: 15px;
    padding-right: 15px;
}

/* Override the default bootstrap behavior where horizontal description lists 
   will truncate terms that are too long to fit in the left column 
*/

.dl-horizontal dt {
    white-space: normal;
}

/*
    Login Form
*/
.btn-facebook {
    background: #305c99;
    color: #fff;
}

.btn-google:hover {
    background: #b22222;
    color: #fff;
}

.btn-facebook:hover {
    background: #2b4db1;
    color: #fff;
}

.btn-twitter:hover {
    background: #007bb6;
    color: #fff;
}

.btn-twitter {
    background: #00cdff;
    color: #fff;
}

.btn-google {
    background: #d24228;
    color: #fff;
}

.btn-linkedin {
    background: #007bb6;
    color: #fff;
}

.btn-block {
    margin: 3px 0 !important;
}

.form-group {
    margin-left: 15px !important;
    margin-right: 15px !important;
}

#loginForm {
    align-items: center;
}

.remember-me {
    margin-bottom: 8px;
}

.split-div {
    font-size: 1.5em;
    margin-bottom: 1em;
    margin-top: 1em;
    padding-bottom: 0.5em;
    padding-top: 0.5em;
    position: relative;
}

.split-span {
    background-color: white;
    display: block;
    left: 40%;
    margin-left: -1.5em;
    position: absolute;
    text-align: center;
    top: -0.3em;
    width: 8em;
}

.split-hr {
    margin-bottom: 0;
    margin-top: 0;
}

.social-icon {
    margin-right: 15px;
}

The Result

If you have followed all of the above steps correctly you should have a layout that almost look like the image below.

The Result
The Result

It is not perfect but you can agree me that this is much better than the default layout

Conclusion

We have taken a basic Asp.Net MVC5 project, changed the login page and register pages and added style enhancements to the layout to achieve a more professional and well presented look and feel.

All the code for the article can be downloaded from Github.

Thank you.

Leave a Reply