Skip to content

Implement User Info Endpoint #303

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
Closed

Conversation

idosal
Copy link
Contributor

@idosal idosal commented May 22, 2021

Hey @jgrandja,
this is a very rough draft to verify I'm in the right direction. I'd love to get your feedback to see how I can deliver this ASAP.

Thanks

@pivotal-cla
Copy link

@idosal Please sign the Contributor License Agreement!

Click here to manually synchronize the status of this Pull Request.

See the FAQ for frequently asked questions.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label May 22, 2021
@idosal idosal marked this pull request as draft May 22, 2021 11:29
@pivotal-cla
Copy link

@idosal Thank you for signing the Contributor License Agreement!

@jgrandja
Copy link
Collaborator

Apologies for the delay @idosal. I will review within the next few days.

@jgrandja jgrandja self-assigned this Jun 17, 2021
@jgrandja jgrandja added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels Jun 17, 2021
@jgrandja jgrandja added this to the 0.1.2 milestone Jun 17, 2021
@jgrandja jgrandja modified the milestones: 0.1.2, 0.2.0 Jun 25, 2021
@jgrandja
Copy link
Collaborator

jgrandja commented Jun 25, 2021

@idosal I'm pushing this out for the 0.2.0 release as we still have a few tasks to complete for 0.1.2.

Copy link
Contributor

@sjohnr sjohnr left a comment

Choose a reason for hiding this comment

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

@idosal, this is indeed a great start! Sorry for the wait time, I'm going to jump in and help move this forward.

First off, you will need to rebase on main before you start working on these changes.

I would suggest going back to commit e4df09b (e.g. git reset --hard e4df09b40e8da43eb30eb110cbb15b09181b7695), squash your commits (e.g. git rebase -i HEAD~2) and rebase the result on main.

You will have conflicts to resolve in the configurer, unfortunately. 😞 If you have trouble with this, let me know.

Once we get through the below round of changes, we can look at adding tests and testing using the samples project to make sure this is working.

