This project is a working example of using React as the front end, ASP.NET Core as the back end, with both managed by Aspire, to:
- Sign in on the back end using Google Oauth2.
- Authenticate both http/s and websocket/s back end endpoints using Jwt Bearer header authentication.
This was developed to provide a working example given the poor or outdated documentation and examples relating to how Microsoft's Google authentication classes work and how they should be configured, what middleware is and isn't required, what order middleware should be placed in the pipeline, how to set up React with Aspire, how Microsoft's Identity and Identity Core should be involved, if at all, subtle changes in how setup is performed over different versions, etc. -- some of the things that, if they didn't exist, would make working with ASP.NET Core much more of a joy.
This example is particularly focused on the .NET 9 version of ASP.NET Core.
- It is mostly implemented with minimal APIs for clarity. However, the Websocket/Signalr hub is controller based.
- Front end is Vite-built basic react and does not include React-Router or other router.
- Comments in code note things discovered empirically when building this example (aren't clearly documented, or documentation is wrong).
- Includes a pattern for overriding authentication handlers (e.g.
WebApplicationAuthenticationExperiment.Google.SubscriberGoogleAuthenticationHandler) to use an injectedWebApplicationAuthenticationExperiment.Subscriber.ISubscriberAuthenticationHandlerimplementation which could, for example, use the authenticating user's external unique id to determine (e.g. by checking a subscriber db table) if the user is a subscriber before considering the authentication successful. - Includes a base hub class
WebApplicationAuthenticationExperiment.Subscriber.SubscriberHubthat obtains the connecting user's external unique id which could be used, for example, to determine (e.g. by querying a tenant db) the user's tenant then add the connection to the signalr/websocket group for the tenant so messages can be sent to only a specific tenant's users (e.g. when a tenant alarm goes off, to inform only that tenant's users' connected UIs to update their alarm displays). - React Authenticator and Listener are both implemented as Typscript classes so they can be easily reused in other Typescript applications.
- Implementation of React
useEffectinApp.tsxcorrectly deals with signed in and signed out state. - Shows how to configure Vite to proxy api requests to the back end without hardcoding endpoint urls by using an Aspire
AppHostmechanism that injects environment variables with information about another service into services that reference it withWithReference()
- Google authentication requires setup with google as documented here. Note that both of the following must be added in Google's Authorized redirect URIs section for this example to work.
It appears the second is needed due to a bug/poor design in Microsoft's Google implementation (tell me if this disaster
makes any sense!). Take note of the
clientIdandclientSecretfor the Setup step that follows.
- .NET 9 SDK
Fill in the values marked [FILL IN] in WebApplicationAuthenticationExperiment/appsettings.Development.json:
Jwt:secretKeywith a 15+ character self-generated secret string.Google:clientIdandGoogle:clientSecretobtained from set with Google as identified in Prerequisites #1 immediately above.
"Jwt": {
"issuer": "compass-point",
"audience": "iot-app",
"secretKey": "[FILL IN]"
},
"Google": {
"clientId": "[FILL IN]",
"clientSecret": "[FILL IN]"
}
}