-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
[pulsar-client]Add a optional params scope for pulsar oauth2 client #11931
[pulsar-client]Add a optional params scope for pulsar oauth2 client #11931
Conversation
/pulsarbot run-failure-checks |
@tuteng Thanks for your contribution. Please do not forget to add docs accordingly to allow users to know your great code changes. And you can ping me to review the docs, thanks. |
/pulsarbot run-failure-checks |
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.
very useful, I left a comment about the test.
please take a look
@@ -86,6 +86,7 @@ public void testConfigure() throws Exception { | |||
params.put("privateKey", "data:base64,e30="); | |||
params.put("issuerUrl", "http://localhost"); | |||
params.put("audience", "http://localhost"); | |||
params.put("scope", "test-scope"); |
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.
can you please add more testing about this value ?
I see this only added here and there is not follow up verification
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.
@addisonj I have added some tests, please take a look at this, thanks
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.
Good addition. Left some comments that I think we should address before merging this.
...client/src/test/java/org/apache/pulsar/client/impl/auth/oauth2/protocol/TokenClientTest.java
Outdated
Show resolved
Hide resolved
@@ -76,6 +77,9 @@ public TokenResult exchangeClientCredentials(ClientCredentialsExchangeRequest re | |||
bodyMap.put("client_id", req.getClientId()); | |||
bodyMap.put("client_secret", req.getClientSecret()); | |||
bodyMap.put("audience", req.getAudience()); |
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.
It seems to me that the audience
field originates from the Auth0
implementation, and is not necessary in every case. Since it is optional and since the bodyMap
does not allow for null
values, I think we should only put this field in the bodyMap
if it is non empty and non null.
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.
I haven't seen the audience related specification yet, if I want to change this configuration, there might be other parts that need to be updated, for example https://github.com/apache/pulsar/blob/master/pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/FlowBase.java#L61, maybe other language need to be updated as well, I'm worried about breaking client compatibility, I want to fixed it in the next pr
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.
I'll submit a PR to change the behavior. My main point is that the RFC for this flow (https://datatracker.ietf.org/doc/html/rfc6749#section-4.4.2) does not mention audience
. The only IDP I know of that requires the audience
field is Auth0. As such, we shouldn't require that audience be set. I don't think it will break client compatibility to demote a field from being required to optional.
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.
I submitted the PR here: #11988
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/protocol/TokenClient.java
Show resolved
Hide resolved
* @param audience the audience identifier | ||
* @param scope the scope |
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.
I think it'd be helpful to update these comments. The audience field seems tied to auth0, not oauth2.0 itself, so you might even reference the auth0 spec: https://auth0.com/docs/authorization/flows/call-your-api-using-the-client-credentials-flow. The scope is an optional part of the oauth2.0 spec defined here: https://datatracker.ietf.org/doc/html/rfc6749#section-4.4.2.
It'd also be helpful to know what is optional and what is required.
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.
Fixed scope
, but without changing the audience
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.
Makes sense, thanks.
@eolivelli please review @tuteng 's latest change. |
/pulsarbot run-failure-checks |
when(defaultAsyncHttpClient.preparePost(url.toString())).thenReturn(boundRequestBuilder); | ||
when(boundRequestBuilder.setHeader("Accept", "application/json")).thenReturn(boundRequestBuilder); | ||
when(boundRequestBuilder.setHeader("Content-Type", "application/x-www-form-urlencoded")).thenReturn(boundRequestBuilder); | ||
when(boundRequestBuilder.setBody(body)).thenReturn(boundRequestBuilder); |
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.
@tuteng Could you please provide more context about this test? I do not fully understand the purpose of this test. Here we only return the boundRequestBuilder
if the body equals the body map, but the request always has the scope
, so that we will always return null here. But looks like the test will not touch any response handling steps.
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.
The purpose of this test is to test that the scope
is correctly encoded in the request body, because it is a unit test, so there is no way to get the real response, In this unit test, only this part of the logic in this function exchangeClientCredentials
can be tested
Map<String, String> bodyMap = new TreeMap<>();
bodyMap.put("grant_type", "client_credentials");
bodyMap.put("client_id", req.getClientId());
bodyMap.put("client_secret", req.getClientSecret());
bodyMap.put("audience", req.getAudience());
if (!StringUtils.isBlank(req.getScope())) {
bodyMap.put("scope", req.getScope());
}
String body = buildClientCredentialsBody(bodyMap);
because it has no way to actually send an http request to a server, all http-related operations are mocked,
So there is the following mock call:
when(boundRequestBuilder.setBody(body)).thenReturn(boundRequestBuilder);
Note that there is a body that is mocked here, and the test will pass when it has the same value as the body in the following function, otherwise an exception will be thrown, the body in the following function is generated in the exchangeClientCredentials function:
Response res = httpClient.preparePost(tokenUrl.toString())
.setHeader("Accept", "application/json")
.setHeader("Content-Type", "application/x-www-form-urlencoded")
.setBody(body)
.execute()
.get();
This is the current way to verify that the scope is encoded correctly
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.
I see. Thanks for the explanation
bodyMap.put("client_id", request.getClientId()); | ||
bodyMap.put("client_secret", request.getClientSecret()); | ||
bodyMap.put("audience", request.getAudience()); | ||
if (!StringUtils.isBlank(request.getScope())) { |
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.
nit: the request.getScope() is always "test-scope", so looks like a unnecessary check.
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.
LGTM
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.
LGTM
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.
LGTM
…11931) ### Motivation In some scenarios (e.g. azure cloud), when the client exchanges tokens with the server, an optional scope parameter is required, this pr fixes this issue, to ensure compatibility, when the user does not fill in this parameter, all behavior is the same as before. ### Modifications * Add an optional parameter scope when exchanges token ### Verifying this change - [x] Make sure that the change passes the CI checks. (cherry picked from commit ac5114f)
…11931) ### Motivation In some scenarios (e.g. azure cloud), when the client exchanges tokens with the server, an optional scope parameter is required, this pr fixes this issue, to ensure compatibility, when the user does not fill in this parameter, all behavior is the same as before. ### Modifications * Add an optional parameter scope when exchanges token ### Verifying this change - [x] Make sure that the change passes the CI checks. (cherry picked from commit ac5114f)
…ion (#12305) ### Motivation It's a C++ client catchup for #11931. ### Modifications - Add a `scope_` field to `ClientCredentialFlow` and load it from `ParamMap` object whose key is `scope`. - Refactor `ClientCredentialFlow` to simplify code and make it testable: - Use only one constructor instead of two overloaded constructors that might look confused - Add a `generateJsonBody` public method for generating JSON body for post fields in `authenticate` so that it can be tested. - Add a `KeyFile` class like what Java client does to load client id and client secret from `ParamMap` or file. ### Verifying this change - [x] Make sure that the change passes the CI checks. This change added test `AuthPluginTest.testOauth2RequestBody` for the cases that scope exists or doesn't exist.
…ion (#12305) It's a C++ client catchup for #11931. - Add a `scope_` field to `ClientCredentialFlow` and load it from `ParamMap` object whose key is `scope`. - Refactor `ClientCredentialFlow` to simplify code and make it testable: - Use only one constructor instead of two overloaded constructors that might look confused - Add a `generateJsonBody` public method for generating JSON body for post fields in `authenticate` so that it can be tested. - Add a `KeyFile` class like what Java client does to load client id and client secret from `ParamMap` or file. - [x] Make sure that the change passes the CI checks. This change added test `AuthPluginTest.testOauth2RequestBody` for the cases that scope exists or doesn't exist. (cherry picked from commit 44dcc04)
…ion (#12305) It's a C++ client catchup for #11931. - Add a `scope_` field to `ClientCredentialFlow` and load it from `ParamMap` object whose key is `scope`. - Refactor `ClientCredentialFlow` to simplify code and make it testable: - Use only one constructor instead of two overloaded constructors that might look confused - Add a `generateJsonBody` public method for generating JSON body for post fields in `authenticate` so that it can be tested. - Add a `KeyFile` class like what Java client does to load client id and client secret from `ParamMap` or file. - [x] Make sure that the change passes the CI checks. This change added test `AuthPluginTest.testOauth2RequestBody` for the cases that scope exists or doesn't exist. (cherry picked from commit 44dcc04)
…pache#11931) ### Motivation In some scenarios (e.g. azure cloud), when the client exchanges tokens with the server, an optional scope parameter is required, this pr fixes this issue, to ensure compatibility, when the user does not fill in this parameter, all behavior is the same as before. ### Modifications * Add an optional parameter scope when exchanges token ### Verifying this change - [x] Make sure that the change passes the CI checks.
…ion (apache#12305) ### Motivation It's a C++ client catchup for apache#11931. ### Modifications - Add a `scope_` field to `ClientCredentialFlow` and load it from `ParamMap` object whose key is `scope`. - Refactor `ClientCredentialFlow` to simplify code and make it testable: - Use only one constructor instead of two overloaded constructors that might look confused - Add a `generateJsonBody` public method for generating JSON body for post fields in `authenticate` so that it can be tested. - Add a `KeyFile` class like what Java client does to load client id and client secret from `ParamMap` or file. ### Verifying this change - [x] Make sure that the change passes the CI checks. This change added test `AuthPluginTest.testOauth2RequestBody` for the cases that scope exists or doesn't exist.
Motivation
In some scenarios (e.g. azure cloud), when the client exchanges tokens with the server, an optional scope parameter is required, this pr fixes this issue, to ensure compatibility, when the user does not fill in this parameter, all behavior is the same as before.
Modifications
Verifying this change
(Please pick either of the following options)
This change is a trivial rework / code cleanup without any test coverage.
(or)
This change is already covered by existing tests, such as (please describe tests).
(or)
This change added tests and can be verified as follows:
(example:)
Does this pull request potentially affect one of the following parts:
If
yes
was chosen, please highlight the changesDocumentation
Check the box below and label this PR (if you have committer privilege).
Need to update docs?
doc-required
Pulsar client oauth2 client support optional parameter scope #11932
(If you need help on updating docs, create a doc issue)
no-need-doc
(Please explain why)
doc
(If this PR contains doc changes)