Spring Boot Security Digest Authentication (2024)
In previous article, we learned about Spring Boot Security Basic Authentication. As we have seen basic authentication is not secured, since it's encoded in base 64 encoder which can be easily decoded can be vulnerable.
Spring Boot Security Tutorial :
- Basic Authentication
- Digest Authentication
- Configuring Authentication Credentials in database
- Spring Boot Method Security with PreAuthorize
- Enable https (http+ssl)
- JWT Introduction
- JWT Token Authentication Example
- JWT Angular Example
- JWT +MYSQL Example
- OAuth 1.0 vs OAuth 2.0
- OAuth2.0 Tutorial
- OAuth2 - Google Authorization Server
- Advantage of JWT as OAuth Access Token Vs OAuth Default Token
- OAuth2 with JWT Access Token
- Spring Security Interview Questions
Q: What is Digest Authentication?
Digest Authentication communicates credentials in an encrypted form by applying a hash function to : the username, the password, the nonce value provided by a server, the HTTP method and the requested URI.
Q: Why Digest Authentication?
Digest access authentication is one of the accepted techniques for a web server to negotiate credentials with a user's web browser, such as username and password. This can be used to verify a user's identity before providing sensitive data like online banking transaction history. Before transferring the login and password over the network, it uses a hash function. Basic authentication, on the other hand, uses the easily reversible Base64 encoding instead of hashing, making it insecure unless combined with TLS.
Project Structure:
Maven Dependency:
Include spring security starter in the pom.xml file to secure our REST API.<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.techgeeknext</groupId>
<artifactId>Digestsecurity</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Digestsecurity</name>
<description>Digest Security project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Spring Security Configuration
- DigestAuthenticationFilter processes Digest Authorization Headers of the HTTP request , placing the result into the SecurityContextHolder.
- If authentication is successful, the resulting Authentication object will be put in the SecurityContextHolder.
- If authentication fails, an implementation of AuthenticationEntryPoint will be called. This will always be DigestAuthenticationEntryPoint, which will request the user to authenticate by Digest Authentication again.
- DigestAuthenticationFilter includes an entry point and UserDetailsService consists of user information such as username , password, activation information, etc.
- For digest authentication, DigestAuthenticationEntryPoint requires an authentication entry point. Entry point needs a key and a realm.
package com.techgeeknext.digestsecurity.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.DigestAuthenticationFilter;
@Configuration
@Order(1)
public class AdminSecurityConfiguration extends WebSecurityConfigurerAdapter
{
// Configure DigestAuthenticationEntryPoint
private DigestAuthenticationEntryPoint getDigestEntryPoint() {
DigestAuthenticationEntryPoint digestEntryPoint = new DigestAuthenticationEntryPoint();
digestEntryPoint.setRealmName("admin-digest-realm");
digestEntryPoint.setKey("somedigestkey");
return digestEntryPoint;
}
// PasswordEncoder Bean
@Bean
public PasswordEncoder passwordEncoder() {
//return new BCryptPasswordEncoder();
return NoOpPasswordEncoder.getInstance();
}
//Configure authentication manager
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("TestUser")
.password(passwordEncoder().encode("digestsecret"))
.roles("USER")
.and()
.withUser("TestAdmin")
.password(passwordEncoder().encode("adminsecret"))
.roles("ADMIN");
}
//default UserDetailsService configured by UserDetailsServiceAutoConfiguration
@Bean
public UserDetailsService userDetailsServiceBean() throws Exception {
return super.userDetailsServiceBean();
}
// Configure DigestAuthenticationFilter.
// Notice the we are injecting userDetailsService and DigestAuthenticationEntryPoint
private DigestAuthenticationFilter getDigestAuthFilter() throws Exception {
DigestAuthenticationFilter digestFilter = new DigestAuthenticationFilter();
digestFilter.setUserDetailsService(userDetailsServiceBean());
digestFilter.setAuthenticationEntryPoint(getDigestEntryPoint());
return digestFilter;
}
//Notice that we are configuring / admin/ * * for the SecurityFilterChain
// added DigestAuthenticationFilter, also configured the EntryPoint authentication.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/admin/**").
addFilter(getDigestAuthFilter()).exceptionHandling()
.authenticationEntryPoint(getDigestEntryPoint())
.and().authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN");
}
}
Take a look at our suggested posts:
REST Controller:
This is a simple Hello REST controller with two endpoints.package com.techgeeknext.digestsecurity.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String sayHello(@RequestParam(required = false,defaultValue = "TechGeekNext User") String name) {
return "Hello "+name;
}
@GetMapping("/admin/hello")
public String sayAdminHello(String name) {
return "Hello Admin "+name;
}
}
Testing Digest Authentication
- Enter valid Admin User credential. Username :TestAdmin and Password: adminsecret using http://localhost:8083/hello?name=User rest api.
- It authenticated successfully, and displayed Hello message. If you notice in browser it shows
Authorization header:
Authorization: Digest username="TestAdmin", realm="admin-digest-realm", nonce="MTYwMDEwMTUyMDM4OToxM2M1Y2I4MGFjMjk4OGI1ODQzZjc3NDUzOGFlMjZjYw==", uri="/admin/hello?name=User", response="2f080edbec53be2bdf3853d477e4a543", qop=auth, nc=00000002, cnonce="11ecd9bf947dbcf4"
Download Source Code
The full source code for this article can be found on below.Download it here - Spring Boot Security - Digest Authentication