M Nouman
M Nouman

Reputation: 591

401 unauthorized when using spring security BCrypt in Spring Boot JPA

I'm trying to implement Bcrypt to hash passwords. But the issue I'm facing is that Spring Security enables authentication for all end points by default. But I don't want that I just want to signup a user and simply generate hash for the passwords. But I can't do that as when I make a Post request from Postman it shows 401 Unauthorized.4

I tried the following things in main class:

1-

@EnableWebSecurity

2-

@EnableAutoConfiguration

3-

@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})

4-

@Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.cors(); 
        return http.build();
    }

5-

I tried with org.mindrot:jbcrypt:0.4 but when I try to use BCrypt in my service function it does not import it from mindrot

I want to use spring security for Authentication and Authorization in future, But First I need to sign up a user and hash his password.

build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.0.1'
    id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '19'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    runtimeOnly 'com.mysql:mysql-connector-j'
    annotationProcessor 'org.projectlombok:lombok'
    implementation 'org.mindrot:jbcrypt:0.4'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

main class

package com.example.bcrypt;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class BcryptApplication {

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

}

UserRepo

package com.example.bcrypt.repository.dao;

import org.springframework.data.jpa.repository.JpaRepository;

import com.example.bcrypt.entity.User;

public interface UserRepository extends JpaRepository<User,Integer>{
    
}

UserService

package com.example.bcrypt.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import com.example.bcrypt.entity.User;
import com.example.bcrypt.repository.dao.UserRepository;


@Service
public class UserService {
    @Autowired
    private UserRepository userRepo;

    public User create(User body){

        BCryptPasswordEncoder bcrypt=new BCryptPasswordEncoder();

        String hashedpassword=bcrypt.encode(body.getPassword());

        body.setPassword(hashedpassword);

        User res=userRepo.save(body);

        System.out.println(res);

        return res;
    }
    
}

UserControlelr

package com.example.bcrypt.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.bcrypt.entity.User;
import com.example.bcrypt.service.UserService;

@RestController()
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping("/register")
    public User create(@RequestBody User body){
        User res=userService.create(body);

        System.out.println(res);

        return res;
    }
}

Upvotes: 0

Views: 1694

Answers (1)

Flavius Condurache
Flavius Condurache

Reputation: 303

Your request fails because of spring security. You can add exceptions or disable it completely by providing a simple @Bean.

@Bean
public SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http) {
  return http
    .csrf()
    .disable()
    .authorizeExchange(authorizeExchangeSpec -> authorizeExchangeSpec.anyExchange().permitAll())
    .build();
}

I count'tell from your code what endpoint you're calling so in the example above I've allowed any request. Note that you should not do that in production environments.

Edit:

I'm sorry, I gave you a bean for webflux.

You should be able to use this bean instead and have it all working. I usually create a configuration class ex:

SecurityConfig.java

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http.cors().disable()
                .csrf().disable()
                .authorizeHttpRequests().requestMatchers("/users/register").permitAll().and()
                .build();
    }
}

Upvotes: 3

Related Questions