Skip to content

Some enhancement suggestions for new Authorization architecture classes for customizing the authorization logic #11024

@fatihdogmus

Description

@fatihdogmus

Hello,

I was trying to extend the current pre authorization behavior to suit our needs. Basically I wanted to look at the request headers, if some conditions are met, execute a custom authorization code and grant access from that logic, otherwise delegate to default pre authorize authorization manager.

But this was very hard to understand and do.

In the documents, for customizing the @PreAuthorize authorization logic, it is said to be done like this:

image

But this only shows how to replicate the default behavior, not how to customize it.

As I set to do customize my logic and add a custom AuthorizationManager, I was faced with these challanges:

  1. AuthorizationManagerBeforeMethodInterceptor doesn't have a factory function or constructor that just accepts an AuthorizationManager and can only be instantiated with a default authorization managers(Yes it has one that accepts an AuthorizationManager, but it also needs a pointcut, which I will come back later)
  2. Since I saw that, I wanted to create a custom class that extended PreAuthorizeAuthorizationManager. In here, I wanted to execute some logic or delegate to super in other cases. But I saw that PreAuthorizeAuthorizationManager, or any other concrete implementation of AuthorizationManager, are marked as final and can't be extended to customize the logic and be provided to AuthorizationManagerBeforeMethodInterceptor.
  3. Event if you write a custom AuthorizationManager that executes your logic or delegates to constructed PreAuthorizeAuthorizationManager in other cases, you need to provide a Pointcut to pass to interceptor. Unfortunately, the utility class used to get the Pointcuts for @PreAuthorize annotation(AuthorizationMethodPointcuts) is package private and you can't easily create the pointcut that you need.

Because of that, I had to create a default AuthorizationManagerBeforeMethodInterceptor, get its Pointcut, than create my own custom interceptor with this pointcut and my custom delegating AuthorizationManger.

Here is the code that I had to write:

image

And this is the custom AuthorizationManager:

image

The code is very small, but in order to get there, I had to fumble through a lot of source code.

There were a lot of pain points while trying to figure out how to do some basic thing.

Here our my suggestions:

  1. Make the concrete implementations of AuthorizationManager non-final, so that we can extend them and customize it with our logic, or make them more composeable.
  2. Add a builder or constructor to AuthorizationManagerBeforeMethodInterceptor to only get an AuthorizationManager to be used inside, and not bother with pointcuts and use the default one, as it is the case with factory function that takes a PreAuthorizeAuthorizationManager.
  3. Add a section on how to create your own AuthorizationManager and register it as default for one or more of the interceptors that come with @EnableMethodSecurity, ideally showing how to delegate to default managers.

I don't know if I over-complicated things with my limited knowledge of the new authorization architecture, but in other parts of the spring security, by just reading the source code and understanding the default behavior, I could extend or compose the existing classes with my own to suit my needs. But this was not that easy to do with the current authorization classes.

Thank you.

Metadata

Metadata

Assignees

Labels

in: coreAn issue in spring-security-corestatus: declinedA suggestion or change that we don't feel we should currently apply

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions