Tom Troughton
Tom Troughton

Reputation: 4325

ASP.NET Identity with React app is breaking on OAuth2 callback

I have used the ASP.NET Core React project template to create a web application into which I've installed Identity Server 4. The React app takes care of all the user interaction, with the dotnet application used as an API only. I've integrated a Google OAuth2 authentication option using the services.AddAuthentication().AddGoogle builder extension provided by Microsoft.AspNetCore.Authentication. Finally, the whole thing is containerised and deployed to a Linux App Service on Azure.

Most of my code was ported from a previous version which was a very similar setup but in that case I'd added a custom React app to an existing ASP.NET application rather than start with the official React project template for dotnet. Back then everything worked well. But I'm facing problems with my new version when deployed to Azure. Here's a Fiddler trace to highlight the issue:

enter image description here

vault2 is a client of the identity service. identity-azure is the Identity Server application. The flow this trace shows is as follows:

  1. User clicks Sign In on the Vault application
  2. Browser is redirected to the Identity application
  3. User clicks the Google button to initiate the OAuth2 flow
  4. User signs in with Google account
  5. User is redirected to the default callback URL (https://identity-azure.<domain>.com/signin-google?state=...)

This last step is where the problem is. You'll notice that you don't see the callback URL in the Fiddler trace, but instead you see a couple of other requests (e.g. service-worker.js) which are clearly being made from the React app. So the signin-google path is being handled by the browser's cached React app and not the server. The React app uses react-router-redux to handle certain routes client-side, and of course signin-google is not one of these so it appears to be returning an empty component.

As far as I can tell, all my ASP.NET routes (implemented using the Route attribute to decorate controller action methods) are handled consistently by the server. However, the signin-google route is implemented in the authentication middleware so as far as I know I don't have much control over it other than to change its path. Is there something I can do to force this to be handled server-side?

I should add that this behaviour is quite erratic. It seems that if my Google account is signed out then the above is observed, but if my account is already signed in then signin-google returns the expected 302 status code and the OAuth2 flow continues successfully.

Upvotes: 0

Views: 1259

Answers (1)

Tom Troughton
Tom Troughton

Reputation: 4325

I finally worked out what was going on. At least, I think I have. I can't be certain because I've since broken the React UI out into an entirely separate application but I was observing a similar pattern there. There was even a clue in my original question! Turns out the breaking pages were actually being served from the React app's service worker. I discovered this because even after breaking the React app out under its own domain leaving my identity-azure domain a pure ASP.NET Web API, requests for certain URLs under identity-azure were still behaving the same and I eventually noticed they were reporting themselves as being served by ServiceWorker on my browsers's Network tab. Example below.

enter image description here

As soon as I cleared the browsers application cache (in Chrome on Windows this was F12 > Application > Clear storage > Clear site data with Unregister service workers checked.

I'm not 100% sure what the solution would be if I'd left my React app in the same solution as the ASP.NET backend, but I presume it'd involve excluding specific URLs from service worker. I hope this helps someone in the future.

By the way, if you're thinking of building a fully decoupled UI for Identity Server 4, there's a great starter example here.

Upvotes: 1

Related Questions