1

I`m trying to use spring security oauth2 to do authority access controll with annotations like @PreAuthorize("hasAuthority('perm2')") or with security config in WebSecurityConfigurerAdapter.But I always get 403 forbiden when I try to access an api annotated by @PreAuthorize("hasAuthority('perm2')") after I login by a user that has 'perm2' authority .I set breakpoint in ClientDetailsUserDetailsService but the loaded UserDetails did not contain any authority.What is more,I found that I could extract authorities contain 'perm2' from AuthoritiesExtractor.
One way to do this is rewriting the UserDetailService so that I could set authorities to UserDetails by AuthoritiesExtractor. But my question is:

Is it a best practice? or am I just missing something else?

My tried code is below,followed by baeldung tutorial

my authserver code is here

@SpringBootApplication
@EnableResourceServer
@RestController
public class App extends SpringBootServletInitializer {


    @GetMapping("/user/me")
    public Principal user(Principal principal) {
        return principal;
    }


    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }


    @Configuration
    @EnableAuthorizationServer
    public static class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
        @Autowired
        private BCryptPasswordEncoder passwordEncoder;

        @Override
        public void configure(
                AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
            oauthServer.tokenKeyAccess("permitAll()")
                    .checkTokenAccess("isAuthenticated()");
        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory()
                    .withClient("SampleClientId")
                    .secret(passwordEncoder.encode("secret"))
                    .authorizedGrantTypes("authorization_code")
                    .scopes("user_info")
                    .autoApprove(true)
                    .redirectUris("http://localhost:8082/ui/login", "http://localhost:8083/ui2/login");
        }
    }

    @Configuration
    @Order(1)
    public static class SecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.requestMatchers()
                    .antMatchers("/login", "/oauth/authorize")
                    .and()
                    .authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                    .formLogin().permitAll();
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                    .withUser("john")
                    .password(passwordEncoder().encode("123"))
                    .roles("USER").authorities("perm1").and()
                    .withUser("tom")
                    .password(passwordEncoder().encode("123"))
                    .roles("USER")
                    .authorities("perm1", "perm2");
        }

        @Bean
        public BCryptPasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    }

my client configuration is here:

@Configuration
@EnableOAuth2Sso
@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled =true)
public class App extends WebSecurityConfigurerAdapter {

    @Bean
    AuthoritiesExtractor authoritiesExtractor(){
        return new FixedAuthoritiesExtractor();
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**")
                .authorizeRequests()
                .antMatchers("/", "/login**")
                .permitAll()
                .anyRequest()
                .hasAuthority("perm1").anyRequest()
                .authenticated();
    }

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

and this is my controller:

@Controller
public class MyController {

    @GetMapping("/securedPage")
    @PreAuthorize("hasAuthority('perm2')")
    public String securedPage() {
        return  "securedPage";
    }

    @GetMapping("/testPerm")
    @PreAuthorize("hasAuthority('perm3')")
    public @ResponseBody
    String testPerm() {
        return  "This could not be happened!";
    }
}

What I expect is :
when I login with john,I got forbidden when I access securedPage.
But when I login with tom,I could acess securedPage.

The fact is whoever I login,I get forbidden page below

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Fri May 24 11:29:09 CST 2019
There was an unexpected error (type=Forbidden, status=403).
Forbidden
Doug Tea
  • 19
  • 2
  • You'll need to show the actual JSON returned by your authorization server when this application retrieves token contents. (Additionally, you're mixing *tons* of concerns--you have duplicate launcher declarations, security definitions are spread everywhere, and `SpringBootServletInitializer` is for legacy war-based projects.) – chrylis -cautiouslyoptimistic- May 24 '19 at 05:10
  • @chrylis-cautiouslyoptimistic- that`s right.Thank you and sorry for late rely. – Doug Tea Dec 25 '20 at 11:26

0 Answers0