skip to Main Content

I’m trying to use the strangler fig pattern to migrate a legacy Net Framework MVC app in stages. I heard a talk by Mark Rendle about using YARP to migrate a Webforms app this way, which was great. However, I can’t find any examples anywhere of using this methodology to migrate from a Net Framework MVC app to new Net 6 MVC app.

I’ve managed to set up the basic proxy which is working (see example repo below). However I don’t know where to begin with flowing the Identity Authentication through from the Net 6 App to the Net Framework app. I can see that the auth cookie is passed through to the proxied Net Framework app, but I don’t know how to take that and say "hey use this" in the Framework app.

Links:

Any pointers on how to achieve this authentication flow would be greatly appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    Microsoft must have been getting this a lot...

    They have created a new nuget package (currently in preview):

    Microsoft.AspNetCore.SystemWebAdapters

    And have an article on its use (thanks Mike Rousos!):

    https://devblogs.microsoft.com/dotnet/incremental-asp-net-migration-tooling-preview-2/

    I have updated my example git repo and reworked a few bits and everything seems to be working as expected.

    Happy days.


  2. I had exactly this scenario myself. The way I solved it was to take control of writing the authentication cookie – in BOTH applications. The approach relies on the auth cookie written by the ASP.NET Core application being able to be decrypted by the Framework app. That way, the Framework app sees each request as coming from a user that it thinks has already logged in. If the user’s first request hits the Framework app directly, they’d be authenticated as usual, but the cookie would be written in a format that the Core app can understand.

    Key points:

    • My Framework app uses Owin
    • NuGet package Microsoft.Owin.Security.Interop must be added to the Framework app
    • I’m using Microsoft.Identity.Web (2.5.0) to Authenticate the user using OpenID in the Core app.
    • Both applications override cookie behaviour to use a class called TicketDataFormat
      (in Core) and AspNetTicketDataFormat (in Framework). AspNetTicketDataFormat is implemented in the Interop package. Both classes have a constructor that takes an IDataProtector (you must write your own implementation – or, at least, I did).
    • There are TWO IDataProtector interfaces in this scenario. The one in the Core app is Microsoft.AspNetCore.DataProtection.IDataProtector, the one in the Framework app is Microsoft.Owin.Security.DataProtection.IDataProtector.

    Here is the relevant section from Program.cs in the Core app:

    builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApp(
        identityOptions => 
    builder.Configuration.GetSection("AzureAd").Bind(identityOptions),
        cookieOptions =>
        {
            cookieOptions.Cookie.Name = ".AspNet.SharedAuthCookie";
            cookieOptions.Cookie.HttpOnly = true;
            cookieOptions.Cookie.IsEssential = true;
            cookieOptions.Cookie.Path = "/";
            cookieOptions.Cookie.SameSite = SameSiteMode.Lax;
            cookieOptions.ExpireTimeSpan = TimeSpan.FromHours(1);
            cookieOptions.TicketDataFormat = new TicketDataFormat(new AesDataProtector(builder.Configuration["AuthCookieEncryptionKey"]));
            cookieOptions.CookieManager = new ChunkingCookieManager();
        });
    

    and here is the relevant section from Startup.Auth.cs in the Framework app:

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
        CookieName = ".AspNet.SharedAuthCookie",
        CookieSameSite = SameSiteMode.Lax,
        ExpireTimeSpan = TimeSpan.FromHours(1),
        SlidingExpiration = true,
        TicketDataFormat = new AspNetTicketDataFormat(new AesDataProtector(authCookieEncryptionKey)),
        CookieManager = new ChunkingCookieManager()
    });
    

    Class AesDataProtector is my own class – and there are two of them. One each in the Core and Framework apps that each implement the appropriate IDataProtector interface. These classes actually do the reading and writing of the cookie data. The way I’ve coded my AesDataProtector classes, they are passed a key (it has to be the same one in each app) as a string value into the constructor. In both classes, I’ve used System.Security.Cryptography.Aes to do the encryption and decryption. You can use whatever cookie name makes sense to you, but it must bee the same in both apps.

    We’ve gone into production with the changes to the Framework app, so the user’s authentication cookie is now being written the new way and has not caused us any issues. Having proved this out in testing, we know that when we’re ready to deploy the Core app, the authentication will ‘just work’.

    I found this article of great help in figuring this out: https://learn.microsoft.com/en-us/aspnet/core/security/cookie-sharing?view=aspnetcore-7.0

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search