Spring Security - Basic Authentication

. . 6 min read

display

This guide walks you through the process of building a Spring boot application that uses Spring Security and Spring Data JPA. Applying the new way to configure Spring Security without the WebSecurityConfigurerAdapter

What You Will build

You will build a Spring Boot application with Spring Security basic authentication and Spring Data Jpa for managing the users.

What You Need

  • A favorite text editor or IDE
  • JDK 1.8 or later
  • Gradle 4+ or Maven 3.2+

Setup Project With Spring Initializr

  • Navigate to Spring initializr.

  • Define the project name example: spring-boot-security-basic-auth

  • Choose Project Maven and the language Java.

  • Choose Your Java version ex: 17

  • Click add dependencies and select:

    • Spring Web
    • Spring Security
    • Spring Data JPA
    • H2 Database
    • Lombok
  • Click Generate.

Unzip the Downloaded Zip and open the Project using your favorite text editor or IDE

Start the implementation

Define the User Entity, implement the UserDetails interface and override the implemented methods

@Entity(name = "users")
@Getter
@Setter
public class User implements UserDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String firstName;

    private String lastName;

    @Column(unique = true)
    private String username;

    private String password;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return Collections.emptyList();
    }

    @Override
    public String getPassword() {
        return this.password;
    }

    @Override
    public String getUsername() {
        return this.username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

}

Define the User Repository and the query method findOneByUsername

Lean more about query methods here

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    Optional<User> findOneByUsername(String username);
}

Define the User Details Service implementation that will manage user authentication.

public class CustomUserDetailsService implements UserDetailsService {

    private UserRepository userRepository;

    public CustomUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userRepository.findOneByUsername(username).orElseThrow(() -> {
            throw new UsernameNotFoundException(username);
        });
    }

}

Define the Spring Security Configuration, You will notice that we didn't extend the WebSecurityConfigurerAdapter we just define beans at this level

@Configuration
public class SecurityConfiguration {

    /**
     * Define the password encoder.
     * 
     * @return {@link BCryptPasswordEncoder}
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * Define the user service to retrieve and authenticate the user.
     * 
     * @param userRepository
     * @return {@link UserDetails}
     */
    @Bean
    CustomUserDetailsService customUserDetailsService(UserRepository userRepository) {
        return new CustomUserDetailsService(userRepository);
    }

    /**
     * Define the filer chain.
     * 
     * @param http
     * @return {@link SecurityFilterChain}
     * @throws Exception
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(
                (authz) -> authz.antMatchers("/secured").authenticated().anyRequest().permitAll())
                .httpBasic();
        return http.build();
    }

}

Define the Rest Controller with some routes

@RestController
public class AppResource {

    @GetMapping("/**")
    public String any() {
        return "Hello World";
    }

    @GetMapping("/secured")
    public String secured(Authentication auth) {
        User user = ((User) auth.getPrincipal());
        return "Hello " + user.getFirstName() + " " + user.getLastName();
    }

}

Create data.sql under the resources folder to populate our table

INSERT INTO USERS (FIRST_NAME, LAST_NAME, USERNAME, PASSWORD) VALUES
                              -- password is '123'
    ('john', 'doe', 'admin', '$2a$12$vl2OJQMtIZutojuJVhaRXuLmkyFV1QgE24HqFPWoYTmPOXa6wOUbi');

When running the application, by default the data.sql will be executed before the entity creation into the database, to prevent that add the following property under the application.properties

spring.jpa.defer-datasource-initialization=true

Testing

Write some test cases to check that the uri /secured is working as expected

  • Test 1 : check with correct credentials
  • Test 2 : check with wrong credentials
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SpringBootSecurityBasicAuthApplicationTests {

	private final String USERNAME = "admin";
	private final String PASSWORD = "123";
	private final String WRONG_PASSWORD = "bvfsdg";

	@Autowired
	TestRestTemplate template;

	@Test
	public void accessPrivateResourceSuccess() throws Exception {
		ResponseEntity<String> response = template.withBasicAuth(USERNAME, PASSWORD)
				.getForEntity("/secured", String.class);

		assertEquals(HttpStatus.OK, response.getStatusCode());
	}

	@Test
	public void accessPrivateResourceFaildGivingWrongPassword() throws Exception {
		ResponseEntity<String> response = template.withBasicAuth(USERNAME, WRONG_PASSWORD)
				.getForEntity("/secured", String.class);

		assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode());
	}

}

Run The Application

Run the Java application as a SpringBootApplication with your IDE or use the following command line

 ./mvnw spring-boot:run

Now, you can open the URL below on your browser, default port is 8080 you can set it under the application.properties

http://localhost:8080/

When you access the secured URI /secured, a prompt shows up pass in the username & password

  • username : admin
  • password : 123
http://localhost:8080/secured

Summary

Congratulations 🎉 ! You've created a Spring Security application with basic authentication using Spring Boot & Spring Data JPA

Github

The tutorial can be found here on GitHub 👋

Blog

Check new tutorials on nonestack 👋

15
923

Recent articles

Spring Authorization Server - OAuth JWT

spring authorize server

This guide walks you through the process of building a Spring Boot Authorization Server JWT that uses Spring Security Security and Spring Security OAuth Resource. Applying the new way to configure Spring Authorization Server JWT without the Custom Filter

Continue reading
9 min read
.
1115 views

Spring Data - JPA DataTable

spring data

This guide walks you through the process of building a Spring boot application that uses JPA DataTable.

Continue reading
10 min read
.
853 views

Spring Web - Rest Client

spring boot

Spring Framework introduces RestClient a new Fluent API to make synchronous HTTP requests

Continue reading
4 min read
.
1071 views

Spring Boot - Get Started

spring boot

Spring Boot is a popular framework that simplifies and accelerate the process of developing a java based application

Continue reading
5 min read
.
874 views