Securing Spring MVC REST endpoint using Basic Auth

Carvia Tech | April 07, 2019 | 3 min read | 96 views | Spring Boot 2


In this tutorial we will create a simple Spring Boot 2.1.x based REST API that is secured by Basic Authentication, User details are stored in-memory.

Download the source code

You can download the entire source of this project from github:
https://github.com/cancerian0684/tutorial-basic-auth-server

Perquisites

  1. Java 8

  2. IDE like IntelliJ IDEA or Eclipse

  3. Gradle

  4. Spring Boot 2.x

  5. curl or POSTMAN for testing REST API

Using Spring Initializer for project template

We can head over to Spring Initializer at https://start.spring.io/ and create a project template with below configuration.

spring initializer basic auth
Spring initializer for project template

Import project into favorite IDE

We can import the project structure created in above step inot IntelliJ IDEA and start implementing the rest of important stuff.

Build file contains the required dependencies: kotlin, spring boot start web and starter security.

/build.gradle
buildscript {
	ext.kotlin_version = '1.3.21'
	repositories {
		mavenCentral()
	}
	dependencies {
		classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
		classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlin_version}")
		classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlin_version}")
	}
}

... rest of the stuff

dependencies {
	compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
	compile('com.fasterxml.jackson.module:jackson-module-kotlin')
	compile('org.jetbrains.kotlin:kotlin-reflect')

	compile 'org.springframework.boot:spring-boot-starter-security'
	compile 'org.springframework.boot:spring-boot-starter-web'
}

App entry point

We need to create an app entry point that we can run to start the application.

BasicAuthApp.java
@SpringBootApplication
public class BasicAuthApp {

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

}

Create REST endpoint

Lets create a REST endpoint using Spring MVC.

HelloController.kt
@RestController
class HelloController {

    @GetMapping("/api/health")
    fun hello(): Health {
        return Health.UP
    }

}

data class Health(val status: String) {
    companion object {
        val UP = Health("UP")
    }
}

This endpoint simply returns hardcoded health indicators.

Securing the endpoint using Spring Security

Now finally we will secure the endpoint using Basic Auth.

WebSecurityConfiguration.kt
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
class WebSecurityConfiguration : WebSecurityConfigurerAdapter() {

    @Bean
    fun passwordEncoder(): PasswordEncoder {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder()   (1)
    }

    @Bean
    @Throws(Exception::class)
    override fun authenticationManagerBean(): AuthenticationManager {
        return super.authenticationManagerBean()
    }

    @Throws(Exception::class)
    override fun configure(http: HttpSecurity) {
        http.httpBasic()
                .and()
                .csrf().disable().headers().frameOptions().disable()
                .and()
                .exceptionHandling()
                .authenticationEntryPoint { _, httpServletResponse, e -> httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED) }
                .and()
                .authorizeRequests()
                .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
                .antMatchers(HttpMethod.POST, "/login", "/register").permitAll()
                .antMatchers("/api/**").authenticated() (2)
                .anyRequest().authenticated()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    }

    @Throws(Exception::class)
    override fun configure(auth: AuthenticationManagerBuilder) {
        auth.inMemoryAuthentication()   (3)
                .withUser("user1")
                .password("{noop}password")
                .authorities("USER")
                .and()
                .withUser("user2")
                .password("{noop}admin")
                .authorities("ADMIN")
    }
}
1 We are creating a passwordEncoder bean that uses appropriate algorithm to decode/encode a given raw password.
2 We configure Spring Security to protect /api/** endpoint so that only authenticated requests are allowed.
3 We are creating in memory user pool with given plain text credentials and authorities.

Start the server

We can start the server using gradle command line:

Starting the server
$ ./gradlew bootRun

this command will start the server at default port 8080.

Test the endpoint

We can use curl to test the API endpoints.

Curl request without credentials
$ curl -i -X GET http://localhost:8080/api/health
Response
HTTP/1.1 401
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 07 Apr 2019 14:50:20 GMT
{
    "timestamp": "2019-04-07T14:51:55.207+0000",
    "status": 401,
    "error": "Unauthorized",
    "message": "No message available",
    "path": "/api/hello"
}

We can see that server returns 401 response code when we hit it without passing the basic auth credentials.

Now lets pass on the credentials and try it again:

Request with Basic Auth
$ curl -i --user user1:password -X GET http://localhost:8080/api/health
Response
{"status":"UP"}

we can see that API endpoint returns the health when we provide user credentials using basic auth.

We can also using POSTMAN to hit and endpoint by providing credentials in Basic Auth format.

postmain basic auth
Using POSTMAN to hit the endpoint

and it works!


Top articles in this category:
  1. How to prevent duplicate form submission in Spring MVC
  2. File Upload in Spring MVC using RestTemplate with ByteArrayResource & FileSystemResource
  3. How will you test web layer in Spring Boot using WebMvcTest annotation?
  4. What is difference between Component, Repository, Service, Controller & RestController
  5. What are different Bean Scopes in Spring?
  6. What is new in Spring Boot 2
  7. Setting a Random Port in Spring Boot Application at startup



Find more on this topic:
Spring Framework image
Spring Framework

Spring Framework - MVC, Dependency Injection, Spring Hibernate, Spring Data JPA, Spring Boot and Spring Cloud for Microservices Architecture.

Last updated 1 week ago


Recommended books for interview preparation:

This website uses cookies to ensure you get the best experience on our website. more info