0

Am in the process of performing SSO for all apps in a domain

Things i have done so far are

  1. Created a parent site with form authentication where login is performed
  2. Removed the authentication mode of all child applications to none
  3. Added a handler in all child apps checking if user authenticated and fetch user details for the app

Code for handler is as follows

public class MyHandler : IHttpHandler, IRequiresSessionState  
{
    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        if (context.Request.IsAuthenticated)
        {
            if (context.Session["UserDetails"] == null)
            {
                string userName = HttpContext.Current.User.Identity.Name;
                UserManagement userMngmt = new UserManagement();
                userMngmt.GetLoggedUserDetails(userName);
               // context.Response.Redirect(context.Request.Url.ToString(), true);
            }
        }
        else
        {
            context.Response.Redirect("/SSO");
        }
    }
}

The idea is if he is authenticated get user name and get his details and store in session and proceed to load the requested page with the user details.

But now the page is not getting loaded. I understood that after checking i have to load the page requested.How to do so.

Robert_Junior
  • 1,122
  • 1
  • 18
  • 40

1 Answers1

2

I think you're hooking at wrong place. The IHttpHandler is handler for single url or set of specific urls. The logic should go to either IHttpModule (check out https://msdn.microsoft.com/en-us/library/ms227673(v=vs.100).aspx). Or to Global.asax.cs:

protected void Application_BeginRequest(object sender, EventArgs e)
{
   var context = ((HttpApplication)sender).Context;
   if (!context.Request.IsAuthenticated &&     
       !context.Request.Url.PathAndQuery.StartsWith("/SSO", 
         StringComparison.OrdinalIgnoreCase))
   {
     context.Response.Redirect("/SSO");
   }

}

So you can inject arbitrary code into every single request (in your case some session warm-up) and you don't have to redirect anywhere - because the page will load after executing your code.

Also note it is not a great idea to rely on fact that some "magic" will fill-in some cache; better way is to use lazy-loading instead.

public UserData GetUserData(HttpContext context)
{
    if (!context.Request.IsAuthenticated)
    {
      throw new Exception("Unauthorized");
    }

    var result = context.Session["UserDetails"];
    if (result == null)
    {
      string userName = HttpContext.Current.User.Identity.Name;
      var userMngmt = new UserManagement();
      result = userMngmt.GetLoggedUserDetails(userName);
      context.Session["UserDetails"] = result;
    }
    return result;
}

So you can still use Session as cache, however you'll use it as cache only when explicitly requested and also it is much clearer where your data comes from (you don't have to walk trough whole application to find out where the Session["UserDetails"] is being set)

Also check out ASP.NET MVC 4 intercept all incoming requests (its for MVC but modules concept / global application concept haven't changed between ASP.NET and MVC)

Community
  • 1
  • 1
Ondrej Svejdar
  • 21,349
  • 5
  • 54
  • 89
  • The only thing i don't go with modules is like it will hot for every js,css file request which i think wil slow down the process. That's why i moved to handlers – Robert_Junior Dec 01 '15 at 05:34
  • @Robert_Junior - then your only option left is to have some kind of base page from which will all pages inherit & override OnInit event there. – Ondrej Svejdar Dec 01 '15 at 10:01