Spring Security Digest Authentication

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:

Free eBook - REST Services with Spring
Join more than 2,200 engineers!

,

  • Amit Singh

    Hi I tried to tun this… I am not able to understand how MyBasicAuthenticationEntryPoint is called in flow

    • baeldung

      Not sure what entry point you are referring to – there is no mention of this entry point in this particular article.
      Thanks. Eugen.

  • Amit Singh

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

    • baeldung

      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 ?

        • baeldung

          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?

    • ty

      Also should add that I am using encoded passwords.

    • baeldung

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

      Eugen.

  • Ho Wai

    Thanks a lot for sharing this digest auth example, it saves me from try-and-error hell!

    After reading other articles on authentication from baeldung, i finally find out how to providing custom provider, i hope the code can help someone :

    in xml :

    For the bean customUserDetailsService, it should implements org.springframework.security.core.userdetails.UserDetailsService, you provide the username/password/permission in the function loadUserByUsername() :

    @Override
    public UserDetails loadUserByUsername(String username)

    throws UsernameNotFoundException, DataAccessException {
    final String correctUsername = “user1″;
    final String correctPassword = “password1″;

    if( !username.equals(correctUsername) ) {
    throw new UsernameNotFoundException(“no such user”);
    }

    final UserDetails user = new User(username, correctPassword, true, true, true, true, new GrantedAuthority[]{ new GrantedAuthorityImpl(“ROLE_USER”) });

    return user;
    }

    For the bean customAuthenticationProvider, it should implements org.springframework.security.authentication.AuthenticationProvider, this bean should do nothing when Spring invoke it, so it just return the input parameter :

    public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Override
    public Authentication authenticate(final Authentication auth) throws AuthenticationException {
    return auth;
    }

    @Override
    public boolean supports(Class auth) {
    return auth.equals(UsernamePasswordAuthenticationToken.class);
    }

    }

    I must say thank you to baeldung again! The security tutorial is simple and clear, read-for-use, it save spring newbie ppl like me! Thanks!

Powered by WordPress. Designed by Woo Themes