Skip to content

Expose getter for nameAttributeKey in OAuth2AuthenticatedPrincipal #16003

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

Conversation

andreblanke
Copy link

Given a DefaultOidcUser or DefaultOAuth2User, it is currently not possible to create a faithful copy of the instance since the constructors require a nameAttributeKey for the all-arg constructor:

public DefaultOidcUser(Collection<? extends GrantedAuthority> authorities, OidcIdToken idToken,
		String nameAttributeKey)
public DefaultOAuth2User(Collection<? extends GrantedAuthority> authorities, Map<String, Object> attributes,
		String nameAttributeKey)

which is not accessible.

This issue has been mentioned before in #14461 (comment) where a custom ExtendedOidcUser decorator class is used to work around it. While that works, I feel that this should be possible without introducing a separate class using just the public API.

The PR aims to change this by adding the OAuth2AuthenticatedPrincipal.getNameAttributeKey method in 464b078. This is a breaking change for classes implementing the interface.

With the nameAttributeKey now available from within the interface, I figured it also makes sense to provide a default implementation for OAuth2AuthenticatedPrincipal.getName in c7bcf86.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Oct 26, 2024
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.

Thanks, @andreblanke! I've left some feedback inline.

@jzheaux jzheaux self-assigned this Nov 1, 2024
@jzheaux jzheaux added type: enhancement A general enhancement 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 Nov 1, 2024
@jzheaux
Copy link
Contributor

jzheaux commented Nov 21, 2024

Hi, @andreblanke! Are you able to make the requested changes? No rush, if I don't hear from you in about a week, I'm happy to make the changes myself.

@jzheaux jzheaux added this to the 6.5.x milestone Nov 21, 2024
@andreblanke andreblanke force-pushed the oauth2-name-attribute-key branch 2 times, most recently from c92a4a0 to 25f8bec Compare November 24, 2024 16:39
@andreblanke
Copy link
Author

Hi there @jzheaux. First of all thank you for your feedback. Sorry, I've been postponing this. I'd like to finish the changes in the next few days once we've decided on an implementation (getter for nameAttributeKey vs. new constructors).

@andreblanke andreblanke force-pushed the oauth2-name-attribute-key branch from 4848c6b to 6b815d2 Compare December 8, 2024 11:19
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.

Thanks for the updates, @andreblanke! I've left some feedback inilne.

@andreblanke andreblanke force-pushed the oauth2-name-attribute-key branch 2 times, most recently from ad945b6 to ced9228 Compare December 15, 2024 22:58
@jzheaux
Copy link
Contributor

jzheaux commented Jan 27, 2025

Hi, @andreblanke. Thanks for doing all this research with me, I appreciate your contributions. At this point, I think it's pretty clear that this approach is too complex to address your much simpler concern. I think deprecation will need to wait for another time.

Can you confirm that this is what you are effectively needing:

DefaultOAuth2User user = new DefaultOAuth2User(...);
DefaultOAuth2User copy = // ... copy the values somehow
assert user.equals(copy);
assert user != copy;

If so, I think we can do something much simpler, which is add a copy constructor to each class:

DefaultOAuth2User user = new DefaultOAuth2User(...);
DefaultOAuth2User copy = new DefaultOAuth2User(user);
assert user.equals(copy);
assert user != copy;

// ... same for DefaultOidcUser

If you can confirm that this would work, I will push a change along these lines and have you review it. If not, please feel free to explain more of your use case so we can find a better fit together.

@jzheaux jzheaux added the status: waiting-for-feedback We need additional information before we can continue label Jan 27, 2025
@andreblanke
Copy link
Author

Hi @jzheaux. First of all thank your for your guidance so far. Sorry the PR has been dragging on for a while now. I agree that the current approach is too complex and the scope of the PR has grown quite a bit from my original submission.

Unfortunately a copy constructor wouldn't be sufficient for my use case. My original requirement (which I should've maybe mentioned to avoid the XY problem) was to add a new GrantedAuthority to an OidcUser.

Since DefaultOAuth2User.authorities is unmodifiable, re-creating the OidcUser using

new DefaultOidcUser(newMappedAuthorities, originalUser.idToken, originalUser.userInfo)

and replacing the principal where it's used is the only option. However, the new DefaultOidcUser isn't an exact copy since its nameAttributeKey is IdTokenClaimNames.SUB as opposed to whatever it was for `originalUser.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 11, 2025
@jzheaux jzheaux force-pushed the oauth2-name-attribute-key branch from ced9228 to 5cd6227 Compare February 13, 2025 23:03
jzheaux added a commit to andreblanke/spring-security that referenced this pull request Feb 13, 2025
@jzheaux jzheaux force-pushed the oauth2-name-attribute-key branch from 5cd6227 to 798e9b4 Compare February 13, 2025 23:35
@jzheaux
Copy link
Contributor

jzheaux commented Feb 13, 2025

Gotcha, @andreblanke, that makes sense.

Given that you need to add more authorities, could you do something like the following:

OidcUserService userService = new OidcUserService();
userService.setOidcUserMapper((request, info) -> {
	List<GrantedAuthority> authorities = request.getAccessToken().getScopes()
		.stream().map(SimpleGrantedAuthority::new).toList();
	authorities.add(your custom authority);
	return new DefaultOidcUser(authorities, request.getIdToken(), info);
});

@jzheaux jzheaux added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Feb 20, 2025
@jzheaux
Copy link
Contributor

jzheaux commented Mar 26, 2025

I'm going to close this PR at this point, @andreblanke. Thanks for your efforts, and please don't hesitate to reach out if the above snippet doesn't address your concern.

@jzheaux jzheaux closed this Mar 26, 2025
@jzheaux jzheaux added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-feedback We need additional information before we can continue labels Mar 26, 2025
@jzheaux jzheaux removed this from the 6.5.x milestone Apr 9, 2025
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: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants