Single Sign-On (SSO) implementation in ASP.NET MVC

To start with any secured web application, the developer needs to work on the implementation of the authentication functionality. If any user needs to enter into multiple secured web application on same domain in .NET framework, he needs to login through each of those applications. Logging in a number of times can be avoided with Single Sign On (SSO) functionality.

SSO is a functionality that allows to login once and access multiple web applications with same credentials.

For example – once the user enters a user name and password on Gmail, he will be able to access Google’s other web application like Google Plus, YouTube, Play store, etc., with same credentials without logging in again.

HOW SSO WORKS:

When a user runs a page in an application that requires user base authentication, the application searches for a cookie (forms authentication cookie) in the http request, if it does not find the cookie, it redirects the current page to the login page.

When a user enters valid credentials and click “Login” button, the system validates the credentials in data storage and set the credentials in Thread.CurrentPrincipal.Identity.Name property in .NET framework, and create a cookie in Response, and redirects to the requested page.

If a user navigates to another page of the application, then browser sends the authentication cookie as it already has the cookie from the last response. The browser when gets the cookie, validates the cookie properties; if the cookie is not expired, then the browser will fetch the required information from the cookie and set the user name into the Thread.CurrentPrincipal.Identity.Name property in .NET framework.

IMPLEMENT SSO IN MVC:

Here we see the steps to implement SSO in MVC Application using .NET
1. Open visual studio, create three blank applications (SingleSignOn, ApplciationA & ApplicationB). SingleSignOn application is for login functionality and ApplicationA and ApplicationB are secured web applications.

2. The solution will look something like below:

implement Single Sign On in ASP.NET MVC

3. Add a AccountController in SingleSignOn, It will contain the login functionality code.

Custom Single-Sign-On with ASP.NET

4. Write login code or simple forms authentication code in the AccountController as below:

public class AccountController : Controller
{
// GET: Account
public ActionResult Login(string returnUrl)
{
if (Request.IsAuthenticated)
{
return RedirectToAction(“Index”, “Home”);

}

ViewBag.ReturnUrl = returnUrl;

return View();

}

[AllowAnonymous]

[HttpPost]

[ValidateAntiForgeryToken]

public ActionResult Login(string userName, string password, string returnUrl)

{

if (FormsAuthentication.Authenticate(userName, password))

{

FormsAuthentication.SetAuthCookie(userName, false);

if (!string.IsNullOrEmpty(returnUrl))

{

return Redirect(returnUrl);

}

else

{

return RedirectToAction(“Index”, “Home”);

}

}

else

{

ModelState.AddModelError(string.Empty, “Invalid Login Detials”);

ViewBag.ReturnUrl = returnUrl;

return View();

}

}

}

FormsAuthentication.Authenticate method will check the credentials and authenticate whether user name and password are correct or not. We can also validate username and password from SQL Server database or from any other Data Source.

5. Now we will add a login view and write html form in the login view for user login.

@using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl }))
{
    @Html.ValidationSummary()
    @Html.AntiForgeryToken()

        @Html.Label("UserName")
        @Html.Editor("UserName")


        @Html.LabelForModel("Password")
        @Html.Password("Password")
    
    <input class="btn btn-primary" type="submit" value="login" />
}

6. Create a Machine Key tag into web.config under System.Web tag in SingleSignOn, ApplciationA and ApplicationB.

  <system.web>
     <machineKey validationKey="4B616C4E8BE5E18C3A1650939E88F3B0ED1AFC692919D7937DA68BBC552F04027DCF8BD31125E5E69094E1A4BA96731067BB57F0D3C34B63B9B03123703CD01A" decryptionKey="EC095D7743D3368F22FB7F482D9F41AA911922EC753515BB"   validation="HMACSHA384" decryption="DES" />

You can create your own machine keys through below steps:

  • Open IIS manager.
  • Select the website name from the left panel.
  • In the right panel, double click on Machine Key icon under Asp.Net settings and you will get below window:

  • Now click on Generate Keys button in the right pane to generate random machine keys.

7. Add forms authentication tag to web.config of SingleSignOn, ApplciationA and ApplicationB.

    <authentication mode="Forms">
       <forms name="SingleSignOnApp" loginUrl="http://localhost/SingleSignOn/Account/Login" timeout="525599" slidingExpiration="true">
        </forms>
     </authentication>

8. We are using local IIS  localhost/SingleSignOn to configure it. To run it right click on project, choose Properties menu and choose Web as below:

9. To test an SSO functionality, right click on Home Controller in both ApplicationA and ApplicationB. Add Authorize attribute on the top of Home Controller that will redirect the unauthenticated users to SingleSignOn login.

[Authorize]
 public class HomeController : Controller
 { 
   public ActionResult Index()
   {
     return View();
   }
 }

10. Right click on Action result, select Add View and add Index View for the HomeController in both ApplicationA and ApplicationB.

 @{
    ViewBag.Title = "Application-A Home";
}
<h2>Application-A Home</h2>
Welcome @User.Identity.Name
 

11. Now browse http://localhost/ApplicaitonA, it will automatically redirect to http://localhost/SingleSignOnAccount/Login?ReturnUrl=%2fApplicationA%2f.

12. Login using username and password. After successful log in, it will automatically redirect to http://localhost/ApplicationA.

13. Now try the same process for ApplicationB and browse http://localhost/ApplicationB. You will see that it automatically logs in and redirect to ApplicationB.

Aside | Posted on by | Tagged , | Leave a comment

Performance Optimization – Bundling and Minification in ASP.NET MVC 4

