Anjana
Anjana

Reputation: 426

Securing controllers with @Preauthorize annotation doesn't work

I'm trying to secure the endpoints using Spring Security. But the code doesn't seem to work. Not sure where I'm going wrong.

My Security Class

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true,proxyTargetClass = true)
open class WebSecurity : WebSecurityConfigurerAdapter() {
    @Throws(Exception::class)
    override fun configure(http: HttpSecurity) {
        http.httpBasic()
                .and()
                .cors().and()
                .csrf().disable().authorizeRequests()
                .antMatchers("/authorize/users/*").permitAll()
                .anyRequest().authenticated().hasRole("MANAGER")
                .and()
                .formLogin()
    }

    @Bean
    public override fun userDetailsService(): UserDetailsService {

        //User Role
        val theUser = User.withUsername("sergey")
                .passwordEncoder { charSequence: String? -> PasswordEncoderFactories.createDelegatingPasswordEncoder().encode(charSequence) }
                .password("12345678").roles("USER").build()

        //Manager Role
        val theManager = User.withUsername("john")
                .password("87654321").roles("MANAGER").build()
        val userDetailsManager = InMemoryUserDetailsManager()
        userDetailsManager.createUser(theUser)
        userDetailsManager.createUser(theManager)
        return userDetailsManager
    }
}

Controller

 @RestController
    @RequestMapping("/authorize")
    open class AuthController {

   @PreAuthorize("hasRole('MANAGER')")
        @PostMapping("/users/add")
        fun createUsers(@RequestHeader("Authorization") token: String,
                             @RequestBody users: UserDTO) : ResponseEntity<Any> {
            lateinit var message: String
            try {
    
                val response = authService.insert(users, token)     
    
            }
            catch (exception: RuntimeException) {
                return ResponseEntity(exception.message, HttpStatus.INTERNAL_SERVER_ERROR)
            }
        }
    
        }

In Postman I've set the Basic Auth. Still getting 401 unauthorized

enter image description here

Upvotes: 1

Views: 556

Answers (1)

jzheaux
jzheaux

Reputation: 7752

401 Unauthorized is associated with the credentials not being recognized or present.

I believe the problem is here:

val theManager = User.withUsername("john")
        .password("87654321").roles("MANAGER").build()

Without an encoding prefix, Spring Security is likely erroring when performing the password comparison.

Instead, do

val theManager = User.withUsername("john")
        .password("{noop}87654321").roles("MANAGER").build()

The {noop} hint tells Spring Security that this password is unhashed.

Debugging Tips

If that doesn't repair the problem, consider adding antMatchers("/error").permitAll() to your list of authorized requests and possibly simplifying the stack to:

.authorizeRequests()
    .antMatchers("/error").permitAll()
    .anyRequest().authenticated()

This won't fix it, but opening up the /error endpoint may provide additional debug information for you.

Upvotes: 2

Related Questions