Search code examples
javaspringspring-bootspring-securityrbac

Allow a specific role to access a limited set of URI but let the remaining roles to access to all URI


I'm facing a problem in authorizing a user with role ROLE_CUSTOMER to access just to these set of URI as listed below:

POST /api/v1/beneficiaries/check 
GET /api/v1/accounts/{accountId}/beneficiary-accounts  
GET /api/v1/accounts/{idAccount} 
GET /api/v1/cards/{cardId}
PUT /api/v1/cards/{cardId}/deactivate

but not for the remaining URI

and allow the other users with roles (ROLE_API, ROLE_USER) to access all URI, they should be just authenticated.

How I can achieve that just with antMatchers config.

I have tried for several times with the below config:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .antMatchers("/api/v1/api-docs/**").permitAll()
                .antMatchers("/api/v1/api-docs**").permitAll()
                .antMatchers("/api/v1/auth").permitAll()
                .antMatchers("/api/v1/auth-dejamobile").permitAll()
                .antMatchers("/api/v1/hc").permitAll()
                .antMatchers("/api/v1/dictionaries/**").permitAll()
                .and()
                .authorizeRequests()
                .antMatchers(HttpMethod.POST, "/api/v1/beneficiaries/check").hasRole("CUSTOMER")
                .antMatchers("/api/v1/accounts/*/beneficiary-accounts").hasRole("CUSTOMER")
                .antMatchers("/api/v1/accounts/*").hasRole("CUSTOMER")
                .antMatchers("/api/v1/cards/*").hasRole("CUSTOMER")
                .antMatchers(HttpMethod.PUT,"/api/v1/cards/*/deactivate").hasRole("CUSTOMER")
                .and()
                .authorizeRequests()
                .antMatchers("/**").not().hasRole("CUSTOMER")
                .anyRequest().authenticated();


        http
        .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
    }

but the ROLE_API and ROLE_USER haven't access to the five URI as described above, and ROLE_CUSTOMER hasn't access to PUT /api/v1/cards/{cardId}/deactivate !!

Any help is very appreciated.


Solution

  • When writing Spring Security matching rules the order of the rules matter as the order in which they are defined is also the order in which they are consulted!. So .antMatchers("/api/v1/cards/*").hasRole("CUSTOMER") also applies to the PUT one (below this one) already.

    Next it your security rule is "allow access to all authenticated users or hasRole Customer" then write that rule. Use something like access("hasRole('CUSTOMER') or isAuthenticated()). Although this rule is a bit weird as only isAuthenticated would do the trick as well in this specific case.