Search code examples
c#asp.netsessioncookiesiis-7.5

Getting "Unrecognized Guid format" Error When Accessing Page in Same Browser Window After Being Logged Out


I have been racking my brain over this for some time now, so I am hoping someone can help (and I am hoping I don't get dinged because the question might not have a definite, concrete answer).

We have an IIS7.5 web environment running ASP.NET 4.0.x on Win2008 Advance Server. Clients use IE8 (intranet site). We have a Siteminder protected directory within wwwroot. Almost all website files are located within this protected directory, thus requiring the user to authenticate through the company's SSO page (the aforementioned Siteminder). IIS defaults for session timeouts are in place (20 minutes, which roughly correlates with our Siteminder policy's timeout setting). The application pool runs in Integrated mode. We are not using Forms Authorization.

Our website has a logout button, as well as a mechanism in place to log the user out should there be a period of inactivity (a JQuery plugin solution that provides a modal dialog 5 minutes before the "expected" time out; an AJAX process checks an ASHX page which provides the session time left).

When logging out, the process makes a call to a logout ASHX page outside of the secured directory mentioned above (note I also tried this inside the secured directory with similar (not desirable) results; I moved the logout ASHX page to a folder outside of the secured directory based on my research around my issue (which is coming shortly). This logout ASHX clears and abandons the current session, removes the ASP.NET_SessionId and the Siteminder cookies, and calls a URL to actually log the user out of their Siteminder session (as recommended by the company's SSO team). The code for the logout ASHX is shown below...

<% @ WebHandler language="C#" class="Logout"%>
using System;
using System.Web;
using System.Web.SessionState;
using System.Configuration;
// log4net imports 
using log4net;
using log4net.Config;

public class Logout : IHttpHandler, IRequiresSessionState {
    private static readonly ILog log = LogManager.GetLogger(typeof(Logout));
    private static string SSO_LOGOUT_URL = ConfigurationManager.AppSettings["SSOLogoutURL"].ToString();
    public Logout() {}
    public void ProcessRequest(HttpContext context) {
        context.Session.Clear();
        context.Session.Abandon();
        HttpRequest Request = context.Request;
        string sRedirUrl = Request.QueryString["timeOutUrl"];
        if (String.IsNullOrEmpty(sRedirUrl)) {
            sRedirUrl = "https://portal.some_domain.net";
        }
        HttpResponse Response = context.Response;
        HttpCookie cookie = new HttpCookie("ASP.NET_SessionId", "");
        cookie.Expires = DateTime.Now.AddYears(-1);
        Response.Cookies.Add(cookie);
        cookie = new HttpCookie("SMSESSION", "");
        cookie.Expires = DateTime.Now.AddYears(-1);
        Response.Cookies.Add(cookie);
        Response.Write("<html><head><script language=\"javascript\">function init() {location=\"" + sRedirUrl + "\";}</script></head>");
        Response.Write("<body onload=\"init()\">");
        Response.Write("<iframe src='" + SSO_LOGOUT_URL + "' width=0 height=0></iframe>");
        Response.Write("</body></html>");
        // in PROD, the ROOT level for log4net should be set above "Debug", so this will not get logged (we don't want it to - too much verbosity)
        log.Debug(">>> Logout called - session ended!!!");
    }
    public bool IsReusable { 
        get { 
            return false;
        }
    }
}

All of this works as expected; the user clicks the "Logout" button and they are directed to the company's intranet homepage; if the countdown timer for the session reaches zero, the browser automatically redirects to a friendly "Your session has timed out" page with a link back into the site. Both of these actions go through the code above (the logout ASHX).

My problem occurs when the user attempts to access the site again after being logged out and within the same browser window (close the browser and re-launch and everything works great (as I would expect)). Below is the error...

[FormatException: Unrecognized Guid format.]
   System.GuidResult.SetFailure(ParseFailureKind failure, String failureMessageID, Object failureMessageFormatArgument, String failureArgumentName, Exception innerException) +6076960
   System.Guid.TryParseGuid(String g, GuidStyles flags, GuidResult& result) +138
   System.Guid..ctor(String g) +257
   MSDN.SessionPersistence.LoadSession(String key, String dsn, Int32 SessionExpiration) +332
   MSDN.SessionPage.InitializeComponent() +696
   MSDN.SessionPage.OnInit(EventArgs e) +46
   System.Web.UI.Control.InitRecursive(Control namingContainer) +133
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1970

This occurs more often than not, but I can't seem to nail down a specific cause or specific steps to always reproduce the error. It seems to happen if the time between being logged out and the time a user tries to re-access the page is on the long side versus more immediate. Research on the exact error just leads to topics on making sure the value passed into the GUID object is valid. I also tried researching the "MSDN.SessionPersistence.LoadSession" method but found few results that had no relevance to my problem. Nowhere in my code do I make explicit use of the GUID object.

The logout ASHX is the result of my past week's worth of investigation and trial and error. I thought I nailed it when I began "deleting" the "ASP.NET_SessionId" cookie, but the error still occurs on a hit-and-miss basis.

The thing that is killing me is trying to figure out why I am getting this error. I believe I understand that sessions in ASP.NET are identified by a string of characters that must fit the formatting requirements for the GUID object, but I cannot determine why this is occurring (shouldn't a new session be created with a new session id since I abandoned the old one and deleted the ASP.NET_SessionId cookie?). Most recently I even put the following code into the main ASPX page's Page_Load method...

if (!User.Identity.IsAuthenticated) {
    if (Request.Cookies["ASP.NET_SessionId"] != null) {
        HttpCookie cookie = new HttpCookie("ASP.NET_SessionId", "");
        cookie.Expires = DateTime.Now.AddYears(-1);
        Response.Cookies.Add(cookie);
    }
    HttpContext.Current.Session.Abandon();
}

I did this per another suggestion on another site. As you can probably see, I am beginning to grasp for straws here. I even used IE8's Developer Tools > Cache > View Cookie Information feature to see what was going on in each page (the "time out" page does not show the "ASP.NET_SessionId" or "SMSESSION" cookies).

So, is my approach sound, or am i missing some key idea (what I have so far is a culmination of research on SO and other sites)? Could the issue be outside of the C#/ASP.NET/IIS realm and exist because of Siteminder? Any help would be greatly appreciated.

UPDATE:

I did some more investigating around the timing of when this occurs. I waited for the logout to occur, then set timers at the 5, 10, 15, and 20 minute marks (after each test, I closed the browser). I was able to successfully log back into the site at the 5, 10, and 15 minute marks, but at the 20 minute mark, I would receive the unrecognized guid format error. Note that each time I logged back in, I mean I went through my company's Siteminder SSO login page (the site itself does not have a log in mechanism - it is strictly protected by my company's Siteminder-based SSO login form). This still does not answer why this is occurring, but perhaps it narrows things down a bit. Is the problem with Siteminder or with IIS/ASP.NET? As best as I can tell, I am properly logging out of SSO (based on other corporate intranet sites using the same URL for SSO logout).


Solution

  • I found out from a fellow developer (who works on a platform that we are integrating with our own platform under a "common portal" (code above)) that they use some custom code referenced by Microsoft (http://msdn.microsoft.com/en-us/library/aa479313.aspx) to allow session sharing between Classic ASP and ASP.NET. I was unaware of this.

    The problem was happening with how we were getting and setting a special cookie used by the MS solution (the cookie name was getting ; arcHome-BgColor appended to it, thus the cookie could not be found when we needed its value. Additionally, we were using Response.Cookies["mySession"].Value instead of Request.Cookies["mySession"].Value when trying to get the value at other points in the code. Lastly, we set the cookie value in another method to be sure the value was indeed correct.