Before getting you into the details of performance optimization, let me give a brief note on Bundling and Minification of JS/CSS files.

What is a Bundle?

Bundle is simply logical group of files that could be referenced by unique name and loaded with one HTTP request. You can create bundle for JavaScript and CSS.

What is Minification?

It’s a process of removing unnecessary whitespaces, line breaks and comments from code to reduce its size, thereby improving load times.

Bundling and minification are the performance optimization techniques that can help to improve load time by reducing the number of requests to the server and reducing the size of requested assets (such as JavaScript and CSS.)

Scenario without Bundling and Minification

Most of the current major browsers limit the number of simultaneous connections to six per hostname. This means that while six requests are being executed, any additional requests for assets on a host will be queued in the browser. In the below image, the IE developer tool network tab shows the timings for assets required by the ‘Index view’ of a sample application.

1st

  • The brown bars show the time for which the request is queued by the browser waiting for the six connections to complete.
  • The yellow bars show the request time taken to send the request and receive the first response from the server.
  • The blue bars represent the time taken to receive the response data from the server.

You can get detailed timing information by double-clicking on an asset. For example, the following image shows the load time details of the file.

2nd

In the preceding image, ‘Start’ event shows the time that a request was queued because of the browser limit of only six simultaneous connections. This request was queued for 187 milliseconds waiting for another request to complete.

Bundling

Bundling makes it easy to combine multiple files into a single file. It can create bundles for JavaScript, CSS, etc.  Lesser files mean lesser HTTP requests which in turn improves the initial page load performance.

How to do it

Adding reference:

First of all, add the references for both WebGrease.dll and System.Web.Optimization.dll to your projects as shown below. These DLLs can be downloaded from Internet or using NuGet Package Manager.

3rd

 Creating Bundle

After adding required DLL references, now create the bundle for your JS and CSS files within the Global.asax file as shown below. Here, I have created the bundle for all required JS and CSS files. You can also add your own custom JS and CSS files with complete path using ‘Include’ method.

4th

The preceding code creates a new JavaScript bundle named ~/bundles/jquery that includes debug and minified files in the ‘Scripts’ folder that compares the wild card string “~/Scripts/jquery-{version}.js” from bundle.config. This means in debug mode, jquery-2.1.3.js will be added to the bundle and in release mode, jquery-2.1.3.min.js will be added. Below common conventions are followed by the bundling framework:

  • Selecting “.min” file for release when “FileX.min.js” and “FileX.js” exist.
  • Selecting the non “.min” version for debug.
  • Ignoring “-vsdoc” files (such as jquery-2.1.3-vsdoc.js), which are used for IntelliSense.

The {version} wild card shown above is used to automatically create a jQuery bundle with the appropriate version of jQuery in your ‘Scripts’ folder.  In the above example, following benefits are provided by using wild card:

  • It allows to use NuGet to update to a latest jQuery version without changing the preceding bundling code or jQuery references in your view pages.
  • It automatically selects the full version for debug configurations and the “.min” version for release builds.

Registering Bundle

You will now need to register above created bundles with in ‘Application Start’ event of Global.asax as below:

5th

Adding Bundles to Layout Page in MVC3

You can add reference for created bundles in the project’s view pages and layouts as below:

@Scripts.Render(“~/bundles/jquery”)

@Scripts.Render(“~/bundles/jqueryui”)

@Scripts.Render(“~/bundles/jqueryval”)

Allow Bundling and Minification in debug mode

Bundling and minification doesn’t work in debug mode, so to enable bundling and minification, set the debug value in Web.config file to “false”. You can also override the Web.config setting with the ‘EnableOptimizations’ property on the ‘BundleTable’ class. The following lines of code within ‘Application_Start’ event of Global.asax enables bundling and minification, and in the Web.config file it overrides respective settings.

protected void Application_Start(){ BundleConfig.RegisterBundles(BundleTable.Bundles); //Enabling Bundling and Minification BundleTable.EnableOptimizations = true; }

How it works

Now run your application and you can see that all the JS and CSS files are converted to single JS and CSS files as shown below:

6th

 Minification

Minification is a technique for removing unnecessary characters (like white spaces, newlines, and tabs) and comments from the JavaScript and CSS files to reduce the size which causes improved load times of a webpage. There are various tools to minify the JS and CSS files. YUI Compressor and JSMin are the most popular tools for minifying the JS and CSS files. Use these tools for minifying your JS and CSS files and in your application use with “.min” suffix, so that you can easily identify that this is a minimize version of your CSS or JS file.

Minification with VS2013 and Web Essentials 2013 extension

I would like to share how you can create minify version of your JS or CSS file using ‘Web Essentials’ extension and VS2013. Right click on JS or CSS file, select “Web Essential” option and click on the highlighted “Minify JavaScript/CSS file(s)” as shown in the below image.

7th

With the help of this tool, every time you update your code in original JS or CSS file, the minify version of these files get automatically updated.

Busting Browser’s Cache by Bundling

As you know, browsers cache resources on the basis of accessed URLs. The browser first checks its cache when a web page requests a resource to see if there is a resource with the accessed URL. If it exists in cache, then it uses that existing copy instead of getting a new copy from server. So, whenever you change the content of JS and CSS files, it will not reflect on the browser. To reflect these changes, you have to refresh/reload the browser. But bundles automatically takes care of this problem by adding a hash code to each bundle as a query parameter to the URL as shown below.

Whenever you change the content of JS and CSS files, then a new hash code will be generated and rendered to the web page automatically. Through this, the browser will look into a different URL and will get the fresh copy of JS and CSS files.

Aside | Posted on by | Tagged , | Leave a comment