Hash API keys#3842
Merged
Merged
Conversation
01ad6ca to
05df12a
Compare
cb47a2f to
fd5a17e
Compare
05df12a to
5f94f9b
Compare
stchris
approved these changes
Oct 16, 2024
Contributor
stchris
left a comment
There was a problem hiding this comment.
Nice and straightforward, left a minor comment but this looks good to go!
| for index, partition in enumerate(results.partitions()): | ||
| for role in partition: | ||
| role.api_key_digest = hash_api_key(role.api_key) | ||
| role.api_key = None |
Contributor
There was a problem hiding this comment.
Minior nitpick, but I think
Suggested change
| role.api_key = None | |
| del role.api_key |
would make sure that key is no longer in memory (as soon as the garbage collector runs)
cc19c2b to
1cb1e20
Compare
7bd4b1e to
50b689e
Compare
5f94f9b to
74c8627
Compare
Aleph used to store user API keys as plaintext in the database. This commit changes that to store only a hash of the API key. API keys are generated using the built-in `secrets.token_urlsafe` method which returns a random 256 bit token. In contrast to passwords, API keys are not provided by users, have a high entropy, and need to be validated on every request. It seems to be generally accepted that, given 256 bit tokens, salting or using an expensive key derivation functions isn't necessary. For this reason, we’re storing an unsalted SHA-256 hash of the API key which also makes it easy to look up and verify a given API key. I've added a separate column for the hashed API key rather than reusing the existing column. This allows us to batch-hash all existing plaintext keys without having to differentiate between keys that have already been hashed and those that haven't. Once all existing plaintext API keys have been hashed, the old `api_key` column can simply be dropped.
Required as we do not store plaintext API keys anymore. Also, we want to remove the option to pass API keys via URL parameters in the future. This makes it impossible to use OpenRefine with non-public collections. This was never documented, and most users weren't aware that they can indeed use OpenRefine with non-public collections anyway.
74c8627 to
97806ea
Compare
tillprochaska
added a commit
that referenced
this pull request
Dec 10, 2024
* Store hashed API keys Aleph used to store user API keys as plaintext in the database. This commit changes that to store only a hash of the API key. API keys are generated using the built-in `secrets.token_urlsafe` method which returns a random 256 bit token. In contrast to passwords, API keys are not provided by users, have a high entropy, and need to be validated on every request. It seems to be generally accepted that, given 256 bit tokens, salting or using an expensive key derivation functions isn't necessary. For this reason, we’re storing an unsalted SHA-256 hash of the API key which also makes it easy to look up and verify a given API key. I've added a separate column for the hashed API key rather than reusing the existing column. This allows us to batch-hash all existing plaintext keys without having to differentiate between keys that have already been hashed and those that haven't. Once all existing plaintext API keys have been hashed, the old `api_key` column can simply be dropped. * Add CLI command to store legacy plaintext API keys * Remove prefilled API key from OpenRefine endpoints Required as we do not store plaintext API keys anymore. Also, we want to remove the option to pass API keys via URL parameters in the future. This makes it impossible to use OpenRefine with non-public collections. This was never documented, and most users weren't aware that they can indeed use OpenRefine with non-public collections anyway.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is based on #3094. Review and merge #3094 first!
Aleph used to store user API keys as plaintext in the database. This commit changes that to store only a hash of the API key.
API keys are generated using the built-in
secrets.token_urlsafemethod which returns a random 256 bit token. In contrast to passwords, API keys are not provided by users, have a high entropy, and need to be validated on every request. It seems to be generally accepted that, given 256 bit tokens, salting or using an expensive key derivation functions isn't necessary. (But please challenge this!) For this reason, we’re storing an unsalted SHA-256 hash of the API key which also makes it easy to look up and verify a given API key.I've added a separate column for the hashed API key rather than reusing the existing column. This allows us to batch-hash all existing plaintext keys without having to differentiate between keys that have already been hashed and those that haven't. Once all existing plaintext API keys have been hashed, the old
api_keycolumn can simply be dropped.This is a breaking change. After deployment, admins need to run the
aleph hash-plaintext-api-keysCLI command to hash legacy plaintext API keys. Alternatively, users can regenerate their API key.