Skip to content
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

Closed
wants to merge 1 commit into from

Conversation

janza
Copy link

@janza janza commented Aug 4, 2019

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 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.

Issues resolved

Closes #1237

@CLAassistant
Copy link

CLAassistant commented Aug 4, 2019

CLA assistant check
All committers have signed the CLA.

@janza janza force-pushed the feat/oauth-encrypted-credentials branch from e0085b7 to 7ac170a Compare August 4, 2019 20:29
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.
@janza janza force-pushed the feat/oauth-encrypted-credentials branch from 7ac170a to fe94779 Compare August 8, 2019 14:31
@janza janza changed the base branch from master to next August 8, 2019 14:35
@bungle
Copy link
Member

bungle commented Aug 9, 2019

@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?

@janza
Copy link
Author

janza commented Aug 9, 2019

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.

@bungle
Copy link
Member

bungle commented Aug 9, 2019

@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. private_key_jwt.

@janza
Copy link
Author

janza commented Aug 13, 2019

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.

@hishamhm
Copy link
Contributor

hishamhm commented Sep 9, 2019

I'm open to adding configuration option if that would help with getting this patch merged.

I think that would be the safer way to approach this!

@janza
Copy link
Author

janza commented Sep 11, 2019

Looking at the codebase I think the best option would be to add a boolean flag to create/update endpoints for credentials /consumers/:consumers/oauth2/:oauth2_credentials. If the flag is set those credentials will be hashed, or otherwise just stored raw.

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?

@hishamhm
Copy link
Contributor

@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.

@janza
Copy link
Author

janza commented Oct 8, 2019

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.

@hishamhm
Copy link
Contributor

@janza but this would cause problems in case someone's unhashed secret is s256|a|a, right? Since keys can be arbitrary, it seems to me that the information that states that the key is hashed must live out-of-band, and not encoded as part of the string (otherwise any possible encoding could be a valid unhashed value).

@janza
Copy link
Author

janza commented Oct 14, 2019

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 oauth2_credentials dao. Specificaly in the before hook I'm missing some code to fetch current plugin configuration. If you could give some insight in now to properly do that that I can try and implement it.

end

return {
hash = function(secret)
Copy link
Contributor

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

bungle added a commit that referenced this pull request Feb 26, 2020
### 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).
bungle added a commit that referenced this pull request Feb 26, 2020
### 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)
bungle added a commit that referenced this pull request Feb 27, 2020
### 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)
bungle added a commit that referenced this pull request Feb 28, 2020
### 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)
bungle added a commit that referenced this pull request Mar 10, 2020
### 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)
bungle added a commit that referenced this pull request Mar 19, 2020
### 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)
bungle added a commit that referenced this pull request Mar 24, 2020
### 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)
bungle added a commit that referenced this pull request Mar 25, 2020
### 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)
bungle added a commit that referenced this pull request Mar 26, 2020
### 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)
bungle added a commit that referenced this pull request Mar 26, 2020
### 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)
@bungle bungle closed this Mar 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants