Best way to store access tokens?

When I need to access a third party service and I got a token to access it, I usually store it in the registry. All access to the registry should be safe in a way it is either used in filesystem code or is protected by "Manage Portal". I hope this is true; at least for plone.restapi it applies.

Are there better/ more secure ways to store the tokens, i.e. encrypted, so someone who got the DB can not read them?

1 Like

You could store them on disk in an ini file or using a product-config. Or a KV store of some kind that you control, but not the site admin.

What/how is your hosting setup? That might give some hints.

1 Like

You could encrypt the fields in the registry based on a key you pass in as an environment variable on startup. But if your bad actor knows how to access the ZMI and create a python script that encryption key can also be exposed. The tokens are than at least not saved 'plain' in the content database and readable through the plone.app.registry control panel. But it's symmetric encryption.

The problem space is that of services like Hashicorp's Vault and other similar tools to request/pass/manage secrets at runtime....

1 Like

The key problem with any kind of encryption in such a context is that the keyholder is at some point needed for entering or providing the secret e.g. in case of reboot or so.

1 Like

The solution should be hosting-agnostic.

My idea is to use AES-256 to encrypt and decrypt the token. The password is provided by an environment variable (os.environ at least can not be imported from RestrictedPython code, so not TTW).

Any objections?

Why not just provide the token as environment variable? Maybe I miss something...

Yes, it about tokens a user fetches, this can be many and per user.

Yes, it about tokens a user fetches, this can be many and per user.

This would not be a problem, as you could namespace the variables as in USERNAME.SERVICE.TOKENVALUE.

The key point is probably whether you need to persist the tokens or not.

I need to store them. And plone.keyring is AFAICT not an option, because it rotates and at some point the secret is vanished, so the token is timed out. Ok, tokens usually are in need of a refresh anyway, but I am not sure how to sync this with plone.keyring rotations. I may need to dig here a bit.

1 Like

I had this discussion a few years ago and got some really good suggestions back from plonesec / @mauritsvanrees

One idea that was thrown out was to use Cloud Key Management  |  Google Cloud to manage the key for two-way encryption of keys stored in the registry, or any DX/AT field for that matter.

The simpler, but much less secure solution was to base64 all data related to the plugin into a single, obfuscated registry key, but that's certainly not going to satisfy any compliance rules.

I ended up with a vision of a plugin that creates a new 'encrypted' field for DX that can be used in DX schemas. This also provides a control panel plugin to use a cloud-based key manager so the key(s) are stored on a separate platform than plone.

If plone is compromized, the fields are useless without the key on the cloud.
If the key is compromised, it can be rotated using the cloud provider.
If the cloud provider is compromised, you could configure the plugin on the control panel to use a new one. (assuming it's using a standardized key exchange format like OAuth or JWT)

Another wise quote from the conversation: "You'll still likely use vault to deploy with some db config/secret as env variable."

Just some ideas that came from a previous brain-storming session on this.