Given scenario:
I have an application (NodeJS) running on Heroku, the database is RDS on Amazon and I use Auth0 for authentication. I don't have access to passwords of the users, some users use social media logins.

The problem:
The application has to store API keys from third-party platforms provided by the user and of course I want to prevent at all costs that anyone will ever have access to these data (with the keys, transactions ($) could be executed directly on other platforms!).

How do I encrypt the data when I don't have access to the user's password at any time?

The cases to secure I can think of:

  • Someone has access to my Heroku Account
  • Someone has access to my Auth0 Admin Account
  • Someone steals my database (e.g. by having access to the Heroku environment variable)

Can I securely save and access (while the user is logged in) the users API keys with my database?

It is okay for me, or even good, if I don't have access to the encrypted keys anytime. But I need them stored on my side in a persistent way. Its okay for me if the access is only possible when the user has an active session (by that I am giving up the possibility to perform any background tasks, but I do want to put security first and accept the negative impact on UX). I don't want to add another password for the API keys per user.

The solution can be on my end or using Auth0 or something like AWS Key Management Service, I have already done research but to me, it is still too blurry to say anything specific.


Protecting from someone getting the database contents is easy: Use a key (password) know to your application to encrypt the db records (a single key common to all users). That way, if someone stole just the db, the encrypted values would be without the key that is stored locally in the app node.

If the user would always be using the same browser, I would recommend to simply store the per-user "password" in a cookie¹ However, you may not be able to rely on that, and with such setup a user on a new browser would need to authenticate again producing new API keys (you will define if that's considered acceptable or not).

If the only thing you know is the identity, I think that you have no other course than using that for the encryption. I'm not familiar with the way Auth0 works, but it must be giving you some kind of user identifier (eg. an internal id or an email address) that is validated.

In that case you could eg. search the relevant database entry by looking for a record with the primary key being HMAC("foo", ), and decrypt the parameters with HMAC("bar", ), "foo" and "bar" being different secrets kept by your Heroku application.

Thus, only when knowing a user-id can the record be found and the secrets decrypted. This is not specially secure if someone got hold of both the database and the App², could try different identities, as emails are generally public (eg. I would begin by trying your email address). But still that requires testing users that could be there (from email lists gained from elsewhere, bruteforcing possible emails...).

¹ actually, localStorage / indexedDB would probably fit better.

² only one of them would not allow them to access any contents

| improve this answer | |
  • One must assume an attacker will gain admin access, that is why it is not secure to encrypt passwords in a DB. – zaph Dec 28 '18 at 16:04

You could ask the user for a 'x' digit 'pin' (for simplicity) or for another password and use this for encryption of the sensible data each session... You can also append the pin provided by the user to a general password to encrypt the data... For example, user sends '5555' as his pin... This gets appended to 'kH56ek7r91jfql' giving as a result '5555kH56ek7r91jfql' hackers migth have acces to the database and the second string of the crypt pwd but they need the users pin to decrypt it... Dont use Id or username because this can be easily reversed

Edit: Dont save the users pin just use it to dcrypt the api keys and hold them in memory while session is active

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.