Store external API token with Node - node.js

I'm building a small app with Node (server) and React (front). I make API calls to an external application and the token has to be refreshed often. For now, I've tried two options but they are not optimal :
First I get the Token on React parent component, save it in local storage then pass it to to the child component which will pass it to the server which will handle the call. The problem is that the asynchronous nature of React creates some problems.
Each time I call the API, I generate a new token. The problem is that I could have a lot of API calls.
What would you recommend me?
Thanks

You need a layer in the API to make sure that you don't request a new token until it expires or you don't have the token and ofcourse you need to make an API call only when you don't have token in local storage.
So, there are two places you need to write a logic to make sure if you need token or its already there.
Client-side: before making the API call check if token exist for the user. If it is not present, request the token from Node.js API.
Backend: You need to keep the token in DB or cache(in-memory db) with the client id or any unique id. Saving in DB can be good option even if your server restarted you have track of all the active tokens.
Before making the request to the external API check if you already have a token with you.
The problem might be you are missing one of these steps or both and thats why you are getting new token everytime.

Related

Login functionality from external API in React with Node.js

I’m having trouble figuring out how to get Node.js backend tokens into React.js frontend local storage. To login a user will use their credentials though an external websites API using the Oauth2 flow, this will be the only way to login into the application.
Currently, the user clicks a button which opens a new window in the authorization URL where the user will grant privilege. Once granted, the user is redirected to the backend endpoint which goes through passport.js and gets the required access and refresh tokens sent from the external API. This is then stored in a session on the backend database. What I want, instead, is to not store a session on a database but instead implement JWT and store the user’s data in local storage. With the current flow, its just not possible to do this and I haven’t found the right documentation to work it out.
There are many websites that implement it the exact way I want but tracking down the way they do it has appeared to be a challenge in on itself.
So instead of using passport.js, which was causing a plethora of issues, I decided to implement the Oauth2 flow myself. Instead of doing ALL the work in the backend, I broke the flow into different parts.
Originally, I sent the user to the backend where they would recieve an authorization token there. This turned out to be troublesome, instead, request an authorization code on the front end. For example, send the user to the Auth path and redirect the user back the the front end once privileges have been granted. Wait at the frontend callback for a code, once obtained, send a post request to the backend with that code and any other data in the body.
When obtained at the backend, trade that code for the access token and respond to the post requst with the neccassary token and any other data that needs to be sent back e.g. profile name, picture, date of birth. You can the implementn the JWT flow and no database is required to store any session or tokens, all can be stored client side securely.

Express backend with Firebase auth and my own database to persist users

I'm creating a system where the client in React will implement Firebase authentication, so Firebase will signIn users, but I have a backend server with Express and I need those users in my own DB (postgresql). I can use firebase-admin in the backend to verify the token sent from the client on each request, and from this token, extract user data, as well as its uid. So I could create a user in my own database with these information.
The problem is that since I'm not handling user signup in my own server, I would have to add a verification in the authentication middleware. Each time the user makes a request to the server, the backend verifies the token (with firebase-admin) and checks if the user already exists in my own database, because if it doensn't, then create this user.
I wanted to see if there is another way to handle this, since every request is not only going to verify a token but also query the database looking for the user.
Verifying the ID token in the backend code is pretty much how all Firebase backend services handle it too. They receive the ID token, request the public key from the project, decode the token, and then validate that the user is authorized for the action they're performing.
You seem to want to create a record for the user in some shared database however, which I'd typically recommend against as it affects scalability. The only thing most Firebase backend services cache is the project keys (as those require an expensive HTTP lookup) and recent encoded/decoded token pairs. But there are caches on each server separately, so it's quite different from having shared state in a database as you seem to want.

Accessing the token on the front end

