13

I'm entirely new to OWIN and this issue has been a major blocker for me.

Basically, at my MVC app I have the following at Startup class:

public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
        app.UseCookieAuthentication(new CookieAuthenticationOptions());
        app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = OfficeSettings.ClientId,
                    Authority = OfficeSettings.Authority,

                    TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters()
                    {
                        RoleClaimType = "roles"
                    },

                    Notifications = new OpenIdConnectAuthenticationNotifications()
                    {

                    AuthorizationCodeReceived = (context) =>
                        {
                        // code hidden for readability

                            if(HttpContext.Current.Session == null)
                            {
                                // It's null. Why is that?
                            }

                            var session = HttpContext.Current.Session;
                            if (session["myMockSession"] != null)
                            {
                                // Do stuff...
                            }
                        },

                        RedirectToIdentityProvider = (context) =>
                        {
                            // code hidden for readability
                        },

                        AuthenticationFailed = (context) =>
                        {
                            // code hidden for readability
                        }
                    }
                });

I don't understand why when I'm debugging that the Session is null. HttpContext.Current Property isn't. Are there any constraints with Sessions + OWIN? Is there any workaround for this issue? How should one approach it?

Side note 1: I've tried to add this piece of code I've found in one of the SO questions and the Session was still null:

app.Use((context, next) =>
            {
                // Depending on the handler the request gets mapped to, session might not be enabled. Force it on.
                HttpContextBase httpContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
                httpContext.SetSessionStateBehavior(SessionStateBehavior.Required);
                return next();
            });

Side note 2: I don't seem to find it anymore, but someone suggested in one of the SO questions to add empty methods Session_Start and Session_End (as empty methods) at the Global.asax. That didn't worked neither.

I'm welcoming any advises. Thanks!

AuroMetal
  • 928
  • 3
  • 14
  • 32
  • I have similar issue. were you able to find some solution. – RonakThakkar Jun 29 '16 at 15:35
  • Hi @RonakThakkar. Unfortunately, not yet. I had to put this task aside because I couldn't find any solution. Perhaps we may get a solution in this thread, hopefully. – AuroMetal Jun 30 '16 at 07:20
  • Hi AuroMetal, thank you for posting this question. I have been trying to get this to work, but I am not sure where to plugin the solution by @Johan O exactly. I would really appreciate if some one can provide more details. – A P Aug 13 '18 at 20:02
  • 1
    Hi @AP, if I understood you correctly you are asking where to put this code? Bear in mind it's been over 2 years since the question, but I believe when you create a ASP.NET Web Application > MVC Template (Change Authentication - either Individual User || Work or School Account) an App_Start directory is created and under it there's a Startup.Auth.cs and there it's where you plugin the solution. Again, it's been so long that I may be wrong, so apologies in advance. – AuroMetal Aug 14 '18 at 08:15

1 Answers1

17

You're almost there. The reason your session is still null is that you have not instructed OWIN to initialize System.Web Sessions prior to your middleware is beeing executed.

By adding .UseStageMarker(..) after your middleware registration you'll tell OWIN where in the execution pipline it should perform SetSessionStateBehaviour

app.Use((context, next) =>
{
    var httpContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
    httpContext.SetSessionStateBehavior(SessionStateBehavior.Required);
    return next();
});

// To make sure the above `Use` is in the correct position:
app.UseStageMarker(PipelineStage.MapHandler);

By default, Owin Middleware run at the last event (PipelineStage.PreHandlerExecute) which is too late for you in this case.

Now, to use sessions, you need to work in a second middleware, that runs after the session has been Aquired by the Asp.Net runtime. This middleware must be run in the PostAquireState phase, like so:

.Use((context, next) =>
 {
     // now use the session
     HttpContext.Current.Session["test"] = 1;

     return next();
})
.UseStageMarker(PipelineStage.PostAcquireState);

Asp.Net katana docs has an excellent article on how the middleware works. See the PiplineStage enum docs and the HttpApplication docs for details on the execution order in Asp.net.

bounav
  • 4,886
  • 4
  • 28
  • 33
Johan O
  • 444
  • 4
  • 8
  • Hi @Johan O, absolutely fantastic explanation! Thank you very much for the details, hopefully that will help a few of us with the same issue. – AuroMetal Jul 06 '16 at 09:53
  • Your solution works but fails for `OpenIdConnectAuthentication`. I replaced your second snippet with `app.UseOpenIdConnectAuthentication(..., Notifications = new OpenIdConnectAuthenticationNotifications { RedirectToIdentityProvider = (context) => { Console.WriteLine(HttpContext.Current.Session["test"]); } }); appUseStageMarker(PipelineStage.PostAcquireState);` but I get a null session in my `RedirectToIdentityProvider()` callback function. – Exegesis Aug 26 '22 at 14:24