-
Notifications
You must be signed in to change notification settings - Fork 64
added post client auth method #289
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
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: Ivan Gatnau Lopez <[email protected]>
Signed-off-by: Ivan Gatnau Lopez <[email protected]>
Signed-off-by: Ivan Gatnau Lopez <[email protected]>
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.
Thanks!
I've left some comments on the PR. Thanks for raising!
In order to have the PR merged and in s state that can be safely maintained a couple things need to be added:
- Unit tests validating that the POST method works as expected. The current PR only configures changes tests for the BASIC. Make sure there are unit tests for the case where no method is set, and when basic and post are set. The three cases need to be explicitly covered.
- An end-to-end test that also exercises the post method. We use Keycloak in the e2e tests. Some suite should be updated to use the post mehtod and verify it is working as expected.
Having these two points properly implemented and covered will help us maintain the feature without breaking it accidentally in the future.
Thanks!
config/v1/oidc/config.proto
Outdated
// This section define swhether | ||
// [Client Authentication](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication) | ||
// is Basic (default) or method post. |
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.
// This section define swhether | |
// [Client Authentication](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication) | |
// is Basic (default) or method post. | |
// Available [Client Authentication](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication) methods |
internal/authz/oidc.go
Outdated
inthttp.HeaderAuthorization: []string{inthttp.BasicAuthHeader(o.config.GetClientId(), o.config.GetClientSecret())}, | ||
form, error := buildAuthParams(o.config, codeFromReq, stateFromReq) | ||
if error != nil { | ||
log.Error("error building form", error) |
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.
log.Error("error building form", error) | |
log.Error("error building auth params", error) |
internal/authz/oidc.go
Outdated
// or if the implementation for the specified method is not supported. | ||
func buildAuthHeader(config *oidcv1.OIDCConfig) (http.Header, error) { | ||
|
||
headers := http.Header{} |
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.
There is no need to allocate something here if it is going to be replaced.
headers := http.Header{} | |
var headers http.Header |
internal/authz/oidc.go
Outdated
case oidcv1.OIDCConfig_CLIENT_AUTHENTICATION_METHOD_CLIENT_SECRET_JWT: | ||
// Build jwt auth header | ||
// TODO: implement jwt auth header | ||
return nil, errors.New("not implemented") |
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.
Add more details in the error about what is not implemented so users can understand what is the problem when receiving the response back.
internal/authz/oidc.go
Outdated
params := url.Values{} | ||
switch config.GetMethod() { | ||
case oidcv1.OIDCConfig_CLIENT_AUTHENTICATION_METHOD_BASIC: | ||
default: |
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.
Same two comments as in the previous method.
Signed-off-by: Ivan Gatnau Lopez <[email protected]>
Signed-off-by: Ivan Gatnau Lopez <[email protected]>
Signed-off-by: Ivan Gatnau Lopez <[email protected]>
Thank you for your comments @nacx, while I am trying to implement new tests for new client authentication methods I have some doubts how you guys would like to have this done as TestOIDCProcess looks like an uber test difficult to breakdown in more atomic tests. I have for now duplicated this test as a reusable function I can call with different client authentication methods, would that be acceptable? See commit ilgatnau@998f12b |
Signed-off-by: Ivan Gatnau Lopez <[email protected]>
Signed-off-by: Ivan Gatnau Lopez <[email protected]>
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.
Looking good!
I've left mostly style nits.
There is one important validation thing as well.
Once this is addressed, the only thing left would be to exercise the POST authentication in one of the e2e tests (I'd just modify the keycloak
suite to use that) and it should be good to go!
|
||
|
||
// Clients create a JWT using an HMAC SHA algorithm, such as HMAC SHA-256 (currently not implemented) | ||
CLIENT_AUTHENTICATION_METHOD_CLIENT_SECRET_JWT = 3; | ||
|
||
|
||
// Clients that have registered a public key sign a JWT using that key (currently not implemented) | ||
CLIENT_AUTHENTICATION_METHOD_PRIVATE_KEY_JWT = 4; | ||
|
||
|
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.
style nit: remove the unnecessary blank lines
// Clients create a JWT using an HMAC SHA algorithm, such as HMAC SHA-256 (currently not implemented) | |
CLIENT_AUTHENTICATION_METHOD_CLIENT_SECRET_JWT = 3; | |
// Clients that have registered a public key sign a JWT using that key (currently not implemented) | |
CLIENT_AUTHENTICATION_METHOD_PRIVATE_KEY_JWT = 4; | |
// Clients create a JWT using an HMAC SHA algorithm, such as HMAC SHA-256 (currently not implemented) | |
CLIENT_AUTHENTICATION_METHOD_CLIENT_SECRET_JWT = 3; | |
// Clients that have registered a public key sign a JWT using that key (currently not implemented) | |
CLIENT_AUTHENTICATION_METHOD_PRIVATE_KEY_JWT = 4; |
|
||
// Build basic auth header | ||
headers = http.Header{ | ||
inthttp.HeaderContentType: []string{inthttp.HeaderContentTypeFormURLEncoded}, | ||
inthttp.HeaderAuthorization: []string{inthttp.BasicAuthHeader(config.GetClientId(), config.GetClientSecret())}, | ||
} | ||
|
||
case oidcv1.OIDCConfig_CLIENT_AUTHENTICATION_METHOD_CLIENT_SECRET_POST: | ||
|
||
// Build post auth header | ||
headers = http.Header{ | ||
inthttp.HeaderContentType: []string{inthttp.HeaderContentTypeFormURLEncoded}, | ||
} | ||
|
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.
style nit: for consistency with other code blocks, remove the unnecessary blank lines here as well:
// Build basic auth header | |
headers = http.Header{ | |
inthttp.HeaderContentType: []string{inthttp.HeaderContentTypeFormURLEncoded}, | |
inthttp.HeaderAuthorization: []string{inthttp.BasicAuthHeader(config.GetClientId(), config.GetClientSecret())}, | |
} | |
case oidcv1.OIDCConfig_CLIENT_AUTHENTICATION_METHOD_CLIENT_SECRET_POST: | |
// Build post auth header | |
headers = http.Header{ | |
inthttp.HeaderContentType: []string{inthttp.HeaderContentTypeFormURLEncoded}, | |
} | |
// Build basic auth header | |
headers = http.Header{ | |
inthttp.HeaderContentType: []string{inthttp.HeaderContentTypeFormURLEncoded}, | |
inthttp.HeaderAuthorization: []string{inthttp.BasicAuthHeader(config.GetClientId(), config.GetClientSecret())}, | |
} | |
case oidcv1.OIDCConfig_CLIENT_AUTHENTICATION_METHOD_CLIENT_SECRET_POST: | |
// Build post auth header | |
headers = http.Header{ | |
inthttp.HeaderContentType: []string{inthttp.HeaderContentTypeFormURLEncoded}, | |
} |
var params url.Values | ||
switch config.GetClientAuthenticationMethod() { | ||
case oidcv1.OIDCConfig_CLIENT_AUTHENTICATION_METHOD_BASIC: | ||
|
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.
"client_id": []string{config.GetClientId()}, | ||
"client_secret": []string{config.GetClientSecret()}, | ||
} | ||
|
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.
// Build jwt auth params | ||
// TODO: implement jwt auth params | ||
return nil, errors.New("client authentication method client_secret_jwt is not implemented") | ||
|
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.
|
||
default: | ||
|
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.
default: | |
default: |
|
||
return params, nil | ||
|
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.
style nit: for consistency with other code blocks, just rely on the method return. Let's just return in the cases or in the method, but let's not mix as it is confusing.
return params, nil |
|
||
return params, nil |
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.
return params, nil |
|
||
// Available [Client Authentication](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication) | ||
// methods | ||
ClientAuthenticationMethod client_authentication_method = 24; |
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.
Add the validation for this field. I think the lack of this validation is causing the current tests/examples to always fall to the default
cases, as the values configured there are not defined in the enum.
Adding this validation should make the authservice fail early and not allow undefined values.
ClientAuthenticationMethod client_authentication_method = 24; | |
ClientAuthenticationMethod client_authentication_method = 24 [(validate.rules).enum.defined_only = true]; |
BTW, to let the |
https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication
As per specs, multiple available Client Authentication methods that are used by Clients to authenticate to the Authorization Server when using the Token Endpoint. During Client Registration, the RP (Client) MAY register a Client Authentication method. If no method is registered, the default method is client_secret_basic.
These Client Authentication methods are:
This PR implements implementation for client_secret_post (currently only basic possible) plus placeholder for missing other 2 methods.