Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security RememberMe & RESTful API

I am trying to implement an API along the lines of this guide

The basic flow is:

  • mobile app embeds web view for user to login (normal web app security)
  • on login, webapp returns a secure cookie with a token
  • mobile app uses the token in all future API requests

So I am trying to secure my webapp to allow normal login flow (with Spring Security) via login form, and then all requests to /api/** are authenticated based on a token passed in request header.

I had originally started implementing this by having two web configs - one for the normal webapp security:

@Override protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf()
                .disable()
            .authorizeRequests()
                .antMatchers("/resources/**").permitAll()
                .antMatchers("/sign-in").permitAll()
                .antMatchers("/success").authenticated()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/")
                .loginProcessingUrl("/loginprocess")
                .failureUrl("/sign-in?loginFailure=true")
                .permitAll();
    }

Above just defines standard spring security authentication (custom userDetailsService to get userdetails from DB) and authenticating he login and success pages.

Then another (two files just for clarity/ease of reading) for the API authentication:

@Override protected void configure(HttpSecurity http) throws Exception {
    http
        .antMatcher("/api/**")
        .csrf()
            .disable()
        .authorizeRequests().anyRequest().authenticated().and()
        .addFilterBefore(authenticationTokenFilter(), BasicAuthenticationFilter.class )
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
            .exceptionHandling().authenticationEntryPoint(new Http403ForbiddenEntryPoint());
}

The above has a pre-auth filter that grabs the relevant HTTP headers from the request (token etc) and adds them to the security context - the custom authentication provider then validates the token/user details.

All good - however, it feels like I am re-inventing a bunch of stuff. Having looked at Spring Security's RememberMe functionality, it looks like they already handle a lot of this - on login it returns a cookie with a token that can be then used for auto login on future requests. From the java docs:

<bean id="rememberMeFilter" class=
 "org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
  <property name="rememberMeServices" ref="rememberMeServices"/>
  <property name="authenticationManager" ref="theAuthenticationManager" />
</bean>

<bean id="rememberMeServices" class=
 "org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
  <property name="userDetailsService" ref="myUserDetailsService"/>
  <property name="key" value="springRocks"/>
</bean>

<bean id="rememberMeAuthenticationProvider" class=
 "org.springframework.security.authentication.rememberme.RememberMeAuthenticationProvider">
  <property name="key" value="springRocks"/>
</bean>

The only problem is that I want to include the token in future requests as header params, not a cookie. I have looked at the source for the above classes and the TokenBasedRememberMeServices class autoLogin() method explicitly examines the cookie. The code also uses MD5 as default for hashing.

My questions are:

  1. Is there a standard Spring class that can handle RememberMe functionality from request headers rather than cookies
  2. Is there anything that uses a better hashing algorithm than MD5? (can it be easily switched without overriding?). Or, even better - I have come across the KeyBasedPersistenceTokenService which looks like a much better token generation service (SHA512 & additional key info), are there any good examples of using that to create/validate the secure token.

I would prefer not to have to extend all those classes, as a bunch of the core stuff would be the same, and seems overkill to have to extend them just to change the source of the token and the hashing algorithm.

like image 600
rhinds Avatar asked Mar 04 '14 21:03

rhinds


1 Answers

Ok, having looked around a little, there didnt seem to be core classes that implemented the RememberMe functionality for request headers - however, reading through the Spring Security remember me source code, it was actually quite simple to extend the above classes to look at the request header.

Details are all here: http://automateddeveloper.blogspot.co.uk/2014/03/securing-your-mobile-api-spring-security.html but basically just use RememberMe as normal, but then extend the TokenBasedRememberMeServices and override the extractCookie method to just grab the token from a header rather than a cookie (possibly a little bit hacky, extending a method called extractCookie to grab request headers, but it works)

like image 133
rhinds Avatar answered Nov 15 '22 03:11

rhinds