Login/Authentication with OAuth2 and single-spa - reactjs

I've started building a prototype for a front-end layer with single-spa. The layout is very similar to https://github.com/react-microfrontends, which means:
Root config
A navbar (React)
Two apps (Both React)
A Styleguide module
An API module to handle communication with a set of API
I managed to get a basic prototype running, but I now need to implement some OAuth2/OpenID based authentication, and I'm not sure where to start. I need the user redirected to a separate URL (Auth0 style) if not authenticated or not having a valid JWT, then I need a mechanism of token refresh whenever the auth token expires. On top of any general advice on best practices, existing examples and so on, I have some specific questions I can't quite work out.
How can I redirect the user to a different URL when not authenticated? Which of the modules/components should be responsible for it?
Is there a library that implements OAuth2 out of the box? In particular, I'm interested in some sort of automatic token refresh.
What is the best way to make sure an unauthenticated/unauthorized user cannot access the app bundles?
Thanks in advance.

The typical approach would be to set up an Auth microfrontend that would :
handle credenials retrieval upon login. Be it via Password flow or OAuth ( in your case). Since you are using React, your OAuth provider should have a library that you can use within the Auth MFE to interact with it. If it's keycloak, React Keycloak is a good fit. There's no rule lf thumb here.
pass the credentials to your two React Apps ( Microfrontends) and the API module via Browser storage or shared state.
Doing so, the API module would set the credentials in the API calls. and the two react Apps would check credentials presence before proceeding with their inner logic.
refresh credentials on expiration or log out user ( depending on your logic ). Loging the user would mean deleting the credentials from browser storage for example.
redirect to one of your react App after login. That means the Auth MFE route should always be active in the root config.
I hope it helps. Here I have summarised the flow.
More of it on my github account https://github.com/exaucae/single-spa-patterns/blob/master/AUTHENTICATION.md

Related

Setting up React app using Firebase and Spotify Web API

I’m in the process of creating a React application that will use Spotify’s web api to compile different types of analytics from each users’ Spotify account.
I set up my react app to use Firebase’s authentication so users can create an account and once logged in, link their spotify to that account.
The goal is to store important info in the user database like the web api’s refresh token so they don’t have to re-link their account in the future when they log in. However, I have very little experience with any of these frameworks and don’t know the best way to handle authenticating each users’ spotify account within my React app.
Should I also create an express server to handle the callbacks for my spotify authentication, database queries, and sending data to the front end, or can all of this be handled in React? And if it can be handled in react, where should I set the callback uri to go? The app has a home page for new users to see its features, and a dashboard page that they go to once logged in.
Sorry if this isn’t very well described, but Im basically just looking for the best practice stack to use for a React-Firebase App that uses the spotify web api, and whether or not I need to separate the spotify authentication into some backend to handle those requests.
I tried setting the callback to go to the Dashboard, but that means every time the user goes to the dashboard it has to check for the callback url parameters that it sends, which doesn’t seem like the best way to handle it.
I also tried creating a /callback page to handle the spotify authentication, which worked but meant there was a random callback page on my site, which also doesn’t seem ideal, so Im not sure what the best way to handle it is.

Authentication and Authorization in React app

