User session between Express+Nodejs and clients using Firebase - node.js

what's a common approach of storing user sessions with Nodejs+Express and Firebase auth? I have Android and Ios app that I'd like to use the same logic on (later web as well), so I'd get the JWT token. I'd like to use that token as authorization for requests. Also I'd like to keep the user sessio and not require them to relogin again. I am not sure how to go about this, all of the Express Session resources I've found were on topic of web and cookies. I've stumbled upon MongoConnection a library for Express that presumably stores the sessions in the MongoDb, but how does the session work with non-web requests? Can anyone help me clarify this, I am aware that I am missing the point here as there is certainly an easy way to verify incoming requests and also have a session for the user to not have to login everytime.
Preferably I'd like to have an easy way to have endpoints that require JWT token access. Besides that also have a session of sorts. There is a function to verify tokens in the Firebase Admin SDK for Nodejs but it seems really weird to have to check the token manually in every request.

I treat sessions on the backend and front end entirely separately as I predominantly make RESTful apis. On the front end you can handle sessions however you like, e.g. you can start a session when a user authenticates with firebase auth, and set the user role maybe based of attributes on the firebase auth user. Use cookies, do whatever you prefer.
Then on the backend, on every endpoint just decode the token, verify it, check that the user has access to the resource they are requesting etc. Its common to write your own middlewares so that you dont have to repeat the decoding code. For further info on this approach, this might help. Its not weird to check the token manually on every request, its common practice to guarantee the authenticity of the request. Hope this is of some help.
To sum up, treat your front end session entirely separately from the backend. On your express server on the backend, on any protected endpoint decode and verify the token to determine if the user has access to the resource.
Backend sessions with firebase are a bad idea (due to it been serverless), its better to create a stateless restful api.

Related

How to handle refresh token on react spa?

I have two servers. One for Hasura GraphQL api which queries the db and provides app data. Another is a node server for authentication. These two servers are not on the same domain.
I have a react spa client. When a user logs in, the node server validates the credentials with the hasura graphql endpoint and provides a jwt token and refresh token to the client. The refresh token is sent via httpOnly cookie as the react client and node server are on the same domain.
Now when the jwt token expires, I want to silently refresh the jwt token using the refresh token which is sent automatically as a cookie to the node server. How would I implement this?
One way that I can think of is, on the client side I decode the jwt and if it's expired I send a request to the refresh token endpoint on the node server and get a new jwt token before sending any request to the hasura graphql server which needs the access token sent as an authorization header. This means I would have to do this check before every graphql request. Is this the optimized way or are there any other way to silently refresh the token given my application architecture?
Let's use deduction. Obviously, you can either check the expiration time at the client-side or let Hasura do that for you (and return an error whenever the token's expired).
If you check it on the client side, you will lose some milliseconds before each call to Hasura but will save a single Hasura round-trip whenever you detect an expired token. I would take a base64 decode of a JWT payload over an HTTP call anytime, so IMO there is no a better way to handle JWT auto-refresh, if that's your only concern.
OT but IMHO JWT is not an excellent solution when it comes to things like expiration, blacklisting, etc.. E.g.:
what if at some point you decide that you need to check if the account is suspended? You'd then have to start making calls to your auth server before each call to Hasura;
even if you deal with that, what if you decide to perform (for whatever reason) an auto-login on app-load? Or an auto-refresh at an interval? It's easy to do that with a single tab, but things will go south pretty quick once your user has two or more tabs of your application open at the same time.
I suspect that in many such cases people end up implementing sort-of sessions, only without cookies, which is a bit like reinventing the wheel.
May I suggest looking into Hasura's webhook auth system instead, if you find yourself going down a similar path in the near future - it might just be the optimal choice.
BTW, such questions might be better suited for the Software Engineering SE.
This blog explains JWT and use cases around it very succinctly, https://hasura.io/blog/best-practices-of-using-jwt-with-graphql/
It covers use cases of silent refresh and how to design auth server.

Authentication strategy between 2 node.js microservices

