Geeks With Blogs
hmloo's World of .NET

Introduction

Single sign-on (SSO) is a way to control access to multiple related but independent systems, a user only needs to log in once and gains access to all other systems. a lot of commercial systems that provide Single sign-on solution and you can also choose some open source solutions like Opensso, CAS etc. both of them use centralized authentication and provide more robust authentication mechanism, but if each system has its own authentication mechanism, how do we provide a seamless transition between them. Here I will show you the case.

How it Works

The method we’ll use is based on a secret key shared between the sites. Origin site has a method to build up a hashed authentication token with some other parameters and redirect the user to the target site.

variables Status Description
ssoEncode required hash(ssoSharedSecret + , + ssoTime + , + ssoUserName)
ssoTime required timestamp with format YYYYMMDDHHMMSS used to prevent playback attacks
ssoUserName required unique username; required when a user is logged in

Note : The variables will be sent via POST for security reasons

Building a Single Sign-On Solution

Origin Site has function to
1. Create the URL for your Request.
2. Generate required authentication parameters
3. Redirect to target site.

using System;
using System.Web.Security;
using System.Text;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string postbackUrl = "http://www.targetsite.com/sso.aspx";
        string ssoTime = DateTime.Now.ToString("yyyyMMddHHmmss");
        string ssoUserName = User.Identity.Name;
        string ssoSharedSecret = "58ag;ai76"; // get this from config or similar
        string ssoHash = FormsAuthentication.HashPasswordForStoringInConfigFile(string.Format("{0},{1},{2}", ssoSharedSecret, ssoTime, ssoUserName), "md5");
        string value = string.Format("{0}:{1},{2}", ssoHash,ssoTime, ssoUserName);
        Response.Clear();
        StringBuilder sb = new StringBuilder();
        sb.Append("<html>");
        sb.AppendFormat(@"<body onload='document.forms[""form""].submit()'>");
        sb.AppendFormat("<form name='form' action='{0}' method='post'>", postbackUrl);
        sb.AppendFormat("<input type='hidden' name='t' value='{0}'>", value);
        sb.Append("</form>");
        sb.Append("</body>");
        sb.Append("</html>");
        Response.Write(sb.ToString());
        Response.End();

    }
}

Target Site has function to
1. Get authentication parameters.
2. Validate the parameters with shared secret.
3. If the user is valid, then do authenticate and redirect to target page.
4. If the user is invalid, then show errors and return.

using System;
using System.Web.Security;
using System.Text;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            if (User.Identity.IsAuthenticated)
            {
                Response.Redirect("~/Default.aspx");
            }
        }
        if (Request.Params.Get("t") != null)
        {
            string ticket = Request.Params.Get("t");
            char[] delimiters = new char[] { ':', ',' };
            string[] ssoVariable = ticket.Split(delimiters, StringSplitOptions.None);
            string ssoHash = ssoVariable[0];
            string ssoTime = ssoVariable[1];
            string ssoUserName = ssoVariable[2];
            DateTime appTime = DateTime.MinValue;
            int offsetTime = 60; // get this from config or similar
            try
            {
                appTime = DateTime.ParseExact(ssoTime, "yyyyMMddHHmmss", null);
            }
            catch
            {
                //show error
                return;
            }
            if (Math.Abs(appTime.Subtract(DateTime.Now).TotalSeconds) > offsetTime)
            {
                //show error
                return;
            }
            bool isValid = false;
            string ssoSharedSecret = "58ag;ai76"; // get this from config or similar
            string hash = FormsAuthentication.HashPasswordForStoringInConfigFile(string.Format("{0},{1},{2}", ssoSharedSecret, ssoTime, ssoUserName), "md5");
            if (string.Compare(ssoHash, hash, true) == 0)
            {
                if (Math.Abs(appTime.Subtract(DateTime.Now).TotalSeconds) > offsetTime)
                {
                    //show error
                    return;
                }
                else
                {
                    isValid = true;
                }
            }
            if (isValid)
            {
                //Do authenticate;
            }
            else
            {
                //show error
                return;
            }
        }
        else
        {
            //show error
        }
    }
}

Summary

This is a very simple and basic SSO solution, and its main advantage is its simplicity, only needs to add a single page to do SSO authentication, do not need to modify the existing system infrastructure.

Posted on Monday, July 9, 2012 7:42 PM | Back to top


Comments on this post: How to Implement Single Sign-On between Websites

# re: How to Implement Single Sign-On between Websites
Requesting Gravatar...
Hi, great article. Thumbs up!

I just have a question for you. I am not much experienced in C# but just wanted to ask you that in order to implement the above solution, is it required that both the websites should use forms authentication?
Left by brian on Aug 08, 2012 7:51 AM

# re: How to Implement Single Sign-On between Websites
Requesting Gravatar...
yes, exactly.
Left by hmloo on Aug 08, 2012 11:33 AM

# re: How to Implement Single Sign-On between Websites
Requesting Gravatar...
thanks for sharing
Left by journeycoder.com on Apr 21, 2014 3:44 AM

# re: How to Implement Single Sign-On between Websites
Requesting Gravatar...
Nice work. My use case is as follows:
I have a .NET based Web application at my work place. The other application is an OpenStack cloud installed on one of the servers here.

All of the components of the Cloud can be accessed using a Web-Interface called Dashboard. The users login using the Dashboard login page. But the login page code is out of my control. FYI, OpenStack is written using Python + a Python-based Web Framework called Django.

I have full control over my .NET Web app. Anyway I can achieve SSO b/w these two heterogeneous applications??

Any help would be highly appreciated and thank you in advance!!
Left by Sheshu on Mar 22, 2015 5:40 PM

Your comment:
 (will show your gravatar)


Copyright © hmloo | Powered by: GeeksWithBlogs.net | Join free