How to secure a REST service in Spring Boot using Basic Authentication?

Rest Services can be secured in a variety of ways: Basic Authentication , Bearer Authentication , API Keys , Open Id etc.

Basic Authentication is the simplest , it uses a user name and password to secure a REST service.

In this post let’s see how to protect a REST service using basic authentication in Spring Boot.

STEP 1: Add security dependency in pom.xml:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

For testing security code , one more dependency need to be added , but I will ignore it here for simplicity. Also I have not mentioned spring-boot-starter-web dependency as I assume the REST service is already built and only needs security code to be added.

STEP 2: Create a configuration class

This will contain all security related configuration.

package com.springboot.simplerest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

		auth.inMemoryAuthentication().withUser("admin").password("{noop}admin").roles("USER");

	}

	@Override
	public void configure(HttpSecurity http) throws Exception {

		http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
	}

}

Following are the rules to be followed while creating the class :

  • Class need to be annotated with @Configuration and @EnableWebSecurity
  • Class should extend WebSecurityConfigurerAdapter
  • Class should implement a method configureGlobal() which takes an authentication manager builder as a parameter.
  • The method configureGlobal() should be annotated with @Autowired
  • Override the method configure() which takes a http security object as a parameter

configureGlobal() method:

This is the method where the Authentication Manager is built. Authentication Manager takes care of authentication in Spring Boot . Authentication can be done in various ways like : In Memory Authentication , LDAP Authentication , User Details stored in database etc. In this example I am using in-memory authentication . It just configures the user name , password and the role .

If you notice I have added {noop} to the password. This represents NoOpPassword encoder in Spring . Spring Security after version 5 made password encoder mandatory and hence we need to specify a password encoder. This is one way of specifying it (NoOoPassword encoder does not encode the password and hence it is not secure)

If you don’t include the encoder , Spring will throw the error – There is no PasswordEncoder for the id “null”:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
at org.springframework.security.crypto.password.DelegatingPasswordEncoder$UnmappedIdPasswordEncoder.matches(DelegatingPasswordEncoder.java:250) ~[spring-security-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.security.crypto.password.DelegatingPasswordEncoder.matches(DelegatingPasswordEncoder.java:198) ~[spring-security-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]

configure() method:

The next method to be noted is configure() . It builds a httpBasic object. In the sample code, I am authenticating any request with basic authentication (Spring Security uses Fluent API style for this configuration)

Instead of a configuration class , we can also use xml . This is left out in this post for the sake of keeping it simple.

That’s it!

Now my REST service is authenticated.

I had created a REST service which just returns a list of person details.

Let me try to hit it without authentication first:

I get 401 unauthorized error:



Let me pass the credentials and try:

I get the response!

If you want to fire a POST request you might face 403 forbidden error.

In that case , modify configure method in your security configuration class and add methods to disable CORS and CSRF like this:

    @Override
    public void configure(HttpSecurity http) throws Exception {
 
        http.cors().and().csrf().disable().authorizeRequests().anyRequest().authenticated().and().httpBasic();
    }

This is a very simple way to configure basic authentication for your REST service. Although in real time scenarios we can’t use in memory authentication , I have used it to explain the basic concept behind ‘Spring Security Basic Authentication’.

Comments

Leave a Reply

Discover more from The Full Stack Developer

Subscribe now to keep reading and get access to the full archive.

Continue reading