Oceanic
Oceanic

Reputation: 1458

Authorization in spring-security based on path variables

My use case is to authenticate & then authorize users based on @PathVariable parameters. I need to execute some custom code to authorize the principal. I'm not sure of the approach to take here -

  1. I have implemented a custom AbstractAuthenticationProcessingFilter & AuthenticationProvider for authentication, which ends up granting roles to the principal. I can inspect the pathvariables in the servlet request (using HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE), and add additional authorities to the Authentication token. Then I can use the built-in hasRole, hasPermission expressions to implement access control.

  2. I can extend WebSecurityExpressionRoot and implement a custom AbstractSecurityExpressionHandler and define my own expressions to be used in the intercept-url access-control expressions. I'm not sure how I can access the @PathVariables when defining custom methods in my WebSecurityExpressionRoot implementation.

Which approach is preferable, or is there another way to do this cleanly?

Upvotes: 8

Views: 14022

Answers (3)

Nisha Saini
Nisha Saini

Reputation: 1

("/your-end-point/{yourReferenceId}/**")

Upvotes: 0

HYisen
HYisen

Reputation: 121

I do have a solution. In a configuration class

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter

I could have method

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/student/{id}/**")
            .access("@guard.checkUserId(authentication,#id)");
}

while @guard in SpEL links to

@Component
public class Guard {
    @Autowired
    private UserRepository repo;

    public boolean checkUserId(Authentication authentication, int id) {
        String name = authentication.getName();
        System.out.println(name+" at "+id);
        User result = repo.findByUsername(name);
        return result != null && result.getPid() == id;
    }
}

In practice, the #id in SpEL can get the value extracted from {id} in the previous line. You can do whatever you want in checkUserId, and the return value decides whether the access to the path would be allowed.

Upvotes: 12

Sanjay
Sanjay

Reputation: 8955

A way I could imagine for this would be to capture the path variable in a parameter, using method level authorization, and then using hasPermission. This answer has details about how to do it exactly - in case it would help.

Upvotes: 1

Related Questions