asp.net-mvcoauth-2.0asp.net-identityidentityserver4openid-connect

Authentication using both Session cookies and/or JWT Bearer Token in .Net Framework Legacy Appliction


I am currently in the process of migrating an existing ASP.NET MVC Monolithic application to .NET Core using microservices. Part of this migration now involves using Identity Server 4 with an external identity provider. The migration is using the strangler pattern in that we are slowly migrating out the old system, rather than doing the entire migration at once. Therefore we must support the legacy system that uses cookie based session authentication as well as the new microservice apis that use JWT bearer tokens.

Currently I am exploring the simplest method to support both types of authentication until the migration is 100% complete. The web app is fine as it still uses razor pages and server side authentication, therefore can easily establish a session, as well as pass back my token for api authentication. My mobile client is the problem, it is built using ionic and previously used server side session authentication (before my time..). Now that I am using the OpenID Connect protocol with an external ISP all my authentication flow is handled on the client for mobile, therefore a session is not being created.

Option 1: Using strictly my JWT bearer token for authentication on my mobile application and somehow configure my MVC Controllers to be able to use JWT authentication if it is present in the header or Cookie authentication if there is a cookie present in the request (legacy web app). I am not sure if I would need to create custom middleware to accomplish this or if there is a way to configure something in the startup without having to create middleware and the controllers [authorize] attribute will simply know to use cookie or bearer auth. I found an article explaining that this is possible on Core but have yet to find anything related to .NET framework.

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
           //configuration goes here
        });

        app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
        {
           //configuration goes here    
        }

Option 2: Create a new endpoint in my legacy application server and have my mobile client pass the bearer token I receive to the endpoint in order to establish a session. Now my mobile client can pass the cookie and the bearer JWT token in every request and let the server decide how it wants to validate. This obviously adds a little bit of complication as now I am maintaining a cookie and token expiry etc, but it would only be until the migration is over.

Option 3: ???

Question: I have spent a lot of time researching the validity of either options and mostly only getting resrouces related to .NET core, however very little on .NET Framework. I will only need to support the legacy application for a short period of time so I at this point I am looking for the easiest solution rather than the cleanest. Wondering if anyone who has done a similar migration can provide a solution or inisghts on how they were able to accomplish this?


Solution

  • I did something similar recently where I had API Controllers and MVC Controllers in the same project. The API controllers authenticated with JWT and the MVC Controllers with Cookie Authentication.

    This may not translate directly to your issue but hopefully it helps...

    The Startup.Auth is set up similar to what you have in option 1.

    In your configuration classes you can use filters to select the type of authentication to use:

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();
            //Tells APIs to ignore the Default Cookie Type Authentication
            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
    
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
    
        }
    }    
    

    The important parts being config.SuppressDefaultHostAuthentication(); and config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

    The remaining pieces from here are to actually build the token and then consume it.

    Helpful material for using JWT with Identity