1
votes

I know REST is stateless, but this a requirement by design. We need to authenticate the API's requests from its Parent Application which is a traditional ASp.net Web Form application.

I have shared session as per these URLs. http://weblogs.asp.net/lichen/sharing-session-state-over-multiple-asp-net-applications-with-asp-net-state-server

How to maintain the same session id across multiple web applications in ASP.NET

http://www.codeproject.com/Articles/27090/Sharing-Session-Across-Applications

Global.asax code from both application for sharing session

 public override void Init()
    {
        base.Init();
        try
        {
            // Get the app name from config file...
            string appName = ConfigurationManager.AppSettings["ApplicationName"];

            Logger.LogEx(string.Format("{0} - {1}", appName, appName));
           // regenerateId();
            if (!string.IsNullOrEmpty(appName))
            {
                foreach (string moduleName in this.Modules)
                {
                    IHttpModule module = this.Modules[moduleName];
                    SessionStateModule ssm = module as SessionStateModule;
                    Logger.LogEx(string.Format("module {0} - ssm {1}", module, ssm));
                    if (ssm != null)
                    {
                        FieldInfo storeInfo = typeof(SessionStateModule).GetField("_store", BindingFlags.Instance | BindingFlags.NonPublic);
                        SessionStateStoreProviderBase store = (SessionStateStoreProviderBase)storeInfo.GetValue(ssm);
                        if (store == null) //In IIS7 Integrated mode, module.Init() is called later
                        {
                            FieldInfo runtimeInfo = typeof(HttpRuntime).GetField("_theRuntime", BindingFlags.Static | BindingFlags.NonPublic);
                            HttpRuntime theRuntime = (HttpRuntime)runtimeInfo.GetValue(null);
                            FieldInfo appNameInfo = typeof(HttpRuntime).GetField("_appDomainAppId", BindingFlags.Instance | BindingFlags.NonPublic);
                            Logger.LogEx(string.Format("theRuntime {0} - appName {1}", theRuntime, appName));
                            appNameInfo.SetValue(theRuntime, appName);
                        }
                        else
                        {
                            Type storeType = store.GetType();
                            if (storeType.Name.Equals("OutOfProcSessionStateStore"))
                            {
                                FieldInfo uribaseInfo = storeType.GetField("s_uribase", BindingFlags.Static | BindingFlags.NonPublic);
                                uribaseInfo.SetValue(storeType, appName);
                            }
                        }
                    }
                }
            }
        }


        catch (Exception ex)
        {

        }
    }

I have state server enabled in web.cofing

sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:122233" cookieless="false" timeout="240" stateNetworkTimeout="3600" />

The code I am trying to pick the Session saved/shared from Parent application in child (Web Api2) application.

protected void Application_AcquireRequestState(object sender, EventArgs e)
    {
        try
        {
            string loginMethod = "";
            string sFileName = "";
            string userName = "";
            //string sFileExt = Strings.LCase("" + System.IO.Path.GetExtension(sender.request.filepath.ToString()));
            //string serverName = HttpUtility.UrlEncode(Request.ServerVariables("SERVER_NAME"));
            //ILog log1 = log4net.LogManager.GetLogger(HttpContext.Current.CurrentHandler.GetType());

            if ((HttpContext.Current.Session == null || HttpContext.Current.Session["UserID"] == null) && ConfigurationManager.AppSettings["SSOEnabled"] == "1")
            {
                Logger.LogEx("Session is null");
                userName = "" + GetDomainUserName(HttpContext.Current.User.Identity);
                string domainName = "" + GetDomainName(HttpContext.Current.User.Identity);
                loginMethod = "Windows Authentication";


                if (!string.IsNullOrEmpty(userName))
                {
                    Logger.LogEx("Windows userName extracted");
                    Logger.LogEx(userName);
                    Logger.Log(String.Format("Connecting to API with windows username {0}", userName));

                    }
            else if ((HttpContext.Current.Session == null || HttpContext.Current.Session["UserID"] == null))
            {
                Logger.LogEx("Session is null or UserId not found, exception is thrown");
                throw new HttpResponseException(System.Net.HttpStatusCode.Unauthorized);
            }
            else if ((HttpContext.Current.Session != null && HttpContext.Current.Session["UserID"] != null))
            {
                loginMethod = "User is logged in via application Login interface";
                Logger.LogEx("userName is extracted from Shared Session");
                userName = HttpContext.Current.Session["UserName"].ToString();
            }

            if (userName != null && userName != "")
            {
                Logger.LogEx(loginMethod);

            }
            else
            {
                Logger.LogEx("User Name is blank");
                Logger.Log("User should be logged in using Application Login Interface");
                throw new Exception("Unauthorized: User should be logged in using Application Login interface");
            }
            Logger.Log(String.Format("Start request for {0}", HttpContext.Current.Request.Url.ToString()));
        }
        catch (Exception ex)
        {
            Logger.Log(ex);
            throw;
        }


    }

When authentication is set as Windows then "HttpContext.Current.User" is accessible and we are letting API to be accessed.

The same arrangement should work when Anonymous authentication is set, this case "HttpContext.Current.Session" should hold Session values set by Parent, but Session is itself Null.

When we enable session in API, Session is not null, but values from Parent app is not available.

protected void Application_PostAuthorizeRequest() 
{
System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
}

My aim to access the Session Variables set by "Parent Web Site" in to a "Child Web Api 2 App", please help.

1

1 Answers

0
votes

I have found solution to my problem!

The session has to be enabled just before AcquireRequestState event i.e.

 protected void Application_PostMapRequestHandler(object sender, EventArgs e)
    {
        System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
    }