Spring REST API -Part 3: Spring Security (Basic Authentication)

Zia khalid
4 min readApr 15, 2017

Part 3: Spring Security (Basic Authentication)

Note — Codes in the story is in continuation to the previous parts, so if you feel uncomfortable or disconnected please check the previous parts or navigate through git commit to have a better understanding.

In this part we will secure REST API using Basic Authentication.

What is Basic Authentication?

Basic authentication sends a Base64-encoded string that contains a user name and password for the client. Base64 is not a form of encryption and should be considered the same as sending the user name and password in clear text. If a resource needs to be protected, strongly consider using an authentication scheme other than basic authentication.

With Basic Authentication, clients send it’s Base64 encoded credentials with each request, using HTTP [Authorization] header . That means each request is independent of other request and server does not maintain any state information for the client.

Base64 encoded string looks somthing like this

This header will be sent with each request.

Adding spring security dependency
To enable spring security add compile time dependency to your build.gradle

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

Creating User entity

@Entity
public class User extends BaseEntity {

public static final PasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();
private String firstName;
private String lastName;
private String username;
@JsonIgnore
private String password;
@JsonIgnore
private String[] roles;

public User() {
super();
}

public User(String firstName, String lastName, String username, String password, String[] roles) {
this.firstName = firstName;
this.lastName = lastName;
this.username = username;
setPassword(password);
this.roles = roles;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = PASSWORD_ENCODER.encode(password);
}

public String[] getRoles() {
return roles;
}

public void setRoles(String[] roles) {
this.roles = roles;
}
}

We should use PasswordEncoder for encoding password and security
we don’t want our password and role to be exposed so @JsonIgnore annotation ensure field is to be ignored by introspection-based serialization and deserialization functionality.

Creating UserRepository

public interface UserRepository extends CrudRepository<User, Long>{

User findByUsername(String username);

}

Creating Spring’s UserDetailsService for loading user-specific data. It is used throughout the framework as a user DAO and is the strategy used by the DaoAuthenticationProvider.

@Component
public class DetailsService implements UserDetailsService {

@Autowired
UserRepository users;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

User user = users.findByUsername(username);
if (user == null){
throw new UsernameNotFoundException(username + " was not found");
}
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
AuthorityUtils.createAuthorityList(user.getRoles())
);
}
}

Creating WebSecurityConfiguration

@Component
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter{

@Autowired
DetailsService detailsService;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(detailsService).passwordEncoder(User.PASSWORD_ENCODER);
}

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

@EnableWebSecurity — we want custom Spring Security configuration, by overriding base class methods, and ensures that any request to our application requires the user to be authenticated.

Populating database with dummy user

@Component
public class DatabaseLoader implements ApplicationRunner{

private TopicRepository topics;
private UserRepository users;

@Autowired
public DatabaseLoader(TopicRepository topics, UserRepository users) {
this.topics = topics;
this.users = users;
}

@Override
public void run(ApplicationArguments args) throws Exception {

List<User> students = Arrays.asList(
new User("Reza", "Khalid", "rezakhalid", "password", new String[] {"ROLE_USER"}),
new User("Satyaveer", "Singh", "satyveer_singh", "password", new String[] {"ROLE_USER"}),
new User("Satish", "Yadav", "satishyadav", "password", new String[] {"ROLE_USER"}),
new User("Farzan", "Ahmad", "farzan_ahmad", "password", new String[] {"ROLE_USER"})
);
users.save(students);

users.save(new User("zia", "khalid", "zia566", "123456", new String[] {"ROLE_USER", "ROLE_ADMIN"}));

ArrayList<Topic> bunchOfTopic = new ArrayList<Topic>();

String[] buzzWords = {"Multi Threading", "Inner Classes", "Collections", "Generics", "Development", "JVM"};

//Using java 8 features (stream, lambda)
IntStream.range(0,10).forEach(it -> {
String buzzWord = buzzWords[it % buzzWords.length];
Topic topic = new Topic(buzzWord, (it % buzzWords.length));
bunchOfTopic.add(topic);
});

topics.save(bunchOfTopic);
}
}

Commit
Here you can see the commit of all this changes:

https://github.com/ziakhalid/spring-rest-sample/commit/9f2e1a1a201c5629dfef4a97d4638ff5a1c34efd

Hit Run

Using Client : Postman
Send a request to get the list of topics. you would get 401 as status code, and error message saying “Unauthorized”, this as because of spring security, which is trying to authenticate every request.

Now select type as ‘Basic Auth’ from dropdown, fill in username/password , click on ‘update request’.

Click on Headers tab. You should see the new header.which should look like

Now send the request. You should see the list of topics in response this time.

If you find something to improve please let me know, I will try my best to improve this story.

If this article was helpful to you, please do hit the 💚 button below. Thanks!

See you in the next story!

Next Article

Part 4.1: Spring Controllers (RestController — GET)

--

--