My current architecture for my web app has a gateway server that orchestrates a bunch of microservices, authorisation occurs at the gateway if a given principle is authenticated they can talk to some downstream services.
The downstream service gets hold of the required data to identify a given authenticated client. However spring securities default behaviour kicks in and throws the expected:
org.springframework.security.access.AccessDeniedException: Access is denied
Given that I can use the session id and + XSRF token in any given Microservice to validate the user is authenticated and know which user is logged in (i'm currently using Http Basic).
My question is there a simpler / declarative approach that could be used in place of having to adding a filter to every Microservice to override spring securities default behaviour? (see my example Pseudo code)
See the attached diagram: Architecture.
Spring web security config for resource server:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public SessionRepository<ExpiringSession> sessionRepository() {
return new MapSessionRepository();
}
@Bean
HeaderHttpSessionStrategy sessionStrategy() {
return new HeaderHttpSessionStrategy();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and().authorizeRequests().anyRequest().authenticated();
final SessionRepositoryFilter<ExpiringSession> sessionRepositoryFilter = new SessionRepositoryFilter<ExpiringSession>(
sessionRepository());
sessionRepositoryFilter
.setHttpSessionStrategy(new HeaderHttpSessionStrategy());
http.addFilterBefore(sessionRepositoryFilter,
ChannelProcessingFilter.class).csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
}
public SessionRepository<ExpiringSession> getSessionRepository(){
return sessionRepository();
}
}
Header values at the resource microservice:
KEY: cookie VALUE: XSRF-TOKEN=[token_value]; SESSION=[session_value]
KEY: x-requested-with VALUE: XMLHttpRequest
KEY: x-auth-token VALUE: a32302fd-589b-42e1-8b9d-1991a080e904
...
Planned approach (Pseudo code) attach a new filter to the spring securities filter chain that if given flags are true, allow access to secured endpoints.
**
* A custom filter that can grant access to the current resource
* if there is a valid XSRF-TOKEN and SESSION present in the shared
* session cache.
*/
public class CustomAuthenticationFilter extends AnAppropriateFilterChainFilter {
@Autowired
SessionRepository sessionRepository;
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
boolean csrfTokenExists = sessionRepository.findByCsrfTokenId(request);
boolean sessionExists = sessionRepository.findBySessionId(request);
if (csrfTokenExists && sessionExists) {
// everything is okay
} else {
// invalidate the request as being authenticated
throw new InsufficientAuthenticationException("Invalid csrf + session pair");
}
}
}