@@ -0,0 +1,169 @@
/*
* Copyright 2020 the original author or authors.
Copy link
Contributor

Choose a reason for hiding this comment

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

Change to 2021.

* @author Ido Salomon
* @see AbstractHttpMessageConverter
* @see OidcUserInfo
* @since 0.1.1
Copy link
Contributor

Choose a reason for hiding this comment

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

Move below @author and change to 0.2.0, since that's the release we're targeting now.

import java.util.Map;

/**
* A {@link HttpMessageConverter} for an {@link OidcUserInfo OIDC User Info Response}.
Copy link
Contributor

Choose a reason for hiding this comment

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

Please change OIDC to OpenID. I'll tag some other places as well, but go ahead and change all comment references to OpenID.


private static final ParameterizedTypeReference<Map<String, Object>> STRING_OBJECT_MAP =
new ParameterizedTypeReference<Map<String, Object>>() {
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove whitespace, as in {}.


private final GenericHttpMessageConverter<Object> jsonMessageConverter = HttpMessageConverters.getJsonMessageConverter();

private Converter<Map<String, Object>, OidcUserInfo> oidcUserInfoConverter = new OidcUserInfoConverter();
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 we should prefer to remove oidc prefix from internal variable and parameter names. I'll tag some other places as well.

*/
public OAuth2AuthorizationServerConfigurer<B> userInfoClaimsMapper(UserInfoClaimsMapper userInfoClaimsMapper) {
Assert.notNull(userInfoClaimsMapper, "userInfoClaimsMapper cannot be null");
this.getBuilder().setSharedObject(UserInfoClaimsMapper.class, userInfoClaimsMapper);
Copy link
Contributor

Choose a reason for hiding this comment

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

With reduced visibility of the mapper class and moving it to this package, this would now wrap the given Function<Object, OidcUserInfo>, e.g.

this.getBuilder().setSharedObject(UserInfoClaimsMapper.class, new OidcUserInfoClaimsMapper(userInfoClaimsMapper));

This is so the shared object mechanism works internally, but the class is not exposed in the public API.

@@ -314,6 +334,13 @@ private void initEndpointMatchers(ProviderSettings providerSettings) {
OAuth2AuthorizationServerMetadataEndpointFilter.DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI, HttpMethod.GET.name());
this.oidcClientRegistrationEndpointMatcher = new AntPathRequestMatcher(
providerSettings.oidcClientRegistrationEndpoint(), HttpMethod.POST.name());
this.oidcUserInfoEndpointMatcher = new OrRequestMatcher(
new AntPathRequestMatcher(
OidcUserInfoEndpointFilter.DEFAULT_OIDC_USER_INFO_ENDPOINT_URI,
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add a new setting to ProviderSettings called oidcUserInfoEndpoint and use it here. It would default to /userinfo though ProviderSettings does not use constants from anywhere else in the codebase. Change the visibility of this constant in the filter to private.

@@ -384,6 +411,18 @@ private static void validateProviderSettings(ProviderSettings providerSettings)
return jwtCustomizer;
}

private static <B extends HttpSecurityBuilder<B>> UserInfoClaimsMapper getUserInfoClaimsMapper(B builder) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like when resolving conflicts, the code that configures the filter got dropped. See note on review.

After you rebase on main, this should be moved to OAuth2ConfigurerUtils.

private static <B extends HttpSecurityBuilder<B>> UserInfoClaimsMapper getUserInfoClaimsMapper(B builder) {
UserInfoClaimsMapper userInfoClaimsMapper = builder.getSharedObject(UserInfoClaimsMapper.class);
if (userInfoClaimsMapper == null) {
userInfoClaimsMapper = getOptionalBean(builder, UserInfoClaimsMapper.class);
Copy link
Contributor

Choose a reason for hiding this comment

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

Since I suggested reducing the visibility of this class, the user cannot provide a bean of this type. I haven't tested it, but here's a suggested alternative implementation of this method using ResolvableType that would allow a user to provide a bean of type Function<Object, OidcUserInfo>:

	static <B extends HttpSecurityBuilder<B>> Function<Object, OidcUserInfo> getUserInfoClaimsMapper(B builder) {
		OidcUserInfoClaimsMapper userInfoClaimsMapper = builder.getSharedObject(OidcUserInfoClaimsMapper.class);
		if (userInfoClaimsMapper == null) {
			ResolvableType type = ResolvableType.forClassWithGenerics(Function.class, Object.class, OidcUserInfo.class);
			Function<Object, OidcUserInfo> mapperFunction = getOptionalBean(builder, type);
			if (mapperFunction == null) {
				mapperFunction = (principal) -> OidcUserInfo.builder()
						.subject(principal.toString())
						.build();
			}
			userInfoClaimsMapper = new OidcUserInfoClaimsMapper(mapperFunction);
			builder.setSharedObject(OidcUserInfoClaimsMapper.class, userInfoClaimsMapper);
		}
		return userInfoClaimsMapper;
	}


import org.springframework.security.oauth2.core.oidc.OidcUserInfo;

public class DefaultUserInfoClaimsMapper implements UserInfoClaimsMapper {
Copy link
Contributor

Choose a reason for hiding this comment

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

Based on other suggestions, I think you can delete this class.

@sjohnr sjohnr assigned sjohnr and unassigned jgrandja Jul 15, 2021
@sjohnr sjohnr added the status: duplicate A duplicate of another issue label Jul 15, 2021
@jgrandja jgrandja modified the milestones: 0.2.0, 0.2.1 Jul 21, 2021
@sjohnr
Copy link
Contributor

sjohnr commented Sep 17, 2021

Closing in favor of #441

@sjohnr sjohnr closed this Sep 17, 2021
@sjohnr sjohnr added status: declined A suggestion or change that we don't feel we should currently apply and removed status: duplicate A duplicate of another issue type: enhancement A general enhancement labels Sep 17, 2021
@jgrandja jgrandja removed this from the 0.2.1 milestone Sep 17, 2021
@idosal
Copy link
Contributor Author

idosal commented Sep 17, 2021

@sjohnr Damn, I completely missed the review. Sorry about that. Please let me know if there's any way I can contribute.

@sjohnr
Copy link
Contributor

sjohnr commented Sep 17, 2021

@idosal, sorry about that, it's a bummer. Thanks so much for getting it started, it was a great help! Feel free to review #441, since you have invested in this feature already. I'd love to get your feedback on it if you have any thoughts.

@idosal
Copy link
Contributor Author

idosal commented Sep 18, 2021

@sjohnr Thanks, I'm glad it helped. I'll review it ASAP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants