JWT with Node & Passport: Restarting server - node.js

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.

Related

is electron's `safeStorage` for passwords and login credentials?

I need to store login credentials with electron js because it doesnt save them like all browsers. I have seen a lot of questions like this, but I never found a solution. I have seen in the electron docs about the safeStorage feature. is the it safe enough/good enough to store login credentials on the client side? if not what other tools are available to do that? I have heard about keytar but is it good?
The safeStorage api in electron exposes OS-level encryption/decryption using current user's secret key - please refer to electron source and chromium's os_crypt. On windows it utilizes DPAPI while on *nixes it uses whatever password manager the OS has as the documentation suggested.
is the it safe enough/good enough to store login credentials on the client side?
Depends, you should define "secure" first.
Ask yourself, should the same user allowed to read whatever value inside the encrypted text? A tech-literate person might write his own tools to decrypt things you store using that API you are out of luck. See this QA for further discussion.
if not what other tools are available to do that?
There are a lot of tools (and encryption algorithm) to encrypt stuff in nodejs. However, you have to remember an encryption require you to have a key of some sort and the key need to be protected too. Hence, try your best to avoid egg-chicken problem with your key of keys.
OS-based key storage avoids the key of keys problem by storing the "master key" in a way that only accessible using its API. At runtime, you can't retrieve the key at all, you just send a set of bytes for the OS to magically encrypt/decrypt. While at rest, the OS may rely on secure storage such as TPM (Trusted Platform Module).
is electron's safeStorage for passwords and login credentials?
Depends, if you are running a web service it is preferrable to not doing so. You should never dump end user's user name/password directly on a storage that you can't guarantee its safety by yourself (e.g. your server). You should, put an identifier which can be revoked or may expire at later date - token or cookies.
Imagine the trouble when your end user device get stolen. If it's a token/cookie, they can request you to revoke their access from that device - similar to "Log me out from all other device."
However, if its an in-situ application that authenticates to itself then its a fair game - though keep in mind about the first point. Its all down to your security model.

How to use localStorage Carefully in Angular

Since localStorage data can be changed easily, how can we make access controls and more things secure in the Angular App.
Suppose our localstorage contains:
data - {name:user, account_status:inactive,...}
The user can easily change the account_status from inactive to active and get all access.
I am not just concerned about access control but also the other localstorage data which is used in angular.
Can I encrypt the data from the node server and store it in localstorage and decrypt it back when i want to use with the same secret key. Will this have some adverse effects.
Please suggest some methods which can be used.
You can create a common service for localstorage operation which will perform the encryption when storing data in localstorage and decryption when getting data from localstorage. You should encrypt key and value both so it is not easy to change the value in localstorage. You can use CryptoJS for encryption.
That's execalty what happened back in the time with Spotify. The result ? With a little script, you could have spotify premium for free.
My point is, that you should not store sensitive data in the client side, and if you do so and use it, there should be a doucble checking (one from the client, one from the server) : if the user changes the values of the client, the server will check the validity of the requests anyway, and refuse resources to the user.
To finish, my point is that you don't need to encrypt your data, or to stop using local storage : just be clever and double-check the user permissions.
The type data you are trying to store should never to stored on local-storage, especially for a serious production app. Data should always be hashed/encrypted on the server and then sent to the front end for further manipulation.

Generating and using a secret in a config file for JWT

I have a question regarding secrets for JWT.
I understand the "best practice" is storing the secret in an environment variable, but what about this setup?
I am generating my secret using a library called secrets.
I am storing my secret in a config file, and the relevant line looks like this
jwtSecret: process.env.JWT_SECRET || secret,
where secret = new Secret(32, true, true).generate();
Now, the way I understand this is that with this setup, my secret will be regenerated every time the server starts, essentially invalidating all previous tokens. Is this a sound setup? Is there any way that this setup will cause unnecessary grievances for my users beyond requiring them to re-authenticate? What about for me? What headaches might I face using a setup like this? I should point out that this application will likely only ever be running on one server at a time, so sharing that secret amongst multiple nodes is not a problem in my situation.
Oh and if it turns out that this is a wildly bad idea, please make it plainly evident by responding in all caps (I'm only joking, but please do make it evident).
As far as I know, you don't need (and should not) to generate secrets every time you start your server. You can just add one to your environment and that's enough.
But If you want badly to generate a secret instead of coming up with one, you can write a separate script that can be called on demand, and only by an admin behind authentication.
//maybe some authentication code here
process.env.secret = new Secret(32, true, true).generate();

General user session handling (Nodejs)

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.

How to verify an application is the application it says it is?

Here's the situation: we have a common library which can retrieve database connection details from a central configuration store that we have setup. Each application uses this library when working with a database.
Basically, it will call a stored procedure and say "I am {xyz} application, I need to connect o " and it will return the connection details for that applications primary database (server, instance, database, user, and password).
How would one go about locking that down so that only application {xyz} can retrieve the passwords for {xyz} databases (there is a list of database details for each application... i just need to secure the passwords)?
The usual way is to have a different config store per app and give each app a different user/password to connect to the config store.
That doesn't prevent anyone from changing the app and replacing the user/password for app X with the values from app Y but it's a bit more secure, especially when you compile this data in instead of supplying it via a config file.
If you want to be really secure, you must first create a secure connection to the store (so you need a DB drivers that supports this). This connection must be created using a secure key that is unique per application and which can be verified (so no one can just copy them around). You will need to secure the executable with hashes (the app will calculate its own hash somehow and send that to the server who will have a list of valid hashes for each app).
All in all, it's not something trivial which you can just turn on with an obscure option. You will need to learn a lot about security and secure data exchange, first. You'll need a way to safely install your app in an insecure place, verify its integrity, protect the code against debuggers that can be attached at runtime and against it running in the virtual machine, etc.
Off the top of my head, try PKI.
Are you trying to protected yourself from malicous programs, and is this a central database that these applications are connecting to? If so you should probably consider a middle layer between your database and application.
I'm not sure this applies to your case, depending on how what your answers to the abovementioned would be, but by the comments it sounds like you are having a similar case to what this question is about.
Securing your Data Layer in a C# Application
The simplest/most straightforward way would be to store the passwords in encrypted format (storing passwords in plaintext is just plain bad anyhow, as recently demonstrated over at PerlMonks) and make each application responsible for doing its own password encryption/decryption. It would then not matter whether an app retrieved another app's passwords, as it would still be unable to decrypt them.
One possibility is to keep the passwords in the database in an encrypted form, and convey the encryption key to the allowed application(s) in a secure connection.Then, only the application with the encryption key can actually get the passwords and not others.

Resources