I am planing to make a simple admin CP. Im oldschool PHP developer where usually all is in one huge monolith server and concept of microservices does not apply.
In my next app I would like to have:
Express UI (Frontend) <----> REST/GraphQL API <-----> DB server
The idea is to limit access to DB as much as possible. All requests from users would go to frontend only and API would be used only internally by other servers in my solution.
I will set up IP filters between API and DB, and likely between Frontend and API. But my concern is - say I want one admin to create a product. While this user will be authenticated on frontend using sessions, I need requests going to API to be somewhat authenticated too. Ignoring IP filters for now, do not want just about anybody to be able to send REST requests to API.
I have several ideas, please give me your opinion:
sharing express-session between API and frontend using mongodb (likely on yet another server) - I see latency issues
putting API service on same server as frontend and use redis to share sessions - kinda defeats the purpose of microservice separation
on login, generating jsonwebtoken that is always fwded between frontend and API for any user action - cookie stealing will be an issue, since i can only verify user logged in, not that he authorized certain action to be performed
on login, sending private key to admin and have him sign all requests that are fwded to API - this looks like a CPU overkill
Is there any generally used solution I am missing? Is separating frontend and API mitm overkill, or a good practice? I could easily merge the 2 and talk to DB directly from frontend, then i can manage everything with sessions just like with PHP.
Thanks for any inputs! Cheers
A more elaborate implementation of (1) is the use of a session server. The idea is to purely remove database lookup latency but not the bottleneck of session lookup in general. It acts as a caching layer. A zero coding implementation is to use something like redis or memcache as the session storage.
In general though, a cryptographic signing mechanism like JWT would be much more scalable because it involves zero I/O lookup. All you do is verify that the token is properly signed. And as long as you keep your application secret safe you're secure. You can even encode things like user roles and permissions directly in the token to completely avoid querying the database for it.
The key idea of JWT is that all the security is hidden in the backend. The front-end only echos back the token to the server as proof of authentication.
But since the front-end stores the token, it can be hijacked by javascript. One solution is to use HttpOnly cookies as the mechanism to transmit the tokens. I've even seen implementations where the main part of the token is sent in the Authorization header but the signature is sent in a HttpOnly cookie. This prevents scripts from being able to read the entire token.

Node.js, AWS Cognito - Login on front end, user verification in back end

I have an application who consist of a frontend Angular and backend Node.js. I'm using AWS Cognito to authenticate on the frontend, however, I need to know if the user is authenticated in my Node.js backend to allow some routes.
Right now I have two solutions in mind:
Send the JWT Token from the front to the back at each route call to see if the user is properly logged in. But I don't know how it's going to affect my backend performances nor if it's a good practice, and if there's a secure way to do this
In Node.js (I am also using express), check from which web server the route is called from. If it's from my domain, it's mean I can allow the route
What should be the way to deal with this issue?
Send either the Cognito id or access token along with each request and decode it yourself. The tokens are signed. AWS provides a mechanism for you to download the signing keys for your user pool. You would have the overhead of running RSA to verify the tokens, but the cost should be negligible.
There are a bunch of resources on how to decode the tokens yourself:
https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html
https://github.com/awslabs/aws-support-tools/tree/master/Cognito/decode-verify-jwt

In HTTP Basic Authentication, why is it better to store a token?

I have a rich JS app in React running on HTTPS, and server-side I have an api in NodeJS listening for client requests. The users are not developers ; actually they barely use a computer. I want a simple login/password form (something they are familiar with) for them to authenticate.
Instead of storing the username/password client-side and include them in every api request, it is suggested to store a token. If I understand correctly, server-side in DB, this token is also stored alongside the username/password in the table of users.
What confuses me, is that this token would not be hashed (e.g. with bcrypt) like the password would. So isn't it like having a clear password in the database?
Well for sure I missed something important about tokens.
Then if anyone could lead me the path on how best to manage http basic authentication with a token in NodeJS, it would be really appreciated:)

ReST API: Should I associate the access token with a user in my database

I am building a secure ReST API on a nodeJS server so that my Android application can access the data on my site. Based on reading some other posts, I've come to understand that I should use an access token. So my idea is to do the following:
1) When the user logs in on the Android app, the app sends a request to /api/login on my site, providing the username and password (this of course needs to happen over SSL to guard against eavesdropping).
2) My server validates that the username + password match, and, if so, responds with an access token.
3) The app uses this access token to make all subsequent requests to my API.
My question is should I store the access token in the database on my server? Specifically, should I store the fact that the access token is associated with that particular user? Most tutorials I looked at did not do this, but if I don't, then what is to stop a user with this access token modifying or viewing the data of another user? Don't I need to pair an access token with a user in my database?
try using this library, i did the same type of project and this life saver was my solution.
If you need to build a secure API the things are little more complicated. You need to sign the access token with a private keystore.
Would it be a option to use a authentication service like Auth0? They are generating a JWT token for you and you only need to validate this token. The API is completely stateless. You can find a lib for almost any programming language on their website.
What you want to do is exactly HTTP Sessions do.
So, I think you can just use HTTP Session functionality It's already implemented in WAS frameworks like Django, Spring etc. If NodeJS provide session functionality, Just use session functionality in the framework. If not, look up the HTTP Session library. Maybe you can find many library that treat session implementation.

Resources