Skip to content

Add support for Resource Owner Password Credentials grant #7013

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
wants to merge 4 commits into from

Conversation

jgrandja
Copy link
Contributor

@jgrandja jgrandja commented Jun 17, 2019

Fixes #6003

@jgrandja jgrandja self-assigned this Jun 17, 2019
@jgrandja jgrandja added in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: enhancement A general enhancement labels Jun 17, 2019
@jgrandja jgrandja force-pushed the gh-6003-pwd-grant branch from a8a5f16 to a916391 Compare July 10, 2019 02:43
@jgrandja jgrandja force-pushed the gh-6003-pwd-grant branch from a916391 to 7f81fc6 Compare July 19, 2019 13:07
@jgrandja jgrandja marked this pull request as ready for review July 19, 2019 13:31
@jgrandja jgrandja requested review from rwinch and jzheaux July 19, 2019 13:36
@jgrandja jgrandja added this to the 5.2.0.RC1 milestone Jul 26, 2019
@jgrandja jgrandja force-pushed the gh-6003-pwd-grant branch from 7f81fc6 to efaa1e1 Compare July 26, 2019 20:59
Copy link
Member

@rwinch rwinch left a comment

Choose a reason for hiding this comment

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

I have replied inline


ClientRegistration clientRegistration = context.getClientRegistration();
OAuth2AuthorizedClient authorizedClient = context.getAuthorizedClient();
if (!AuthorizationGrantType.PASSWORD.equals(clientRegistration.getAuthorizationGrantType()) ||
Copy link
Member

Choose a reason for hiding this comment

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

Should it retrieve the OAuth2AuthorizedClient again if the token is expired?

Copy link
Contributor Author

@jgrandja jgrandja Aug 23, 2019

Choose a reason for hiding this comment

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

The RefreshTokenOAuth2AuthorizedClientProvider will take care of this as long as it's configured/composed within the DefaultOAuth2AuthorizedClientManager - which by default it is configured.

Copy link
Member

Choose a reason for hiding this comment

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

If the grant type is PASSWORD doesn't it need to use a OAuth2PasswordGrantRequest to request a new token?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It does use a OAuth2PasswordGrantRequest when calling the OAuth2AccessTokenResponseClient- see code just below this logic.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry that was in context of my previous comment. If the token expires shouldn't a new token be requested with a OAuth2PasswordGrantRequest

Copy link
Contributor Author

@jgrandja jgrandja Aug 28, 2019

Choose a reason for hiding this comment

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

If the token expires shouldn't a new token be requested with a OAuth2PasswordGrantRequest

No. For expired access tokens, the RefreshTokenOAuth2AuthorizedClientProvider handles this. The PasswordOAuth2AuthorizedClientProvider only handles getting a new access token (if client is not authorized)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, looks like I missed a condition here. I'll update shortly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@rwinch Thanks for catching this. I've pushed the updates.

Copy link
Contributor

@jzheaux jzheaux left a comment

Choose a reason for hiding this comment

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

I've left some feedback inline.

contextAttributes.put(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME,
StringUtils.delimitedListToStringArray(scope, " "));
}
String username = authorizeRequest.getServerWebExchange().getRequest().getQueryParams().getFirst(OAuth2ParameterNames.USERNAME);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this will only get the username if the username is a query parameter, but not if it's a form parameter.

Copy link
Contributor Author

@jgrandja jgrandja Aug 27, 2019

Choose a reason for hiding this comment

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

@jzheaux Yes you are right. Thanks for catching this! Form parameters are read from ServerWebExchange().getFormData(), which returns a Mono<MultiValueMap<String, String>>. So I had to change the API for DefaultServerOAuth2AuthorizedClientManager.contextAttributesMapper to Function<ServerOAuth2AuthorizeRequest, Mono<Map<String, Object>>> (return a Mono).

I don't think it's a good idea to read the request body for each request mapping by default, so I removed that code. The default behaviour for DefaultContextAttributesMapper should read supported query parameters only.

NOTE: I did add a test that shows how a custom contextAttributesMapper can map form parameters.

contextAttributes.put(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME,
StringUtils.delimitedListToStringArray(scope, " "));
}
String username = authorizeRequest.getServletRequest().getParameter(OAuth2ParameterNames.USERNAME);
Copy link
Contributor

Choose a reason for hiding this comment

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

I figured because of this comment: https://github.com/spring-projects/spring-security/pull/7013/files#diff-b1268bb315785679ff599fe121c6a23aR142 this mapping would be removed from both the servlet bits as well as the reactive bits. This PR appears to remove it from reactive but not servlet.

Copy link
Contributor

Choose a reason for hiding this comment

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

I went ahead and logged #7350 to address this separately so this PR can be merged before RC1.

However, I'd recommend that #7350 ticket be addressed before RC1 if possible.

@jgrandja
Copy link
Contributor Author

jgrandja commented Sep 4, 2019

Merged via dcd997e

@jgrandja jgrandja closed this Sep 4, 2019
@jgrandja jgrandja deleted the gh-6003-pwd-grant branch September 4, 2019 18:14
@spring-projects spring-projects deleted a comment from jgrandja Mar 24, 2020
@spring-projects spring-projects deleted a comment from jgrandja Mar 24, 2020
@spring-projects spring-projects deleted a comment from jgrandja Mar 24, 2020
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.

Support Resource Owner Password Credentials grant
3 participants