Single Sign-On (SSO) from ASP.NET to PHP

I recently implemented the new ExcelCentral forums, and was faced with the challenge of integrating the login from our main ASP.NET site with the PHP-based Invision forum software.

To make this possible, I modified the forum software to retrieve ASP.NET’s login cookie and send a request back to the ASP.NET site to validate it and return the details of the logged-in user.

On the PHP side, the code to check whether a user is logged into the main site looks something like:

/* Get the ASP.NET Login cookie (ASPXAUTH) */
$sessioncookie = $_COOKIE['_ASPXAUTH'];

if ( !$sessioncookie )
{
    /* If we have no cookie, user is not logged in */
    /* Code for anonymous users here */
}
else
{
    /* Send the key from the ASPXAUTH cookie to a page within the ASP.NET application that will return the user's details */
    $userdata = file_get_contents('http://www.yourdomain.com/getloggedinuser.aspx?key='.$sessioncookie);

    if ($userdata == "")
    {
        /* The ASP.NET site did not consider the login cookie to be valid (possibly the session has expired) */
        /* Code for anonymous users here */
    }
    else
    {
        /* Parse the data that was returned from the ASP.NET system */
        $parseduserdata = json_decode($data, true);
        $userid = $parseduserdata['id'];
        $username = $parseduserdata['username'];
        /* Code for logged-in users here */
    }
}

Now we need to write the code for the getloggedinuser.aspx page within the ASP.NET system:

protected void Page_Load(object sender, EventArgs e)
{
    try
    {
        if (Request.QueryString["key"] != null)
        {
            // Retrieve the login key value from the querystring (this is the code from the ASPXAUTH cookie)
            string AuthKey = Request.QueryString["key"];

            // Decrypt the key and get the associated Forms Authentication ticket
            FormsAuthenticationTicket Ticket = FormsAuthentication.Decrypt(AuthKey);

            // Retrieve the user's details from the ticket
            string UserName = Ticket.Name;
            MembershipUser LoggedInUser = Membership.GetUser(UserName);
            string UserID = LoggedInUser.ProviderUserKey.ToString();

            // Output the user details in JSON format
            Response.ContentType = "application/json";
            Response.Write("{\"id\": \"" + UserID + "\",\"username\": \"" + UserName + "\"}");
            Response.Flush();
            Response.SuppressContent = true;
            HttpContext.Current.ApplicationInstance.CompleteRequest();
        }
        else
        {
            // Return a blank page if there is no key provided
            Response.Write("");
            Response.Flush();
            Response.SuppressContent = true;
            HttpContext.Current.ApplicationInstance.CompleteRequest();
        }
    }
    catch(Exception Ex)
    {
        // Return a blank page if an exception occurs
        Response.Write("");
        Response.Flush();
        Response.SuppressContent = true;
        HttpContext.Current.ApplicationInstance.CompleteRequest();
    }
}

By using FormsAuthentication.Decrypt as shown above, we can easily get the user details as long as we can provide the value of the user’s ASPXAUTH cookie. Remember that cookies are only shared across a single domain, so you won’t be able to implement single-sign-on across domains.

In my system, the login cookie is available on both excelcentral.com and on forums.excelcentral.com, so login can be shared between the two.  However, my aspnetcentral.com site wouldn’t be able to get the login cookie from excelcentral.com.

ASP.NET’s default behaviour can cause problems here, because it doesn’t mark cookies with a domain by default.  To change this, you need to edit Web.config with the following (within the system.web tag):

<httpCookies domain="yourdomain.com" />

This setting will mark ASP.NET’s login cookies with your domain, allowing them to be retrieved by any subdomains (eg forums.yourdomain.com).

Leave a Reply

Your email address will not be published.

Blue Captcha Image
Refresh

*