-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(oauth2) hash client secret #4866
Conversation
e0085b7
to
7ac170a
Compare
Hashing is done using sha256 provided by openresty library. The change is backwards compatible by validating hashed secrets only if they are stored in the right format: `s256|hashed_secret|salt`. If the secret doesn't match the format the code assumes secret is stored raw. Most of the code is based on hashing code used in basic-auth plugin.
7ac170a
to
fe94779
Compare
@janza, do you think it should be configurable? What I mean is that it is quite common case to go to e.g. developer portal, and grab the secret. If it is hashed, you need to generate a new secret. Or am I following this correctly? |
Most of the services that use secret hashing only show the secret once when the client is created. There is no way to retrieve it unless a new secret is generated. Secrets should be treated the same as passwords — services don't provide a way to see account password, only the option to reset it. That said, in case there are users using kong in the way you descibed it could be an option to add a configuration flag for backwards compatibility. |
@janza, yes, I somewhat think it depends on situation. I use a lot of services where this is implemented so that you can grab the secret anytime (of course first by signing in, and perhaps presenting 2-factor), and e.g. keycloak allows you to just go to admin and clients to get one. Sometimes it is easier, albeit less secure, just to get secret than create a new client or change the secret (which could affect other components). Of course public key crypto could be used here too... but at the moment the plugin does not support it, e.g. |
I'm open to adding configuration option if that would help with getting this patch merged. I think that in case users don't want secrets to be hashed they should be responsible for providing ways to protect secrets (additional password verification, 2FA, ...) and/or en/decryption before calling into kong oauth2 api — that seems out of scope for kong itself. |
I think that would be the safer way to approach this! |
Looking at the codebase I think the best option would be to add a boolean flag to create/update endpoints for credentials Another idea is to add this configuration flag to plugin config but there's no obvious way to get oauth2 plugin configuration in the oauth2_credentials dao methods. Any recommendations? |
@janza I believe we would need both flags: in the DAO so we can identify which keys are hashed and which ones are not (keeping backwards compatibility), and in the plugin config so that it knows when to apply the DAO flag. |
Current code is already backwards compatible with unhashed keys - hashed keys are stored in a certain format in the DB so we can identify hashed and unhashed keys so I don't think it's needed. |
@janza but this would cause problems in case someone's unhashed secret is |
That is correct and if it's not an acceptable issue we'll also need to have this configuration as part of the DAO. What is not clear to me, in the code, is how to get this flag from plugin configuration into |
end | ||
|
||
return { | ||
hash = function(secret) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use peer-reviewed hashing algorithms like bcrypt instead of rolling our own here, which automatically handle things like salts and performance tunables
### Summary This was originally implemented with #4866 by @janza. After some review comments, and the introduction of DAO transformations, I decided to make changes, thus opening this new PR. This PR adds a new `boolean? column `hash_secret` to `oauth2_credentials` that is used to determine whether or not the `client_secret` will be hashed. The PR adds support for `argon2`, and `bcrypt` and it uses `argon2` if the system library for argon2 is installed. Otherwise it will fallback to `bcrypt`. On successful `client_secret` the plugin will also check if the `client_secret` needs to be rehashed. One caveat. If you run this on cluster and some nodes have `argon2` and some don't, it is possible that you cannot use the credentials on those that don't. So keep your environments similar. This is opened as a draft as I still need to add tests and perhaps some other slight adjustments (still thinking about should plugin be able to force to only use hashed passwords).
### Summary This was originally implemented with #4866 by @janza. After some review comments, and the introduction of DAO transformations, I decided to make changes, thus opening this new PR. This PR adds a new `boolean` column `hash_secret` to `oauth2_credentials` that is used to determine whether or not the `client_secret` will be hashed. The PR adds support for `argon2`, and `bcrypt` and it uses `argon2` if the system library for argon2 is installed. Otherwise it will fallback to `bcrypt`. The plugin will also check if the `client_secret` needs to be rehashed (on usage). One caveat. If you run this on cluster and some nodes have `argon2` and some don't, it is possible that you cannot use the credentials on those that don't. So keep your environments similar. ### Issues resolved Close #4866, Fix #1237 (at least on OAuth2)
### Summary This was originally implemented with #4866 by @janza. After some review comments, and the introduction of DAO transformations, I decided to make changes, thus opening this new PR. This PR adds a new `boolean` column `hash_secret` to `oauth2_credentials` that is used to determine whether or not the `client_secret` will be hashed. The PR adds support for `argon2`, and `bcrypt` and it uses `argon2` if the system library for argon2 is installed. Otherwise it will fallback to `bcrypt`. The plugin will also check if the `client_secret` needs to be rehashed (on usage). One caveat. If you run this on cluster and some nodes have `argon2` and some don't, it is possible that you cannot use the credentials on those that don't. So keep your environments similar. ### Issues resolved Close #4866, Fix #1237 (at least on OAuth2)
### Summary This was originally implemented with #4866 by @janza. After some review comments, and the introduction of DAO transformations, I decided to make changes, thus opening this new PR. This PR adds a new `boolean` column `hash_secret` to `oauth2_credentials` that is used to determine whether or not the `client_secret` will be hashed. The PR adds support for `argon2`, and `bcrypt` and it uses `argon2` if the system library for argon2 is installed. Otherwise it will fallback to `bcrypt`. The plugin will also check if the `client_secret` needs to be rehashed (on usage). One caveat. If you run this on cluster and some nodes have `argon2` and some don't, it is possible that you cannot use the credentials on those that don't. So keep your environments similar. ### Issues resolved Close #4866, Fix #1237 (at least on OAuth2)
### Summary This was originally implemented with #4866 by @janza. After some review comments, and the introduction of DAO transformations, I decided to make changes, thus opening this new PR. This PR adds a new `boolean` column `hash_secret` to `oauth2_credentials` that is used to determine whether or not the `client_secret` will be hashed. The PR adds support for `argon2`, and `bcrypt` and it uses `argon2` if the system library for argon2 is installed. Otherwise it will fallback to `bcrypt`. The plugin will also check if the `client_secret` needs to be rehashed (on usage). One caveat. If you run this on cluster and some nodes have `argon2` and some don't, it is possible that you cannot use the credentials on those that don't. So keep your environments similar. ### Issues resolved Close #4866, Fix #1237 (at least on OAuth2)
### Summary This was originally implemented with #4866 by @janza. After some review comments, and the introduction of DAO transformations, I decided to make changes, thus opening this new PR. This PR adds a new `boolean` column `hash_secret` to `oauth2_credentials` that is used to determine whether or not the `client_secret` will be hashed. The PR adds support for `argon2`, and `bcrypt` and it uses `argon2` if the system library for argon2 is installed. Otherwise it will fallback to `bcrypt`. The plugin will also check if the `client_secret` needs to be rehashed (on usage). One caveat. If you run this on cluster and some nodes have `argon2` and some don't, it is possible that you cannot use the credentials on those that don't. So keep your environments similar. ### Issues resolved Close #4866, Fix #1237 (at least on OAuth2)
### Summary This was originally implemented with #4866 by @janza. After some review comments, and the introduction of DAO transformations, I decided to make changes, thus opening this new PR. This PR adds a new `boolean` column `hash_secret` to `oauth2_credentials` that is used to determine whether or not the `client_secret` will be hashed. The PR adds support for `argon2`, and `bcrypt` and it uses `argon2` if the system library for argon2 is installed. Otherwise it will fallback to `bcrypt`. The plugin will also check if the `client_secret` needs to be rehashed (on usage). One caveat. If you run this on cluster and some nodes have `argon2` and some don't, it is possible that you cannot use the credentials on those that don't. So keep your environments similar. ### Issues resolved Close #4866, Fix #1237 (at least on OAuth2)
### Summary This was originally implemented with #4866 by @janza. After some review comments, and the introduction of DAO transformations, I decided to make changes, thus opening this new PR. This PR adds a new `boolean` column `hash_secret` to `oauth2_credentials` that is used to determine whether or not the `client_secret` will be hashed. The PR adds support for `argon2`, and `bcrypt` and it uses `argon2` if the system library for argon2 is installed. Otherwise it will fallback to `bcrypt`. The plugin will also check if the `client_secret` needs to be rehashed (on usage). One caveat. If you run this on cluster and some nodes have `argon2` and some don't, it is possible that you cannot use the credentials on those that don't. So keep your environments similar. ### Issues resolved Close #4866, Fix #1237 (at least on OAuth2)
### Summary This was originally implemented with #4866 by @janza. After some review comments, and the introduction of DAO transformations, I decided to make changes, thus opening this new PR. This PR adds a new `boolean` column `hash_secret` to `oauth2_credentials` that is used to determine whether or not the `client_secret` will be hashed. The PR adds support for `argon2`, and `bcrypt` and it uses `argon2` if the system library for argon2 is installed. Otherwise it will fallback to `bcrypt`. The plugin will also check if the `client_secret` needs to be rehashed (on usage). One caveat. If you run this on cluster and some nodes have `argon2` and some don't, it is possible that you cannot use the credentials on those that don't. So keep your environments similar. ### Issues resolved Close #4866, Fix #1237 (at least on OAuth2)
### Summary This was originally implemented with #4866 by @janza. After some review comments, and the introduction of DAO transformations, I decided to make changes, thus opening this new PR. This PR adds a new `boolean` column `hash_secret` to `oauth2_credentials` that is used to determine whether or not the `client_secret` will be hashed. The PR adds support for `argon2`, and `bcrypt` and it uses `argon2` if the system library for argon2 is installed. Otherwise it will fallback to `bcrypt`. The plugin will also check if the `client_secret` needs to be rehashed (on usage). One caveat. If you run this on cluster and some nodes have `argon2` and some don't, it is possible that you cannot use the credentials on those that don't. So keep your environments similar. ### Issues resolved Close #4866, Fix #1237 (at least on OAuth2)
Summary
Hashing is done using sha256 provided by openresty library. The change
is backwards compatible by validating hashed secrets only if they are
stored in the right format:
s256|hashed_secret|salt
. If the secretdoesn't match the format the code assumes secret is stored raw. Most of
the code is based on hashing code used in basic-auth plugin.
Issues resolved
Closes #1237