Spring Security Digest Authentication

I usually post about Security on Google+ - you can follow me there:

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 built on top of the Spring MVC tutorial, and secure the application with the Digest Auth mechanism provided by Spring Security.

2. The Security XML Configuration

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:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:beans="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="
        http://www.springframework.org/schema/security 
        http://www.springframework.org/schema/security/spring-security-3.1.xsd
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

    <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>

</beans:beans>

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.

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 implementation of these examples can be found in the github project – this is an Eclipse based project, so it should be easy to import and run as it is.

When the project runs locally, the homepage html can be accessed at (or, with minimal Tomcat configuration, on port 80):

http://localhost:8080/spring-security-mvc-digest-auth/homepage.html

Finally, there is no reason an application needs to choose between Basic and Digest authenticationboth 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.

I usually post about Security on Google+ - you can follow me there:

>> GET THE EBOOKS <<
Get the eBooks and Learn to Build a Simple App
×
Build a Simple but Working App with Spring

,

  • Amit Singh

    What if I want to use it (digest Authentication) with custom AuthenticationManager instead of UserdetailService ?

    • http://www.baeldung.com/ Eugen Paraschiv

      In that case, you will most have to provide your own custom implementation of the digestFilter – as you can see, the default implementation works directly with the UserDetailsService, so you won’t be able to use that. You can however simply write your own filter, similar to the default one, and use whatever custom mechanism you have for retrieving the principal.
      Thanks. Eugen.

      • Amit Singh

        Thanks I got your point, As i tried to understood the digest authentication it is useful in case of REST services only. If I am using simple MVC based application where session is used i think Usernamepasswordtoken shall be able good approach right ?

        • http://www.baeldung.com/ Eugen Paraschiv

          Digest Authentication is indeed useful for a REST API, but it’s definitely not limited to that space – for one thing it’s much older than REST. However, if you’re writing a standard MVC web app, then yes, I’d start with the standard and only move to something more than that if you really need it.

  • ty

    Is it possible to use a custom implementation of UserDetailsService or would it be necessary to use a custom AuthenticationProvider at that point?

    • http://www.baeldung.com/ Eugen Paraschiv

      I may have missed the first part of your question – at what point are you considering the custom provider?
      Thanks. Eugen.

  • GT

    First off … this series of blogs on spring security are simply awesome…thank you for all your hard work. After reading these blogs, i did buy your video pack from Packt Publishing.

    I do have couple of questions thought:

    – I can see that the SecSecurityConfig is setup to scan @ComponentScan(“org.baeldung.security”) package.
    – In that package i can only see @Component annotation for the RestAuthenticationEntryPoint class …. but not for the AuthenticationSuccessHandler implementation
    – So two questions: how is this AuthenticationSuccessHandler being resolved without it having any annotation and how is the the RestAuthenticationEntryPoint getting resolved to the particular bean id digestEntryPoint

    Thanks for you help …

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey GT – glad you’re finding the series helpful. To answer your questions – and working on the assumption that you’re looking at where the article points to – my tutorial over on github (spring-security-mvc-digest-auth) – the component scan is indeed only picking up the entry point for Basic auth. That’s because – at least in this tutorial – there’s no success handler used or needed (which is why none is defined). So – perhaps you’re looking at another tutorial on github, but for this particular one – these are all the beans necessary. Hope this helps. Cheers,
      Eugen.