Search code examples
javaspringspring-securitypostman

Basic Auth in Postman


I started to deal with spring security and there was such a problem. That in the browser, get and delete requests can be performed by logging in, but the save method cannot (because a body is needed). I use postman for save, but even after filling in the basic auth data, I still get the authorization page.

Maybe I didn't set up the security config file correctly?

Here is the controller:

@RestController
@RequestMapping("/product")
@Slf4j
public class ProductController {

    private final ProductRepository productRepository;

    @Autowired
    public ProductController(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }

    @GetMapping("/products")
    public List<Product> getAllProducts() {
        log.info("Receiving all products");
        return productRepository.findAll();
    }

    @GetMapping("/getProduct/{id}")
    public Product getProductById(@PathVariable Long id) {
        log.info("Receiving product by id");
        return productRepository.getReferenceById(id);
    }

    @PostMapping("/save")
    public Product saveProduct(@RequestBody Product product) {
        log.info("Save products");
        return productRepository.save(product);
    }

    @DeleteMapping("/remove/{id}")
    public void deleteProduct(@PathVariable Long id) {
        Product product = productRepository.getReferenceById(id);
        log.info("delete product by id");
        if (product != null) {
            productRepository.delete(product);
        }
    }
}

Here is the security config:

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        UserDetails user = User.builder()
                .username("user")
                .password(passwordEncoder().encode("user1Pass"))
                .roles(UserRole.USER.name())
                .build();
        UserDetails admin = User.builder()
                .username("admin")
                .password(passwordEncoder().encode("admin1Pass"))
                .roles(UserRole.USER.name())
                .build();
        return new InMemoryUserDetailsManager(user, admin);
    }
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((authz) -> authz
                        .requestMatchers("/product/save").hasRole(UserRole.ADMIN.name())
                        .requestMatchers("/product/remove/**").hasRole(UserRole.ADMIN.name())
                        .requestMatchers("/product/products").hasAnyRole(UserRole.ADMIN.name(), UserRole.USER.name())
                        .requestMatchers("/product/getProduct/{id}").permitAll()
                        .requestMatchers("/product").permitAll()
                        .anyRequest().authenticated()

                ).formLogin(withDefaults());
        return http.build();
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

Here is authorization and basic auth in postman:

enter image description here

I tried adding .httpBasic(Customizer.withDefaults()) and in the end all methods work with basic auth, but the post(save in my case) method gives an empty string and a 401 error.


Solution

  • Please try this. I mean to remember that I had the same challenge. And remove .formLogin(withDefaults());.

    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((authz) -> authz
                // your definitions
        );
        http.httpBasic(); // <<--
        http.csrf().disable(); // <<--
        return http.build();
    
    }