How should I store access tokens generated by another application using Google Cloud KMS?
Asked Answered
H

3

6

I am building a Node.js application that receives a long term access token from another application that I need to access. I don't want to store these access tokens directly in the database since anyone who has access to these tokens can basically do whatever they want with it it.

I am new to Cloud KMS and such systems in general but spent the last few hours learning it. It seems like the ideal solution to solve my problem but I'm not entirely sure what strategy I should follow to store these access tokens:

  1. Should I store an encryption key in Cloud KMS and use that encryption key with an NPM package like this one to store access tokens in my database?
  2. Should I store the access tokens in KMS directly? My assumption is that I would have a key store and keys rotated every 14 days. Whenever I receive an access token, I simply encrypt it and store it at KMS. I only store the ciphertext in my database. When I need to access the access token from KMS, I use the ciphertext to decrypt it.

Which of the above is the right way to use KMS? If it's option 2, I have additional questions:

  • Can I encrypt a large number of access tokens with a single key or do I need to create a new key for every access token?
  • If I ever need to modify the access token encrypted at KMS, can I simply modify it or do I need to destroy the old version and encrypt again?

Thanks for your help!

Houdini answered 14/2, 2018 at 11:56 Comment(0)
B
4

I think your best option is to use the Node.js API provided by Google to encrypt the tokens and store the resulting ciphertext in your database.

When the application receives a token from the other application it encrypts it with the API and compares to what it has in the database to see if it's valid, this way the plain text token is only known by the owner.

Can I encrypt a large number of access tokens with a single key or do I need to create a new key for every access token?

You can encrypt as many tokens as you want with the same key. Creating a key for each token would become unmanageable pretty soon, and unless they key itself it's compromised (which is hard to imagine being stored only at Google) there is no significant risk.

If I ever need to modify the access token encrypted at KMS, can I simply modify it or do I need to destroy the old version and encrypt again?

KMS is not storing your data, either encrypted or in plain text, it's just storing the KEY you need to either encrypt or unencrypt your data.

Following the method of storing only the encrypted version of the tokens, when you need to modify one token, it should go like this:

  • Client sends you the token that needs to be revoked.
  • Your application encrypts it and compares it with the tokens stored in the DB
  • The new token is generated (by your client application I understand?)
  • It's sent to your application, which encrypts it
  • The old version of the token is substituted with the new version
  • The client now can use the new token as it has the same validity as the previous. If it tries to use the old token, as it's not in the DB anymore it won't work.

Regarding key rotation, when it happens the new tokens will be encrypted with the new keys. The old tokens will still be unencryptable because your old keys are still on KMS, just not being used for encrypting anymore. However, if you destroy the key they were encrypted with, then they will be unrecoverable.

Baxter answered 14/2, 2018 at 15:8 Comment(0)
M
3

As of December 2019, the preferred way to store and manage secrets on Google Cloud is Secret Manager:

$ echo -n "my-access-token" | gcloud beta secrets create "access-token" \
  --data-file=- \
  --replication-policy "automatic"

You can then access secrets from your applications. Here is an example with Node:

function getSecret() {
  const [version] = await client.accessSecretVersion({
    name:"projects/<YOUR-PROJECT-ID>/secrets/access-token/versions/1",
  });

  const auth = version.payload.data.toString('utf-8');

  // auth is "my-access-token"
  return auth
}

Any services that need to access the secret need roles/secretmanager.secretAccessor permissions on the secret.

Marlyn answered 22/12, 2019 at 17:22 Comment(0)
P
1

Your option 2 is fine, as long as the access tokens are small enough to encrypt with the API (a few thousand bytes or smaller). You can encrypt as many tokens as you need with the same key without impairing security.

14 day key rotation seems more frequent than necessary unless you have a specific need for it.

I don't understand your modification question. If you modify the access token and wish to save the modified version, you should probably encrypt it with your key then save the encrypted data.

Parasynthesis answered 14/2, 2018 at 11:57 Comment(2)
Thanks for the response. The access tokens are <100b so I guess that's Ok. As for my question on modification, what I meant was that the access tokens I am receiving have a long term validity but the access token itself can change (that's just how the app works). When a new access token is generated, it has the same validity as the access token before it but I can no longer use the previous access token. As a result, I need to update the original access token that I had stored in KMS. Is this doable / recommended?Houdini
Yes, if you need to save the updated access token, you should encrypt it and repose it in your storage.Parasynthesis

© 2022 - 2024 — McMap. All rights reserved.