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

Reactive Implementation of AuthorizedClientServiceOAuth2AuthorizedCli… #7589

Closed
wants to merge 1 commit into from

Conversation

ankurpathak
Copy link
Contributor

…entManager

ReactiveOAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager is reactive
version of AuthorizedClientServiceOAuth2AuthorizedClientManager

Fixes: gh-7569

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Oct 31, 2019
@ankurpathak ankurpathak force-pushed the gh-7569-fix branch 5 times, most recently from 116f941 to 643fa9c Compare November 2, 2019 07:14
@jgrandja jgrandja added in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels Nov 11, 2019
@jgrandja jgrandja added this to the 5.3.x milestone Nov 11, 2019
Copy link
Contributor

@jgrandja jgrandja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @ankurpathak and for your patience waiting on me. Please see my comments.

* @see ReactiveOAuth2AuthorizedClientService
* @since 5.3
*/
public final class ReactiveOAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager implements ReactiveOAuth2AuthorizedClientManager {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's rename to OAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies. I meant to say AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager - without OAuth2 prefix so the naming is consistent with existing AuthorizedClientServiceOAuth2AuthorizedClientManager

})
.build()
).flatMap(authorizationContext -> this.reactiveAuthorizedClientProvider.authorize(authorizationContext)
.doOnNext(x -> reactiveAuthorizedClientService.saveAuthorizedClient(x, principal))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename x to authorizedClient

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to _authorizedClient as conflicting with local variable authorizedClient.

@ghostd
Copy link
Contributor

ghostd commented Nov 25, 2019

Hi,

(not sure where i should post this comment... so i put it here)

I had to change some code of the class to make it work with my use case.

How i tested this PR (maybe wrongly?)

(in my code, i already renamed ReactiveOAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager to OAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager)

    ReactiveClientRegistrationRepository clientRegistrationRepository = new InMemoryReactiveClientRegistrationRepository(clientRegistration);
    ReactiveOAuth2AuthorizedClientService authorizedClientService = new InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrationRepository);

    OAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =
        new OAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
                clientRegistrationRepository,
                authorizedClientService
        );
    authorizedClientManager.setReactiveOAuth2AuthorizedClientProvider(new SpecificPartnerReactiveOAuth2AuthorizedClientProvider());

The current implementation does not save the authorized client into the repository.

The code i changed to make it work

I changed

.doOnNext(x -> reactiveAuthorizedClientService.saveAuthorizedClient(x, principal))

to

.flatMap(authClient -> reactiveAuthorizedClientService.saveAuthorizedClient(authClient, principal).thenReturn(authClient))

Regards

@ankurpathak
Copy link
Contributor Author

ankurpathak commented Nov 25, 2019

Hi,

(not sure where i should post this comment... so i put it here)

I had to change some code of the class to make it work with my use case.

How i tested this PR (maybe wrongly?)

(in my code, i already renamed ReactiveOAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager to OAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager)

    ReactiveClientRegistrationRepository clientRegistrationRepository = new InMemoryReactiveClientRegistrationRepository(clientRegistration);
    ReactiveOAuth2AuthorizedClientService authorizedClientService = new InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrationRepository);

    OAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =
        new OAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
                clientRegistrationRepository,
                authorizedClientService
        );
    authorizedClientManager.setReactiveOAuth2AuthorizedClientProvider(new SpecificPartnerReactiveOAuth2AuthorizedClientProvider());

The current implementation does not save the authorized client into the repository.

The code i changed to make it work

I changed

.doOnNext(x -> reactiveAuthorizedClientService.saveAuthorizedClient(x, principal))

to

.flatMap(authClient -> reactiveAuthorizedClientService.saveAuthorizedClient(authClient, principal).thenReturn(authClient))

Regards

@ghostd I will wait for @jgrandja to review above commets and if your changes are required will do the needful.

…entManager

ReactiveOAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager is reactive
version of AuthorizedClientServiceOAuth2AuthorizedClientManager

Fixes: spring-projectsgh-7569
@ghostd
Copy link
Contributor

ghostd commented Nov 27, 2019

Hi,

I did some tests with the new version. It seems if DefaultContextAttributesMapper#apply returns (a mono of) an empty map, the authentication does not occur. If i change the DefaultContextAttributesMapper to return a non-empty map, the authentication succeeds.

