I'm writing an auth module that contains several functions so my server can authenticate with an oAuth2 system using client_credentials. In the module I want to cache / save the credentials since they don't expire for some time (I'll refresh as needed).
Whats the best way to store the credentials?
Should I just create a var at the top of my node module? Should I create a class and instantiate it (const auth = new MyClass()) where my makes subsequent API calls (with the Bearer token)?
Creating a var variable means to store data in RAM, which is not a comprehensive approach.
I suggest you look at Redis, which was developed mostly for your purposes.
Redis is used as a database and for cache, since it’s super fast because the data is stored “in-memory” contrary to other databases in which the data is usually stored “on-disk.”
Moreover, there some thoughts about the fact that Node.js is less efficient at storing data than Redis. This article will clear more about my point.
So, in general, I guess using Redis will bring you more advantages in storing credentials.
Related
For authentication in my REST API, I am using JWTs, which only contain the client user's UUID.
To check if the user is not blocked or has rights to execute a specific endpoint, I fetch the user's data from a PostgreSQL database using the UUID of the JWT, and verify if the user is allowed to execute.
Is it a good practice to do a database operation for securing every API call?
Also thought about storing roles and rights in the JWTs but what if these roles and rights change in the database and the JWTs data becomes stale? Is there any solution to the stale data?
You have to check some data store for staleness with JWT.
If you conclude with performance tests and measurements that accessing a PostgreSQL DB for every request would be too slow, then you optimize that part. Maybe optimize your DB performance by changing the data structure or configuration. Or use a completely different database just for this purpose. Bad practice would be trying to optimize this prematurely.
Here's an article that talks about how to manually expire JWTs, it describes an example with using Redis:
An implementation would probably be, to store a so-called “blacklist” of all the tokens that are valid no more and have not expired yet. You can use a DB that has TTL option on documents which would be set to the amount of time left until the token is expired. Redis is a good option for this, that will allow fast in memory access to the list. Then, in a middleware of some kind that runs on every authorized request, you should check if provided token is in The Blacklist.
TL DR: No its not :-)
In general JWT's are not the most suitable solution for scenario you describe, you are already facing the first trouble of it now.
Because you better store stateless information in your JWT, otherwise you would be better of using other authentication solutions.
Conclusion
Stateless JWT tokens cannot be invalidated or updated, and will introduce either size issues or security issues depending on where you store them. Stateful JWT tokens are functionally the same as session cookies, but without the battle-tested and well-reviewed implementations or client support.
Unless you work on a Reddit-scale application, there's no reason to be using JWT tokens as a session mechanism. Just use sessions.
source: http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
And some other related posts:
http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-for-sessions-part-2-why-your-solution-doesnt-work/
https://medium.com/#yuliaoletskaya/can-jwt-be-used-for-sessions-4164d124fe23
https://logrocket.com/blog/jwt-authentication-best-practices/
Most security consultants / auditors I spoke to also are very strong in there statements about JWT, they are widely overused and have a specific problem domain.
But if you really want/need to, I would follow #ekuusela's answer, especially given:
Bad practice would be trying to optimize this prematurely.
I'm learning Node.js, and I was wondering what is the best way to handle sessions.
It occurs to me that there are two main options: express-session, or cookie-session.
I did some research, and I've found that express-session is not the best way, since it stores all session information on the server, making it less scalable, but lots of tutorials were recommending it.
So, I am a little confused.
These two options are not comparable as they don't have the same functionality.
If you just want to set up a "volatile" session, with no need to store/verify any information server side, you can use cookie based session. This is just an improvement for the user experience (remember choices, preferences...)
On the other hand, if you need to keep some record about that user (authentication, history...), you will need to use a server side session, and a database. Any client side data (like cookie) could be modified by the user.
Note that the last option is not less scalable, it depends on the storage method, MemoryStore by default in express-session package, according to the documentation.
This package is powered by express team, so I guess it is robust enough for a production usage.
I am new to Node and trying to setup Node & Passport to create JWTs upon authentication.
I am hoping to build a "stateless authentication mechanism" to reduce the need of going back and forward to the database.
By going "stateless", if none of the shared secrets or JWT is saved in the DB, I am assuming if the server restarts, all the issued JWTs (logged in users) are invalidated, thereby requiring a new JWT for all users to access protected routes. I do not want the users to log back in each time a server restarts or a new instance is spun.
I believe I can pass in static shared secret(s) to Node environment that I can use each time to generate the same JWTs that doesn't affect server restart.
Questions:
If a good practice is to pass in the shared secrets, where and how should I create this shared secret? and what all shared secret(s) will I have to pass in?
However, if passing in shared secret(s) to Node environment is not a good strategy, I am all ears for suggestions?
Update
I meant shared secrets when I said "key(s)". I'll update the question so it's not confusing.
Actually passing the keys as environment is the recommended way for this kind of applications.
Because the environment is only be visible by the running application and reduces the possibilities of leaking the keys (compared to something like a config file provided with the rest of the application code).
Normally you don't rotate the keys that often, it's usual to rotate them once a month assuming that you control your environment.
But keep in mind that the key is only used to prove that the token was signed by you, normally is good practice to only include a tiny bit of information in the token (for performance reasons). So you still need to go to the database to retrieve extra information about the user itself. You can add all the user information inside the token but keep in mind that the token needs to be sent for each request and that adds overhead.
If you use a process manager like supervisord you can set the environments over there and give the appropriate permissions to the config file to avoid key leakage.
I normally use environments to pass that kind of information to my node applications, I use it for JWT, AWS keys, SMTP credentials, etc. It keeps your code decoupled and avoids possible mistakes like pushing private keys to public code versioning system like github.
I'm thinking about creating session this way:
create a secure token with cryto.randomBytes then store it in cookie.
extract token from cookie when node receive a new connection, store it inside global variable GLOBAL.SESSION[token] = data
I'm stuck on step 2:
What happend if node is crashed? Do I need to store the SESSION in a file like PHP does?
If I do it my way, in order to call SESSION, I need to globalize the token too. However, it's name will be a little long. If I shorten session name via assigning GLOBAL.SESSION[token] = GLOBAL.SESSION, it will be overwritten when node receive another connection.
Should I follow this way? Or Any further ideas about this?
create a secure token with cryto.randomBytes then store it in cookie
Just once? You risk session fixation attacks.
extract token from cookie when node receive a new connection, store it inside global variable GLOBAL.SESSION[token] = data
It's not great practice to keep things global... but that's up to you and your application structure.
What happend if node is crashed?
When your application stops running, everything you put into memory is freed. You are responsible for managing your data, and if you want it persistent, you have to make it persistent by writing to disk, a database, etc.
Should I follow this way?
No. Don't re-invent the wheel. You will inevitably make a security mistake along the way, and you are just creating more work for yourself.
Yes, you will need to store the session data into a persistent database, which could be anything like a flat file, SQL database, or noSQL db like mongo, couchdb, etc.
If you use node.js and express, there is a really good library called connect-session:
https://github.com/expressjs/session
you can readily use instead of reinventing the wheel.
I wrote a simple webserver with nodejs and express. I implemented an user authentication with email username and password. Furthermore I have a remember-function which stores the user id and pwd hash into a cookie. Now I would like an extra session that ends when the user will close his browser or click to the logout button.
Which way is the best practice for implementation? Is the session the same like the remember-function with an expire time and in each request I must check the credentials against the database? (I'm not that sure about this)
Technologies that I'm using: nodejs, express, mongodb
This is not a nodejs question only, I would prefer a general explanation for the problem.
Let me get this out of the way first; Storing the password hash into a cookie would allow anyone to login when they have the password hash and that would be disastrous if the password hashes ever got exposed for some reason. Encrypting cookies is just fine, but don't allow the actual hash you store in the database to be used for authentication. Ever.
About re-authentication, Node is a technology that operates on a single thread and is scaled by running more instances over multiple processors and/or machines. Keeping sessions is a good idea to avoid trips to the database, but you have to think about the architecture as well. What happens if you, say, use sessions stored in files (ala PHP) and you need to scale to multiple machines? Nothing good, at least. So you need a central point to keep track of the sessions.
This can be either your database (MongoDB) or something such as Redis, or another centralized mechanism allowing you to check sessions. Either way, you will have to spend time doing the request and retrieving the session values for the client. If you do not have additional values you need to store it makes no sense to create a dedicated session architecture (that needs expiration, and so forth) and just doing the authentication again is the easiest and most logical solution.
Personally I almost never need sessions and just do authentication again.