Skip to content

Add AuthorizationManagerFactory #17673

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

sjohnr
Copy link
Contributor

@sjohnr sjohnr commented Aug 8, 2025

This PR is a work in progress. cc: @rwinch

@sjohnr sjohnr force-pushed the gh-17585-authorization-manager-factory branch 4 times, most recently from 4ef91a4 to 1de115e Compare August 13, 2025 15:49
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.

Thanks for the updates @sjohnr! I've provided feedback inline.

@sjohnr
Copy link
Contributor Author

sjohnr commented Aug 19, 2025

@rwinch Thanks for the review! Changing the generic type of MessageSecurityExpressionRoot to Message<T> is a breaking change. Please confirm if that's something we want to do here and I will work on this and the other changes from your review.

@rwinch
Copy link
Member

rwinch commented Aug 19, 2025

@sjohnr

@rwinch Thanks for the review! Changing the generic type of MessageSecurityExpressionRoot to Message<T> is a breaking change. Please confirm if that's something we want to do here and I will work on this and the other changes from your review.

I think that this can work if we update the constructor too. For example:

public class MessageSecurityExpressionRoot<T> extends SecurityExpressionRoot {

	public final Message<T> message;

	public MessageSecurityExpressionRoot(Authentication authentication, Message<T> message) {
	  ...
	public MessageSecurityExpressionRoot(Supplier<Authentication> authentication, Message<T> message) {
	  ...

Then this will compile:

Message<?> message = ...
MessageSecurityExpressionRoot root = new MessageSecurityExpressionRoot<>(authentication, message);

Signed-off-by: Steve Riesenberg <[email protected]>
@sjohnr sjohnr force-pushed the gh-17585-authorization-manager-factory branch from 1de115e to 5fb6f37 Compare August 20, 2025 14:50
@sjohnr
Copy link
Contributor Author

sjohnr commented Aug 20, 2025

@rwinch I've working through the changes and it's looking really good. The only thing I'm noticing is that a few packages are missing nullability defaults.

  • org.springframework.security.web.access.expression has a package-info.java but no @NullMarked. Is this intended or perhaps it should be addressed separately?
  • org.springframework.security.messaging.access.expression is missing package-info.java along with all the other packages in spring-security-messaging.

As it stands now, classes in these packages show as having inconsistent nullability. These show up as IntelliJ inspections for me, similar to our conversation a few weeks ago. I think adding @NullMarked at the package level will address this, but if omitting that was intentional, let me know. I've added @NullMarked at the class level to show where these issues are but I will revert that after you review.

@sjohnr sjohnr requested a review from rwinch August 20, 2025 15:04
@sjohnr sjohnr marked this pull request as ready for review August 20, 2025 17:58
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.

This is looking great @sjohnr!

I think we are very close 😄 I provided a few minor comments inline.

Now that we are almost done, please also add documentation (using include-code).

After those are addressed, I think we will be ready to merge!

* authentication.
* @return the {@link AuthenticationTrustResolver}
*/
public AuthenticationTrustResolver getTrustResolver() {
Copy link
Member

Choose a reason for hiding this comment

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

Rather than exposing a getter here, I'd prefer that DefaultMethodSecurityExpressionHandler keep a copy of the TrustResolver and return that.

public class DefaultMethodSecurityExpressionHandler .... {
    ...
    public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
        this.trustResolver = trustResolver;
        getDefaultMethodSecurityExpressionHandler().setTrustResolver(trustResolver);
    }

    public AuthenticationTrustResolver getTrustResolver() {
        return this.trustResolver;
    }
}

The rational is twofold:

  1. As we've seen in places like DefaultMethodSecurityExpressionHandler, exposing getters unnecessarily makes refactoring more difficult

  2. The trustResolver property is deprecated and so we only need to keep the copy around until it is removed. When we remove it, I don't want to be stuck with a getter on DefaultAuthorizationManagerFactory that we only created for a deprecated property.

* Returns the {@link RoleHierarchy} used to discover reachable authorities.
* @return the {@link RoleHierarchy}
*/
public RoleHierarchy getRoleHierarchy() {
Copy link
Member

Choose a reason for hiding this comment

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

Similar to trustResolver, I'd prefer to remove this getter and keep a copy of RoleHiearchy in the classes that need access to it.

* Returns the prefix used to create an authority name from a role name.
* @return the role prefix
*/
public String getRolePrefix() {
Copy link
Member

Choose a reason for hiding this comment

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

Similar to trustResolver, I'd prefer to remove this getter and keep a copy of rolePrefix in the classes that need access to it.

@@ -36,6 +36,7 @@
<suppress files="JoseHeader\.java" checks="SpringMethodVisibility"/>
<suppress files="DefaultLoginPageGeneratingFilterTests\.java" checks="SpringLeadingWhitespace"/>
<suppress files="AuthenticationException\.java" checks="MutableException"/>
<suppress files="FilterInvocationExpressionRoot\.java" checks="SpringMethodVisibility|RedundantModifier"/>
Copy link
Member

Choose a reason for hiding this comment

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

I think that if you make the constructor for FilterInvocationExpressionRoot package-private, then you can remove RedundantModifier.

* @author Steve Riesenberg
* @since 7.0
*/
final class FilterInvocationExpressionRoot extends SecurityExpressionRoot<FilterInvocation> {
Copy link
Member

Choose a reason for hiding this comment

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

I think that this makes more sense to be called HttpServletRequestExpressionRoot rather than FilterInvocationExpressionRoot (I know I proposed using FilterInvocationExpressionRoot, but seeing it shows me that it doesn't make sense - sorry about that!). It would then accept just the HttpServletRequest instance.

/**
* @author Steve Riesenberg
* @since 7.0
*/
Copy link
Member

Choose a reason for hiding this comment

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

FYI As per this comment I created gh-17781

@rwinch
Copy link
Member

rwinch commented Aug 20, 2025

We've only added nullability for crypto and core so feel free to leave as is. We'll get the rest of the module in a different ticket commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants