Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Spring Security With Spring Boot 2.0: Password Encoder

DZone's Guide to

Spring Security With Spring Boot 2.0: Password Encoder

Using these nifty Java frameworks, we can has passwords and set up authentication protocols for our application. Read on to learn how.

· Security Zone ·
Free Resource

Discover how to provide active runtime protection for your web applications from known and unknown vulnerabilities including Remote Code Execution Attacks.

In a previous post, we used the user details service in order to provide a way to load our data from a function based on a username given.

The implementation of the user details might be backed by an in-memory mechanism, a SQL/NoSQL database, etc.

The options are unlimited.

What we have to pay attention when it comes to password storage is the password hashing.
For security reasons, we want to store passwords in a hashed form. Supposing someone gets unauthorized access to the table storing our user data, by storing the passwords in clear text, that person can retrieve the password of every user in the system.

So we want a way to hash our passwords before storing them in a database. Always be aware that your hashing has to be robust and up to date. For example, MD5 was very popular in the past but nowadays it leads to poor security. Actually, it is possible to crack MD5 passwords fairly easily if you use a gpu.

Spring Security provides us with out-of-the-box functionality when it comes to encoding passwords. Password encoder is an interface which is used through the authorization process.

package org.springframework.security.crypto.password;


public interface PasswordEncoder {

    String encode(CharSequence rawPassword);

    boolean matches(CharSequence rawPassword, String encodedPassword);

}

The encode function shall be used to encode your password and the matches function will check if your raw password matches the encoded password. Once your user details service fetches the user information from the database then the password given to authorize shall be validated with the one fetched from the database. In this case, Spring will use the matches function.

Now Spring provides us with various implementations of a password encoder. Let's try to create a password encoder bean.

package com.gkatzioura.security.passwordencoder.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class PasswordEncoderConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new PasswordEncoder() {
            @Override
            public String encode(CharSequence rawPassword) {
                return rawPassword.toString();
            }

            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return rawPassword.toString().equals(encodedPassword);
            }
        };
    }
}

This bean is no different than the NoOpPasswordEncoder which comes with Spring Boot.

Now we are going to do a small experiment and add a custom password encoder. Our password encoder will compare the clear text password submitted by the user, hash it, and then compare it with an already hashed password from the equivalent user in our database.

To do the hashing we will user bcrypt.

@Bean
public PasswordEncoder customPasswordEncoder() {

    return new PasswordEncoder() {

        @Override
        public String encode(CharSequence rawPassword) {

            return BCrypt.hashpw(rawPassword.toString(), BCrypt.gensalt(4));
        }

        @Override
        public boolean matches(CharSequence rawPassword, String encodedPassword) {

            return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
        }
    };
}

To test this we will set up our security by using the environmental variables as we've seen in a previous post.

First, we need to have our password encoded. Our system will not have the password stored in any clear text form.

System.out.println(BCrypt.hashpw("user-password",BCrypt.gensalt(4)));
$2a$04$i4UWtMw6surai4dQMhoKSeLddi1XlAh2sSyG58K3ZvBHqVkhz8Y3y

So what we are going to do next is to set our environmental variables before running our Spring Boot application.

SPRING_SECURITY_USER_NAME=test-user
SPRING_SECURITY_USER_PASSWORD=$2a$04$i4UWtMw6surai4dQMhoKSeLddi1XlAh2sSyG58K3ZvBHqVkhz8Y3y

The next step is to go to your login screen and give the credentials user-name and user-password.
As you can see you have just been authenticated.

Behind the scenes, Spring hashed the password you submitted and compared it to the existing one through the environmental variables.

Find out how Waratek’s award-winning application security platform can improve the security of your new and legacy applications and platforms with no false positives, code changes or slowing your application.

Topics:
security ,spring security ,authentication ,spring boot security

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}