In a .NET app I can add authentication and authorization using web.config and/or IIS. I can also use [Authorize (Roles = "RoleABC")] in a MVC app's controller or action. And even extend the AuthorizationAttribute
I'm looking into creating a React app for intranet use, and reading these tutorials (ReactJS and MS), but can't find authentication/authorization details.
Even though the app will be Single Page App, I still would like to authenticate and authorize users for certain options within the app, just like I can do in MVC app.
Is the only option to do that way is creating Blazor app instead?
For authentication and authorization, you should use auth tokens (like JWT). Your backend should create an auth token when a client logs in to the system and sends it to the client. Your server also should send the authenticated user information to the client (react app) so that you can render correct pages according to the user type. For example, you can render the admin page for an admin type of user, and the guest page for a guest type of user. You can save this user data as JSON in Redux. Hence you can access the user data from any component of your react. Also, in your backend, you must restrict the endpoints according to the auth token which is sent by the client. In the backend of my app, I follow the below steps:
Authentication check -> Authorization check -> controller (endpoint) -> result
React isn't opinionated on this, so it's up to you to design the implementation. A basic way to do this is:
Log in and obtain an authorized JWT token from the backend and include the account ID when you sign it
Store the JWT token in localStorage, store the account info in Redux
Conditionally limit routes based on account info (ie. admin group) on the front end
Have every auth-required API call include the JWT token in the x-auth-token header, then on the backend use middleware to check if it's still valid. You can then also decode the account ID in order to check its privileges so that you can limit API access
This may be helpful: https://medium.com/#faizanv/authentication-for-your-react-and-express-application-w-json-web-tokens-923515826e0#5f52
Not sure whether you still need this - I personally feel we should have something bridging the authZ gap between server and client to make it easy. So I spent a few days on a github project for this purpose, here it is: authzyin.
What I tried to do is to leverage policy based authorization from asp.net core - which I think it's very cool - and automatically bring the same definition to the client to use in React via hooks.
For authentication I am using msal.js against AAD - so authN is done on the client and jwt bearer token auth is used for all requests.
It has a client lib and a server lib which can be used together or separately. Of course it might still be lacking some features - please feel free to take it as a reference (contribution is also welcome).

OpenID Connect SSO in React-Redux app

I'm trying to implement SSO on my React-Redux app using an OpenID-Connect provider. The intent is to protect all components and redirect the user to the Identity Provider's login page if the session ends.
This is why I cannot have a dedicated Login page (component) in the application.
I've read that saving JWTs in the localStorage could be a good idea so I was thinking of using a flag isAuthenticated in the Redux store and keep JWTs in the localStorage. I can then fetch the JWTs from the localStorage to authenticate other APIs I'd be calling from within my app. Is this approach appropriate?
Moreover can anyone point me to a library/package that I can use to fetch (and refresh) JWTs for this purpose? I went through a lot of documentation and tried out the following but couldn't get these to work:
redux-oidc: I don't have any specific Callback component in my application so I don't quite know how to apply this approach to my app.
passport-openid-connect: Passport relies on storing sessions in cookies but I'd like to use the localSorage instead.
redux-auth-wrapper: A higher order component sounds great but I still cannot figure out how to integrate it without any dedicated Login component.
Could someone please guide me through? I'm a newbie to the React ecosystem so please excuse my incomprehension.
Any help would be much appreciated!
Thanks
You are on the right track - redux-oidc manages your Redux state with the login details - the client library that actually manages the JWT (implicit flow), redirecting to the IdentityServer (whichever) login page and returning to your app (the "callback") is oidc-client.
redux-auth-wrapper is just a HOC (High Order Component) - basically a wrapper to check if the user is authenticated (either in the Redux store or with a custom function) and forward to a login page - in my opinion you do not really need it as redux-oidc already gives you everything you need.
I personally also implemented an IdentityServer4 - to centrally manage all external providers - and it's been working great so far.
I would suggest first looking at https://blogs.msdn.microsoft.com/webdev/2017/04/26/the-mvp-show-learns-about-asp-net-identity-server-and-heidelberg/ where the creator of IdentityServer4 is explaining extremely well how the identification works and the flows (implicit vs hybrid).
Once you know the Identity basics and how it all hangs together, have a look at the redux-oidc sample (very easy to follow).
Have fun ;)

Example of an SPA with a login screen that uses AngularJS and connects to ASP.NET Web API 2?

