Skip to content

Allow AbstractRestClientOAuth2AccessTokenResponseClient to be extended #15953

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

Closed
bmorris591 opened this issue Oct 19, 2024 · 3 comments
Closed
Assignees
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) status: duplicate A duplicate of another issue type: enhancement A general enhancement

Comments

@bmorris591
Copy link

I have a legacy OAuth2 API I need to use, and it requires the use of a password grant. Support for password grants was removed in AbstractRestClientOAuth2AccessTokenResponseClient so when I tried to migrate my OAuth2 configuration to use the new RestClient based OAuth2AccessTokenResponseClient I could not. At least not for the password grant.

I tried to implement my own, but the constructor of AbstractRestClientOAuth2AccessTokenResponseClient is package private so it cannot be extended. I did not want to copy all the code, as that is a maintainability nightmare.

Consider making AbstractRestClientOAuth2AccessTokenResponseClient extensible for this use case, even though password grants are deprecated there are still many out in the wild.


As a workaround I've created the package org.springframework.security.oauth2.client.endpoint in my own project, which allows me to extend. Obviously that doesn't work with JPMS - and it's also a nasty hack.

@bmorris591 bmorris591 added status: waiting-for-triage An issue we've not yet triaged type: enhancement A general enhancement labels Oct 19, 2024
@sjohnr
Copy link
Contributor

sjohnr commented Oct 24, 2024

Thanks for reaching out @bmorris591!

This issue is very similar to gh-14657 so I'm going to close this as a duplicate. Having said that, in Spring Security 6.4 (currently available in 6.4.0-RC1 and 6.4.0-SNAPSHOT), you can directly implement a minimal version of OAuth2AccessTokenResponseClient and re-use DefaultOAuth2TokenRequestHeadersConverter and DefaultOAuth2TokenRequestParametersConverter as in the following example:

public final class RestClientPasswordTokenResponseClient
		implements OAuth2AccessTokenResponseClient<OAuth2PasswordGrantRequest> {

	private final RestClient restClient = RestClient.builder()
		.messageConverters((messageConverters) -> {
			messageConverters.clear();
			messageConverters.add(new FormHttpMessageConverter());
			messageConverters.add(new OAuth2AccessTokenResponseHttpMessageConverter());
		})
		.defaultStatusHandler(new OAuth2ErrorResponseErrorHandler())
		.build();

	private final Converter<OAuth2PasswordGrantRequest, HttpHeaders> headersConverter =
		new DefaultOAuth2TokenRequestHeadersConverter<>();

	private final Converter<OAuth2PasswordGrantRequest, MultiValueMap<String, String>> parametersConverter =
		new DefaultOAuth2TokenRequestParametersConverter<>();

	@Override
	public OAuth2AccessTokenResponse getTokenResponse(OAuth2PasswordGrantRequest grantRequest) {
		try {
			return this.restClient.post()
				.uri(grantRequest.getClientRegistration().getProviderDetails().getTokenUri())
				.headers((h) -> h.putAll(this.headersConverter.convert(grantRequest)))
				.body(this.parametersConverter.convert(grantRequest))
				.retrieve()
				.body(OAuth2AccessTokenResponse.class);
		}
		catch (RestClientException ex) {
			String errorMessage = "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: %s"
				.formatted(ex.getMessage());
			OAuth2Error error = new OAuth2Error("invalid_token_response", errorMessage, null);
			throw new OAuth2AuthorizationException(error, ex);
		}
	}

}

If you do, please keep in mind that the OAuth2PasswordGrantRequest class is deprecated and will be removed in Spring Security 7.

@sjohnr sjohnr closed this as completed Oct 24, 2024
@sjohnr sjohnr self-assigned this Oct 24, 2024
@sjohnr sjohnr added status: duplicate A duplicate of another issue in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) and removed status: waiting-for-triage An issue we've not yet triaged labels Oct 24, 2024
@sjohnr
Copy link
Contributor

sjohnr commented Oct 24, 2024

Also note that DefaultPasswordTokenResponseClient is deprecated but still available until Spring Security 7.

@bmorris591
Copy link
Author

Also note that DefaultPasswordTokenResponseClient is deprecated but still available until Spring Security 7.

Yeah - I was trying to migrate everything to RestClient so it was nice and "neat". Thanks for your hint on the simply impl - seems to work in tests. When the time comes for Spring 7 I will need to revisit.

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) status: duplicate A duplicate of another issue type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants