asp.net-coreoauthproxygoogle-oauthnuxt3.js

Google login with client and server on different domains (Nuxt SPA, ASP.NET Core)


It's been a few days I'm trying to find a way around this. It should be pretty common to host the client and server on different domains, as I've read about it. However, the specifics of how to make this work with Google OAuth are quite mysterious with the setup I have.

First off, it works. Unless it is run on certain browsers, those which block third-party cookies, namely Brave, which I mainly use, and Safari. It works on Brave if I turn the default, block third-party cookies, off.

In the most functional state, I use an external link in my Nuxt app to my API endpoint, which redirects the user to Google, and after logging in there the server redirects the user back to the client app with a cookie storing their token. Works unless third-party cookies are blocked.

Thus, I sought to use a proxy so that cookies pass through the Nuxt server (at my client's domain) to be received by the client app. I can confirm my requests are being made to the proxy server, and my email/password login which operates by the same cookie is functional. But the Google login page which would appear under https://accounts.google.com/, now appears under my own client's domain, and after entering my email, I face this: Something went wrong

Which seems like my proxy is taking care of too many things (even those related to Google).

One thing I tried is setting redirect="manual" in my Nuxt proxy:

const res = await proxyRequest(event, target, {
  fetchOptions: { credentials: "include", redirect: "manual" },
  cookieDomainRewrite: "nietzschess.xyz"
})

Which made the Google page render under https://accounts.google.com/, as it should. But now, after login, Google redirects back to my backend's callback URI, and the API gives 500s. API logs imply an issue in Correlation:

warn: Microsoft.AspNetCore.Authentication.Google.GoogleHandler[15]:
'.AspNetCore.Correlation.YzS8xkFzg-4OG36DirGmUHqimr5lOwXKftNgHxO24Ec' cookie not found.
info: Microsoft.AspNetCore.Authentication.Google.GoogleHandler[4]
Error from RemoteAuthentication: Correlation failed..
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HNBNDSENR62I", Request id "0HNBNDSENR62I:00000005": An unhandled exception was thrown by the application.
Microsoft.AspNetCore.Authentication.AuthenticationFailureException: An error was encountered while handling the remote login.
 ---> Microsoft.AspNetCore.Authentication.AuthenticationFailureException: Correlation failed.
--- End of inner exception stack trace ---
 at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
 at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
 at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

There is a Correlation cookie on the request to the callback URI, with an unmatching Id .AspNetCore.Correlation.wBq43NhtKaKq7pwjxUNe-EasZpTygbPqzEylzqnXwOY=N. I understand that the correlation cookie is assigned to the client at the beginning of the OAuth process, and is invalidated by the end when my client receives the token. I don't exactly know how it gets unmatching at this stage though, so any help is appreciated.

Additionally, I posted the question under a more general title so those who have done this before in a different way should tell me if there's a better way, or about existing examples.

My code is available on github, although running it locally would be difficult due to the environment variables it uses:


Solution

  • Following ChatGPT's advice, I implemented the PKCE flow for authentication while letting the server get the code at the last stage, and ask for the token itself to register the user in my DB. All while the Nuxt proxy is in place, and forwards API requests.

    This worked out, and my authentication now works for Brave and Safari. However, the proxy led me to other issues. Due to the game nature of my app which requires websocket connections and fast interactions, that is hindered by the proxy. So I'm going to seek a solution to bring my API and frontend to the same domain.