1. Overview

In this article, we will see spring security digest authentication example. Spring security provides digest authentication filter using that we can authenticate the user using digest authentication header. Digest authentication header considers of :

base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
expirationTime:   The date and time when the nonce expires, expressed in milliseconds
key:              A private key to prevent modification of the nonce token

Why digest authentication?

  1. It’s more secure than basic authentication. Basic authentication header considers of base64(user:password) which means that it’s like plain text anyone can view username and password after decoding base64.
  2. While running application on HTTP (Not secure layer) at that time digest authentication is more preferable.
  3. Popular browsers like Chome, Mozilla FireFox, and IE etc support digest authentication.

Limitation of digest authentication:

 

2. Example

spring security digest authentication example

spring security digest authentication example

2.1 pom.xml

Spring security dependency :  spring-boot-starter-security

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>spring-boot-example</groupId>
    <artifactId>spring-boot-digest-authentication</artifactId>
    <version>1.0-SNAPSHOT</version>
    <description>spring security digest authentication example</description>
    <!-- Inherit defaults from Spring Boot -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
    </parent>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>  <!--starter require for spring boot spring security-->
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    </dependencies>

    <!-- Package as an executable jar -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2.2 SecurityConfiguration

  • DigestAuthenticationFilter is responsible for processing digest available in the request header. DigestAuthenticationFilter requires entry point and UserDetailsService consist of User Details like username, password, activation details etc.
  • For digest authentication, DigestAuthenticationEntryPoint require an entry point for authentication. Entry point requires realm and key.
  • /home is open for all, remaining pages are secure.
package com.javadeveloperzone;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.DigestAuthenticationFilter;

/**
 * Created by JavaDeveloperZone on 04-08-2017.
 */
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
            http.addFilter(digestAuthenticationFilter())              // register digest entry point
            .exceptionHandling().authenticationEntryPoint(digestEntryPoint())       // on exception ask for digest authentication
            .and()
            .httpBasic()                      // it indicate basic authentication is requires
            .and()
            .authorizeRequests()
            .antMatchers( "/home").permitAll() // /home will be accessible directly, no need of any authentication
            .anyRequest().authenticated();

    }

    DigestAuthenticationFilter digestAuthenticationFilter() throws Exception {

        DigestAuthenticationFilter digestAuthenticationFilter = new DigestAuthenticationFilter();
        digestAuthenticationFilter.setUserDetailsService(userDetailsServiceBean());
        digestAuthenticationFilter.setAuthenticationEntryPoint(digestEntryPoint());
        return digestAuthenticationFilter;
    }

    @Override
    @Bean
    public UserDetailsService userDetailsServiceBean() {
        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
        inMemoryUserDetailsManager.createUser(User.withUsername("zone").password("password").roles("USER").build());
        return inMemoryUserDetailsManager;

    }

    @Bean
    DigestAuthenticationEntryPoint digestEntryPoint() {
        DigestAuthenticationEntryPoint bauth = new DigestAuthenticationEntryPoint();
        bauth.setRealmName("Digest WF Realm");
        bauth.setKey("MySecureKey");
        return bauth;
    }

    @Bean
    public AuthenticationManager customAuthenticationManager() throws Exception {
        return authenticationManager();
    }
}

2.2 HelloController

  • RestController is for rest API.
package com.javadeveloperzone.controller;


import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by JavaDeveloperZone on 19-07-2017.
 */
@RestController
public class HelloController {

    @RequestMapping(value = "/secure")
    public String secure() {
        return "You are authorize to access this page. This is secure page. ";
    }
    @RequestMapping(value = "/home")
    public String home() {
        return "This is public page. No need of authentication";
    }
}

2.3 SpringBootConfig

package com.javadeveloperzone;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

/**
 * Created by JavaDeveloperZone on 19-07-2017.
 */

@SpringBootApplication
@ComponentScan // Using a root package also allows the @ComponentScan annotation to be used without needing to specify a basePackage attribute
public class SpringBootConfig {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(SpringBootConfig.class, args);            // it wil start application
    }
}

Output:

Let’s try to access secure URL: http://localhost:8080/secure It will ask for authentication details like username and password.

 

spring security digest authentication example login

spring security digest authentication example login

 

When username and password passed to the server in digest not as simple as basic authentication.

spring security digest authentication example-header information

spring security digest authentication example-header information

3. References

Was this post helpful?
Let us know, if you liked the post. Only in this way, we can improve us.
Yes
No

Leave a Reply

Your email address will not be published. Required fields are marked *