Search code examples
asp.net.netasp.net-mvcasp.net-core.net-core

Antiforgery token migration from .NET framework to .NET Core


We are slowly working on migrating code from the .NET Framework to .NET Core, mostly Razor views sites. We have built a proof of concept and it all works fine, except the anti-forgery tokens from one site to the other.

I haven't really been able to find any documentation or examples on how it would work. My use case is we are migrating small parts using their recommended approach using YARP and proxying calls back to .NET Framework legacy project.

  • So users hits some page (.NET)
  • User Submit form from view (.NET)
  • Server handles request (.NET Core)

This is the use case we are facing that we haven't moved the frontend code, but would like to be able to migrate mostly backend code first and views near the end.

I have looked a bit into Machine key on the .NET framework side

  <!-- Configure machine key for data protection -->
  <machineKey
      validationKey="AutoGenerate,IsolateApps"
      decryptionKey="AutoGenerate,IsolateApps"
      validation="SHA1"
      decryption="AES"
      validationKeyPath="c:\temp-keys\validationKeys"
      decryptionKeyPath="c:\temp-keys\decryptionKeys" />

and AddDataProtection for the .NET Core side:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"c:\temp-keys\"))
    .SetApplicationName("YourAppName");

But I'm not entirely sure if this is the right approach and how to align the keys. .NET Core seems to create 1 file while .NET framework seems to expect 2 files. So any pointers / help would be nice :)


Solution

  • So I didn't find a way to share Antiforgery token or get them to work both places. But I did find a 2 solutions that would work:

    Both involved having an API endpoint to create Antiforgery token on new AspNetCore API.

    1. Have javascript call the Endpoint and get token like described here. https://learn.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-8.0#javascript-ajax-and-spas
    2. Call the API endpoint from the .NET framework website and forward all the cookies / headers needed. Send the token to the frontend that could then call the website as intended.

    Just simple example in code below

    .NET Core endpoint:

    app.MapGet("antiforgery/token", (IAntiforgery forgeryService, HttpContext context) =>
    {
        var tokens = forgeryService.GetAndStoreTokens(context);
        context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken!,
                new CookieOptions { HttpOnly = false });
    
        return Results.Ok(tokens.RequestToken);
    });
    

    .NET Framework call API and set Cookies

        var handler = new HttpClientHandler();
        
        // Create an instance of HttpClient with the handler
        using (var httpClient = new HttpClient(handler))
        {
            // Make a request to a website to get some cookies
            var response = await httpClient.GetAsync("https://example.com");
            
            // Check if the request was successful
            if (response.IsSuccessStatusCode)
            {
                // Get the cookies from the handler
                var cookies = handler.CookieContainer.GetCookies(new Uri("https://example.com"));
                foreach (Cookie cookie in cookies)
                {
                    // Add cookies here
                }
            }
            else
            {
                Console.WriteLine($"Error: {response.StatusCode}");
            }
        }
    

    Worked for us :)