1. Overview
This tutorial shows how to set up, configure, and customize Digest Authentication with Spring. Similar to the previous article covering Basic Authentication, we’re going to build on top of the Spring MVC tutorial and secure the application with the Digest Auth mechanism provided by Spring Security.
Digest Authentication is an improvement to Basic Authentication and tries to solve the problems from the previous authentication mechanism by ensuring that the credentials are never sent in clear text across the wire.
2. The Security XML Configuration
The first thing to understand about the configuration is that, while Spring Security does have full out of the box support for the Digest authentication mechanism, this support is not as well integrated into the namespace as Basic Authentication was.
In this case, we need to manually define the raw beans that are going to make up the security configuration – the DigestAuthenticationFilter and the DigestAuthenticationEntryPoint:
<beans:bean id="digestFilter"
class="org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
<beans:property name="userDetailsService" ref="userService" />
<beans:property name="authenticationEntryPoint" ref="digestEntryPoint" />
</beans:bean>
<beans:bean id="digestEntryPoint"
class="org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
<beans:property name="realmName" value="Contacts Realm via Digest Authentication" />
<beans:property name="key" value="acegi" />
</beans:bean>
<!-- the security namespace configuration -->
<http use-expressions="true" entry-point-ref="digestEntryPoint">
<intercept-url pattern="/**" access="isAuthenticated()" />
<custom-filter ref="digestFilter" after="BASIC_AUTH_FILTER" />
</http>
<authentication-manager>
<authentication-provider>
<user-service id="userService">
<user name="user1" password="user1Pass" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
Next, we need to integrate these beans into the overall security configuration – and in this case, the namespace is still flexible enough to allow us to do that.
The first part of this is pointing to the custom entry point bean, via the entry-point-ref attribute of the main <http> element.
The second part is adding the newly defined digest filter into the security filter chain. Since this filter is functionally equivalent to the BasicAuthenticationFilter, we are using the same relative position in the chain – this is specified by the BASIC_AUTH_FILTER alias in the overall Spring Security Standard Filters.
Finally, notice that the Digest Filter is configured to point to the user service bean – and here, the namespace is again very useful as it allows us to specify a bean name for the default user service created by the <user-service> element:
<user-service id="userService">
3. Consuming the Secured Application
We’re going to be using the curl command to consume the secured application and understand how a client can interact with it.
Let’s start by requesting the homepage – without providing security credentials in the request:
curl -i http://localhost/spring-security-mvc-digest-auth/homepage.html
As expected, we get back a response with a 401 Unauthorized status code:
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=CF0233C...; Path=/spring-security-mvc-digest-auth/; HttpOnly
WWW-Authenticate: Digest realm="Contacts Realm via Digest Authentication", qop="auth",
nonce="MTM3MzYzODE2NTg3OTo3MmYxN2JkOWYxZTc4MzdmMzBiN2Q0YmY0ZTU0N2RkZg=="
Content-Type: text/html;charset=utf-8
Content-Length: 1061
Date: Fri, 12 Jul 2013 14:04:25 GMT
If this request were sent by the browser, the authentication challenge would prompt the user for credentials using a simple user/password dialog.
Let’s now provide the correct credentials and send the request again:
curl -i --digest --user
user1:user1Pass http://localhost/spring-security-mvc-digest-auth/homepage.html
Notice that we are enabling Digest Authentication for the curl command via the –digest flag.
The first response from the server will be the same – the 401 Unauthorized – but the challenge will now be interpreted and acted upon by a second request – which will succeed with a 200 OK:
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=A961E0D...; Path=/spring-security-mvc-digest-auth/; HttpOnly
WWW-Authenticate: Digest realm="Contacts Realm via Digest Authentication", qop="auth",
nonce="MTM3MzYzODgyOTczMTo3YjM4OWQzMGU0YTgwZDg0YmYwZjRlZWJjMDQzZWZkOA=="
Content-Type: text/html;charset=utf-8
Content-Length: 1061
Date: Fri, 12 Jul 2013 14:15:29 GMT
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=55F996B...; Path=/spring-security-mvc-digest-auth/; HttpOnly
Content-Type: text/html;charset=ISO-8859-1
Content-Language: en-US
Content-Length: 90
Date: Fri, 12 Jul 2013 14:15:29 GMT
<html>
<head></head>
<body>
<h1>This is the homepage</h1>
</body>
</html>
A final note on this interaction is that a client can preemptively send the correct Authorization header with the first request, and thus entirely avoid the server security challenge and the second request.
Explaining some of the parameters from the response:
- realm: offers a security policy domain defined for web or application servers. The protected resources on a server can be partitioned into a set of protection spaces, each with its own authentication scheme and/or authorization database containing a collection of users and groups.
- nonce: is an alternative mechanism for whitelisting sources which is a unique random string that will be generated for each page request by the server. By using this type of attribute you can allow only inline scripts or styles with the correct value to be executed, giving to the attackers a hard way to attack.
- qop: quality of protection which can have the value “auth”.
4. The Maven Dependencies
The security dependencies are discussed in depth in the Spring Security Maven tutorial. In short, we will need to define spring-security-web and spring-security-config as dependencies in our pom.xml.
5. Conclusion
In this tutorial we introduce security into a simple Spring MVC project by leveraging the Digest Authentication support in the framework.
The code backing this article is available on GitHub. Once you're
logged in as a Baeldung Pro Member, start learning and coding on the project.
When the project runs locally, the homepage html can be accessed at (or, with minimal Tomcat configuration, on port 8080):
http://localhost:8080/spring-security-mvc-digest-auth/homepage.html
Finally, there is no reason an application needs to choose between Basic and Digest authentication – both can be set up simultaneously on the same URI structure, in such a way that the client can pick between the two mechanisms when consuming the web application.