attributes.putAll(contextAttributes);
}).build())
).flatMap(authorizationContext -> this.authorizedClientProvider.authorize(authorizationContext)
.doOnNext(_authorizedClient -> authorizedClientService.saveAuthorizedClient(_authorizedClient, principal))
Copy link
Contributor

@jgrandja jgrandja Dec 2, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ghostd Thanks for catching this...

.flatMap(authClient -> reactiveAuthorizedClientService.saveAuthorizedClient(authClient, principal).thenReturn(authClient))

@ankurpathak This bug was fixed in this commit.

Can you also apply the update to the test to make use of PublisherProbe<Void> saveAuthorizedClientProbe to ensure we cover the scenario of the Mono being subscribed to. See the commit that makes use of PublisherProbe in the test

Copy link
Contributor

@jgrandja jgrandja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates @ankurpathak. Please see my comments.


@Override
public Mono<Map<String, Object>> apply(OAuth2AuthorizeRequest authorizeRequest) {
ServerWebExchange serverWebExchange = authorizeRequest.getAttribute(ServerWebExchange.class.getName());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ServerWebExchange won't be available in this scenario so .defaultIfEmpty(Collections.emptyMap()) will execute every time. The logic should be similar to AuthorizedClientServiceOAuth2AuthorizedClientManager.DefaultContextAttributesMapper. Looks like a test is missing for this scenario, can you please add.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also see this comment as the logic for .flatMap(contextBuilder -> this.contextAttributesMapper.apply(authorizeRequest) is incorrect. Please add a test for this as well. If contextAttributesMapper returns an empty Map, authorizedClientProvider.authorize() should still be called.

@philsttr
Copy link
Contributor

philsttr commented Dec 2, 2019

Any chance this could be added in 5.2.x ?

.build();
Mono<OAuth2AuthorizedClient> authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);

authorizedClient.subscribe();
Copy link
Contributor

@philsttr philsttr Dec 2, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't subscribe() here. Instead, rely on StepVerifier subscribing (during verifyComplete()). Move the verifications and assertions after the StepVerifier.

The same comment applies to all these test methods where .subscribe() is explicitly called

@ankurpathak
Copy link
Contributor Author

ankurpathak commented Dec 5, 2019

@jgrandja you can takeover this as I tried a lot on this but can't make it.

@philsttr
Copy link
Contributor

philsttr commented Dec 5, 2019

I can pick this up to continue it.

@jgrandja
Copy link
Contributor

jgrandja commented Dec 5, 2019

@ankurpathak No worries and thank you for your work thus far.

@philsttr That would be great if you can take over this. Much appreciated.

@philsttr
Copy link
Contributor

philsttr commented Dec 5, 2019

Followup PR created as #7702

Please close this PR (#7589) in favor of #7702

@jgrandja jgrandja removed this from the 5.3.x milestone Dec 6, 2019
@jgrandja
Copy link
Contributor

jgrandja commented Dec 6, 2019

Closing in favour of #7702

@jgrandja jgrandja closed this Dec 6, 2019
philsttr added a commit to philsttr/spring-security that referenced this pull request Dec 10, 2019
Rename OAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager to AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager.

Handle empty mono returned from contextAttributesMapper.

Handle empty map returned from contextAttributesMapper.

Fix DefaultContextAttributesMapper so that it doesn't access ServerWebExchange.

Fix unit tests so that they pass.

Use StepVerifier in unit tests, rather than .subscribe().

Fixes spring-projectsgh-7569
jgrandja pushed a commit that referenced this pull request Dec 10, 2019
Rename OAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager to AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager.

Handle empty mono returned from contextAttributesMapper.

Handle empty map returned from contextAttributesMapper.

Fix DefaultContextAttributesMapper so that it doesn't access ServerWebExchange.

Fix unit tests so that they pass.

Use StepVerifier in unit tests, rather than .subscribe().

Fixes gh-7569
jgrandja pushed a commit that referenced this pull request Dec 10, 2019
Rename OAuth2AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager to AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager.

Handle empty mono returned from contextAttributesMapper.

Handle empty map returned from contextAttributesMapper.

Fix DefaultContextAttributesMapper so that it doesn't access ServerWebExchange.

Fix unit tests so that they pass.

Use StepVerifier in unit tests, rather than .subscribe().

Fixes gh-7569
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Provide reactive implementation of AuthorizedClientServiceOAuth2AuthorizedClientManager
5 participants