I am building a web app with nodejs. I am using express-jwt for authorization. Since I am relatively new in the web development field, I decided not to use frameworks for the front-end. I am building the frond-end using ejs templating.
How do I hook onto the token that is generated when the user logs in ?. I have been doing tests on Postman and everything works.
Any assistance or leads will be appreciated :)
Suleiman
Its very simple to deal with jwt tokens, you just need basic javascript in the frontend.Whenever the user logs in store the jwt token(that you will get from server) in the local storage of the browser.
localStorage.setItem('jwt', token);
Whenever you need the token for requesting a resource just fetch the token from the local storage and provide it to the backend server with the http request.
var myData = localStorage.getItem('jwt');
If the token gets expired you will receive authentication error from the server(need to program like that) remove the jwt token from the local storage and log out the user.
localStorage.clear();
At any point of time, you can access the token from the local storage to make a backend call. Similarly you can also store other information in the same fashion which would be helpful (like basic details of the user)
You should also see this article about why storing tokens in local storage is not such a good idea. It contains some other suggestions on how to manage tokens on the client side.

How to let frontend know your server has successfully retrieved an access token

I've been studying the OAuth 2.0 authorization code flow and am trying to write a React application with an Express backend that displays what a user would see on their own Instagram profile. I'm trying to do so with minimal external libraries (i.e. not using passport-js) and without bringing a database into the mix.
This is my flow as of now:
Resource owner clicks an <a> tag on the React application (port 3000) which redirects them to the /auth/instagram endpoint of my Express server (port 8000)
res.redirect(AUTHORIZATON_URL) sends them to Instagram's authorization server
Resource owner consents and the authorization code is sent back to the predefined redirect-url /auth/instagram/callback with the authorization code set as a query parameter
I strip the authorization code off the url and make a POST request to https://api.instagram.com/oauth/access_token to grab the access token
Now that I have the access token, how do I reach out to the React frontend to let them know that everything worked and that the user was successfully authenticated?
From what I've read, this is where the idea of sessions and cookies come into play, but I haven't had luck finding documentation on how to achieve what I want without bringing in third party libraries.
In the end, I would like for my app to support multiple users viewing their profiles simultaneously. Since I imagine passing the access token to the frontend defeats the purpose of securely retrieving it on the backend, I'm guessing I will somehow need to pass a session id between the frontend and backend that is somehow linked to an access token.
Any ideas as to what my next steps should be are greatly appreciated, as well as any articles or documentation you see fit. Thanks!
Since you're doing the OAuth authentication on the server side, you have to pass some parameter to the redirect_uri, identifying the user session (see: Adding a query parameter to the Instagram auth redirect_uri doesn't work? );
When the redirect uri is called from the authority server, you will know which user was authorized. To notify the browser there are two options: 1) Notify the client using web sockets; 2) Pull the state from the client using a timer triggered function;

What are the recommended strategies for authorising API calls from my react native application to my node server?

I have a react native application that I want to make API calls from. I am getting confused about how I should be authorising these calls on the node back end.
Method 1:
User logs in to application and authenticates, I then return a JWT with refresh token. This is then stored client side / in react native app and is sent upon each request. If token expires, then refresh using refresh token.
Method 2:
Create API key for each client. When a user creates an account, I create an API key (or maybe access key and secret key like AWS does) and send that with each request.
Is there a preferred / recommend method out of these two? Perhaps they are not mutually exclusive? Do I still need to provide an API key to my react native app so that it can make API calls and then I use JWT for authenticating users?
In my personal opinion,
You may go for the Method 1, since it is not secure to store / create API keys or Secret keys on the client side.
JWT are more secure, you may read the following article
In the Method 2, you will most probably try this approach
Generate Api key based on client IP or the device token, whatever suits you, and set an expiration time including the AES techniques, then decrypt it on the server, check the client's IP against the requestor IP and also the expiration time.
Complexity and time taken to do Method 2 is much more that Method 1, also considering I might have not covered all the security use cases.
Do I still need to provide an API key to my react native app so that it can make API calls and then I use JWT for authenticating users
You can make the http calls normally. The recommended way is call your token generation api and then authenticate other valuable api's based on that token if you're using JWT
Hope it helps.

Resources