Implement CSRF in ReactJS PWA with ExpressJS proxy to API backend - reactjs

I have the following setup:
ReactJS PWA frontend application that uses service workers to cache the source code to the client.
ExpressJS Reverse Proxy which relays any request that would go to a backed API. This handles a login process and stores a token on the server and sends a session cookie to the client. The cookie is HtttpOnly, SameSite, Secure and signed. The proxy also checks if the connection is secure, referrer is in white list and exact match and same for the host.
Backend API is on a different server with OAuth login protection.
Express returns a server side rendered page on the first load then ReactJS hydrates that page and uses as an SPA. Every file afterwards is cached into the browser.
Every request that comes from the client app is handled with the same token as they are not user specific operations. User specific operations require e-mail and password to get a new unique token from the API.
My issue is:
An attacker could create a cookie and send it along with a curl request to the proxy. This would by pass my ReactJS app as both referrer and host can be faked.
I would like to find out how can is secure the connection between the ExpressJS proxy and the ReactJS PWA.
I was thinking about CSRF with csurf but that would not work. If the PWA is installed on a phone's as an app, then it would only access the Proxy when the request is sending. Therefore I cannot set the CSRF header.
If I was to add the CSRF token to the very first request when the client hits the server and the page is rendered with SSR, I would only set the token only once, which can be re used as many times as the attacker wants.
Is there a proper way to lock the proxy to the app somehow?
I cannot store anything in Local storage and I cannot hard code tokens into the source code of the app. (They are insecure options)
Thanks!

Related

secured spring boot backend with React Frontend

i managed to secure my spring boot backend (localhost:8081) with keycloak as an authorization server (with an access token needed), but i want my frontend (react with port localhost:3000) to access the data which is secured. Thus meaning that localhost:3000/products should fetch data from localhost:8081/products after a successful login.
Could anyone guide me on this problem?
You choose an OIDC client lib for react. It should handle
redirection to authorization server for login
redirection back from authorization server with authorization code
exchange of authorization code for access, refresh and ID tokens
automatic access token refreshing
(maybe) automatically insert authorization header with bearer access token for configured routes
The requests your React app will issue to Spring resource server will then have required JWT access token.
PS
Make sure your Spring back-end is configured as resource-server (and not as client).
Also make sure that you do not use the deprecated Keycloak adapters for spring.

How to perform oauth with Nextjs and external REST API

I am making an application with Nextjs and Nestjs for API. I want to support server-side rendering for certain pages with Nextjs. The authentication and user registrations need to be done on Nestjs. For now I am trying to do google oauth.
For requests from client side to API, I will have to send some access token along with the request to authorize the user. And for server-side authorization, I'll have to get this access token from the cookies and then send it in the request to the API. From what I have seen, access tokens last only 1 hour. So how can I do it in a way that lasts longer than 1 hour?

Passport Authentication works through Postman but not Web App

Using Express and Passport JS on the backend we are currently able to login to the application, and access all of the API requests using postman.
However when we try and make API requests that require authentication on the React JS Web Application we get a 401 unauthorised error.
We've run logs from both the postman request and the web app request and both are passing the connect.sid cookie in the header.
My question is, how do I get the application authenticated and able to make API requests like postman can. I login to postman the same way I do using the web application but it doesn't authenticate the api requests.
Things I've tried:
manually setting the headers to allow cross origin requests
setting an Authorize bearer token
Specifying on the backend the origin of the front end, which only allows api calls to be made from the front end web server
The application is a ReactJS application, and I am making the API calls using Axios
I fixed this by passing withCredentials on login, this sends your user to the passport.js and authenticates the user.
You need to call withCredentials every time you make an API call though

User's context on isomorphic (or universal) react app with JWT

I'm actualy developing a react-based front-end application and I would like to switch on isomorphic features.
The user can be authenticated, I currently use JWT to store the client connection on localstorage.
Now, my problem is that the first page of the app can be different on the case the user is connected or not.
Actually, the page is loaded, and xhr requests are sent with the token in the header, so the response of the server depend of the token.
BUT, if I switch to isomorphic rendering, the token will not be included in the request, so the server will return a response as if the user is disconnected.
Here is a scheme to explain how it actually works :
First the browser load the javascript from the node.js server. If a user token already exists, the browser send the requests to the backend with this token. So the response depends on the user's permissions.
Now, a scheme for isomorphic js :
The page is generated by node.js. So the requests are sent by node.js to the backend, and so node.js has no access to the token stored in the browser.
I would like to know if there is any approach to solve this problem.
Thank you.
You can store the JWT in a cookie, rather than in localStorage. This way, your server-side app can access the JWT as well and use it to make your authenticated calls.
The mechanics of how you use the JWTs doesn't change, just where you store them. A library like js-cookie makes managing cookies easy.
Cookies.set('jwt', jwt, { secure: true });
The catch is that you now need to be careful of CSRF. API calls triggered from another site to your domain will include the cookies if the user has any. Creating unique CSRF tokens on the page lets you prevent this.
Stormpath has a good write-up of storing in cookies vs localStorage.

Can JWT be used across different AngularJS Apps?

I have a Laravel 5.1 API that is connected to an AngularJS Frontend.
Can I do this..
Have one (hosted on mydomain/public) AngularJS App with the sole purpose of authenticating the user and getting a JWT token from the Laravel API Backend
Somehow passing this same Token to a second (hosted on mydomain/secure) AngularJS in order to authenticate the user and the access the App.
I know the token is saved on the local storage so I don't see a reason why I can not or would I have to merge the two apps together.
Cheers,
Yeah. They are not related to the number of Ng-App or instances of Angular apps you define.
How JSON Web Tokens Work ??
A browser or mobile client makes a request to the authentication server containing user login information. The authentication server generates a new JWT access token and returns it to the client. On every request to a restricted resource, the client sends the access token in the query string or Authorization header. The server then validates the token and, if it’s valid, returns the secure resource to the client.
So server logic is not dependent on if your front end is single page or multi page.
You can read this post for more clarity:
http://www.toptal.com/web/cookie-free-authentication-with-json-web-tokens-an-example-in-laravel-and-angularjs

Resources