title: Azure ad b2c authentication challenge loses session object
body: <p>I am using the github example active-directory-b2c-dotnet-webapp-and-webapi.</p>
  
  <p>I configured my own b2c tenant and got the MVC sample to work successfully.</p>
  
  <p>However, I need this to work with a WebForms app. I created a new Webforms app, checked that the references were pointing to the same versions of the dlls as the working sample and adjusted the code to work in WebForms.</p>
  
  <p>Everything works up until the time that I issue the Authentication.Challenge and process the AuthorizationCodeReceivedNotification in the OnAuthorizationCodeReceived function.</p>
  
  <p>The Session object in notification.OwinContext.Environment["System.Web.HttpContextBase"] is null whereas at this point in the MVC sample the session object in notification.OwinContext.Environment["System.Web.HttpContextBase"].Session is a System.Web.HttpSessionStateWrapper with a valid SessionId.</p>
  
  <p>In WebForms, HttpContext.GetOwinContext throws an error as not being available, so I then tried HttpContext.Current.GetOwinContext which returned an HttpContext object instead of a HttpContextBase object. So I finally used</p>
  
  <pre><code>if (!Request.IsAuthenticated)
  {    
     HttpContextBase context = new HttpContextWrapper(HttpContext.Current);    
     context.GetOwinContext().Authentication.Challenge();
     return;
  }
  </code></pre>
  
  <p>instead of the following which is used in the MVC sample</p>
  
  <pre><code>if (!Request.IsAuthenticated)
  {
     HttpContext.GetOwinContext().Authentication.Challenge();
     return;
  }
  </code></pre>
  
  <p>At this point in the code, in both MVC and WebForms the Authentication object has a valid Session object in its OwinContext.Environment prior to the Challenge being issued. The problem is that whilst in the MVC version the resulting notification includes the session object, the WebForms version of the notification has a null object.</p>
  
  <p>The problem finally surfaces when getting the TokenCache by calling the MSALSessionCache which uses the httpContext.Session object (MVC works; Webforms throws Null reference exception)</p>
  
  <p>I am aware that MVC and Webforms treat the session differently but cannot work out how to solve this problem.</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>Whilst this worked it did not address the problem regarding the session id. I added                 </p>
  
  <pre><code>Notifications = new OpenIdConnectAuthenticationNotifications
                  {
                      AuthenticationFailed = AuthenticationFailed,
                      AuthorizationCodeReceived = OnAuthorizationCodeReceived,
                      MessageReceived = OnMessageReceived,
                      SecurityTokenReceived=OnSecurityTokenReceived,
                      SecurityTokenValidated= OnSecurityTokenValidated
                  },
  </code></pre>
  
  <p>to your code with the appropriate stubs for these functions. MessageReceived was invoked as was SecurityTokenReceived and Validated. However, AuthorizationCodeReceived was never invoked. When the first three were invoked, I examined the notification.OwinContext.Environment["System.Web.HttpContextBase"] and in all cases the Session object is null - which is what my problem was to start with.</p>
  
  <p><strong>EDIT (includes answer)</strong></p>
  
  <p>Thanks to @Ramakrishna the solution is to add A RequireAspNetSession helper function at the beginning of ConfigureAuth. The revised code snippet for his sample is as follows:     </p>
  
  <pre><code>public void ConfigureAuth(IAppBuilder app)
      {
          RequireAspNetSession(app);
  
          app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
  
          app.UseCookieAuthentication(new CookieAuthenticationOptions());
  
          // Configure OpenID Connect middleware for each policy
          app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(SignUpPolicyId));
          app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(ProfilePolicyId));
          app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(SignInPolicyId));
      }
  
      public static void RequireAspNetSession(IAppBuilder app)
      {
          app.Use((context, next) =&gt;
          {
              var httpContext = context.Get&lt;HttpContextBase&gt;(typeof(HttpContextBase).FullName);
              httpContext.SetSessionStateBehavior(SessionStateBehavior.Required);
              return next();
          });
  
          // To make sure the above `Use` is in the correct position:
          app.UseStageMarker(PipelineStage.MapHandler);
      }
  </code></pre>
  
  <p>you will need to add the following references:</p>
  
  <pre><code>using System.Web.SessionState;
  using Microsoft.Owin.Extensions;
  </code></pre>