I would like to create a new AngularJS, Web API Single page application. Does anyone have any examples that show how I can set up a user login screen that connects to a WEB API controller for a simple login (no need for google/facebook login etc) that uses ASP.NET Identity and without the need for user registration.
Also how can I handle showing a new view once the login has been completed. What I would like is to have a solution that does not show routing in the browser URL. So for example I would like to be able to switch from the login view and a couple of other different views without the url changing from www.abc.com.
In other words I would like to avoid showing www.abc.com/login, www.abc.com/screen1, www.abc.com/screen2
Any advice would be much appreciated.
So, instead of trying to find an example, I created one instead (link at the bottom). To explain how the functionality works, I want to go over a few things:
The new ASP.NET Identity system provides an OAuth 2.0 Bearer token implementation which can be used with clients that consume a Web API resource over HTTP. Since the authentication is not stored in a session cookie, the server is not responsible for maintaining the authentication state. The side-effect is that the consumer has to manage authenticating the server and managing the returned token. This is the system that Microsoft uses in the SPA template that it provides with VS 2013.
AngularJS makes no assumptions about authentication, so it's up to you how to authenticate.
AngularJS provides the $http service for querying remote HTTP-based services as well as $resource which is built on top of $http. Using Authorization headers with the Bearer token implementation above, you can combine both to provide authenticated access to server resources over HTTP. AngularJS allows you to set a 'default' Authorization header which it will use in every subsequent HTTP transaction.
With that in mind, the way I accomplished this is by creating a User service that handles all of the authentication details, including setting the HTTP Authorization header, between the Web API server and the SPA. Based on the authentication status of the user, you can hide certain UI elements in order to prevent navigation. However, if you also define the state as requiring authentication as a property of the resolve object for the state, a watcher set on the $stateChangeError event will capture the error and redirect the user to the login form. Upon proper authentication, it will then redirect the user to the state they were trying to navigate to.
In order to prevent authentication from being lost between browser sessions (since the client is responsible for maintaining the authentication token, and that token is maintained in memory), I also added the ability for the user to persist the authentication to a cookie. All of this is transparent to the user. For them, it is practically identical to traditional form-and-session based authentication.
I'm not sure why you want to prevent the user from seeing the routes, but I have coded it as such. I am in debt to Sedushi's Plunker example of how to use AngularUI Router to navigate in a stateful manner without using URLs. Still, I'm not sure I can personally recommend this for any application I would write on my own.
The full solution (both the WebAPI and the WebUI) is available with step-by-step instructions here.
Let me know about any specific part that is unclear, and I will try to make it more clear in the answer.
Refer the following blog for the demo of single page application (SPA) for ASP.NET Web API 2 and AngularJS, developed by the team at Marlabs.
http://weblogs.asp.net/shijuvarghese/archive/2014/01/25/demo-spa-app-for-asp-net-web-api-2-and-angularjs.aspx
The app is built with following technologies:
ASP.NET Web API 2
EF 6 Code First
AutoMapper
Autofac
Semantic UI
AngularJS 1.1.5
The application is published on github at https://github.com/MarlabsInc/webapi-angularjs-spa.
#DavidAntaramian gave a great example. But if you want a simple one, you can look to this HOL from Microsoft.
Their latest example on github uses .NET Core, but you can download release from October 2015.

AngularJS and Firebase Authentication

I would like to add an authentication mechanism to my AngularJS app with Firebase backend. The requirements are simple:
Authenticated users should be able to access any page.
If unauthenticated users goes to /some_page (any page except /login), they should be redirected to /login. Once they enter the right credentials, they should be redirected to back to /other_page.
Possible solution that is described here makes the following assumption:
My solution assumes the following server side behaviour: for every
/resources/* call, if user is not authorized, response a 401 status
But, I'm not sure if it is possible to enforce this behavior when using Firebase as a backend.
Any help and/or examples to implement such AngularJS+Firebase integration will be appreciated!
One solution is to do your routing on the client side with the $route service.
When a user authenticates through Firebase, save some record of this on the client, like in localstorage, some all-encompassing controller, or your own Angular service (my preferred option).
In your routing controller, if the user is authenticated, redirect to /some_page, otherwise redirect to /login and keep track of the $location where the user intended to go.
If, on the other hand, you want to route with your server, you could use the solution you linked to by having your server generate Firebase auth tokens.
I had the same requirement recently and came across this blog post.
http://www.42id.com/articles/firebase-authentication-and-angular-js/
It explains setting up an Angular JS application that interacts with Firebase. Also included are ways to authenticate against OAuth providers such as Google+ and Github using Firebase API, routing based on authentication status, storing user profile information on Firebase and setting up security rules on Firebase to protect user data.
If you are using Firebase Simple Login (rather than generating the authentication tokens on your own servers), you can see how to detect your login state client-side here:
Displaying text after login

Resources