Securing Spring MVC REST endpoint using Basic Auth

Munish Chandel | April 07, 2019 at 08:44 PM | 22 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!



You may also be interested in..
Generic placeholder image
ebook PDF - Cracking Spring Microservices Interviews for Java Developers
You may also be interested in..
Generic placeholder image
ebook PDF - Cracking Java Interviews v3.4 by Munish Chandel

Similar Articles:
  1. How to create a custom banner for your spring boot application
  2. Run code on Spring Boot App Startup
  3. Spring Boot 2.0 Reactive Web Performance Metrics
  4. Securing Spring MVC REST endpoint using Basic Auth
You may also be interested in..
Generic placeholder image
ebook PDF - Cracking Spring Microservices Interviews for Java Developers
You may also be interested in..
Generic placeholder image
ebook PDF - Cracking Java Interviews v3.4 by Munish Chandel
Facebook Page
Free Email Updates

Enter your email address to subscribe to this blog and receive notifications of new posts by email.


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