How to Implement Single Sign-On between Websites
- by hmloo
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.