Spring OAuth 2 and OpenAM Integration, ClientContext per session

I am currently trying to integrate Spring-Security-Oauth2, Zuul, OpenAM as an OAuth2 authorization server and WCF REST API as a resource server. The final setup should look something like this:

Security

I read a tutorial that explains how to set up a SSO environment with spring and AngularJS ( sso with spring and angularJS ), however, in my case, I would like to use OpenAM and a password grant flow to authenticate users. So, in my Spring Boot application, my current config looks like this:

@SpringBootApplication
@EnableZuulProxy
@EnableOAuth2Client
public class ApolloUIProxyApplication {

    public static void main(String[] args) {
        SpringApplication.run(ApolloUIProxyApplication.class, args);
    }

    @Configuration
    protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.logout().and().antMatcher("/**").authorizeRequests()
                    .antMatchers("/index.html", "/home.html", "/", "/login").permitAll()
                    .anyRequest().authenticated().and().csrf()
                    .csrfTokenRepository(csrfTokenRepository()).and()
                    .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
                    .addFilterAfter(authenticationProcessingFilter(), CsrfFilter.class);
        }

        @Bean
        public ZuulFilter tokenRelayFilter(){
            JwtTokenRelayFilter filter = new JwtTokenRelayFilter();
            filter.setRestTemplate(restTemplate());
            return new JwtTokenRelayFilter();
        }

        @Bean
        public ZuulFilter customTokenFilter(){
            return new CustomZuulFilter();
        }

        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter(){
            return new JwtAccessTokenConverter();
        }

        private Filter csrfHeaderFilter() {
            return new OncePerRequestFilter() {
                @Override
                protected void doFilterInternal(HttpServletRequest request,
                                                HttpServletResponse response, FilterChain filterChain)
                        throws ServletException, IOException {
                    CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
                            .getName());
                    if (csrf != null) {
                        Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
                        String token = csrf.getToken();
                        if (cookie == null || token != null
                                && !token.equals(cookie.getValue())) {
                            cookie = new Cookie("XSRF-TOKEN", token);
                            cookie.setPath("/");
                            response.addCookie(cookie);
                        }
                    }
                    filterChain.doFilter(request, response);
                }
            };
        }

        private CsrfTokenRepository csrfTokenRepository() {
            HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
            repository.setHeaderName("X-XSRF-TOKEN");
            return repository;
        }


        private OAuth2ClientAuthenticationProcessingFilter authenticationProcessingFilter(){
            OAuth2ClientAuthenticationProcessingFilter processingFilter = new OAuth2ClientAuthenticationProcessingFilter("/login");
            processingFilter.setRestTemplate(restTemplate());
            processingFilter.setTokenServices(resourceServerTokenServices());
            return processingFilter;
        }

        @Bean
        public ResourceServerTokenServices resourceServerTokenServices(){
            OpenAMRemoteTokenService remoteTokenServices = new OpenAMRemoteTokenService();
            remoteTokenServices.setRestTemplate(restTemplate());
            remoteTokenServices.setAccessTokenConverter(accessTokenConverter());
            remoteTokenServices.setClientId("...");
            remoteTokenServices.setClientSecret("...");
            remoteTokenServices.setCheckTokenEndpointUrl("http://...");
            return remoteTokenServices;
        }

        @Bean
        public OAuth2RestTemplate restTemplate(){
            OAuth2RestTemplate template = new OAuth2RestTemplate(resourceDetails(), clientContext());
            return template;
        }

        @Bean
        public AccessTokenProvider accessTokenProvider(){
            ResourceOwnerPasswordAccessTokenProvider provider = new ResourceOwnerPasswordAccessTokenProvider();
            return provider;
        }

        @Bean
        public OAuth2ClientContext clientContext(){
            return new OpenAMClientContext();
        }

        @Bean
        public OAuth2ProtectedResourceDetails resourceDetails(){
            ResourceOwnerPasswordResourceDetails details = new ResourceOwnerPasswordResourceDetails();
            details.setGrantType("password");
            details.setAccessTokenUri("http://...");
            details.setScope(Arrays.asList("openid");
            details.setClientId("...");
            details.setClientSecret("...");
            return details;
        }

        @Bean
        public AccessTokenConverter accessTokenConverter(){
            DefaultAccessTokenConverter tokenConverter = new DefaultAccessTokenConverter();
            tokenConverter.setUserTokenConverter(userAuthenticationConverter());
            return tokenConverter;
        }

        @Bean
        public UserAuthenticationConverter userAuthenticationConverter(){
            return new OpenAMUserAuthenticationConverter();
        }

    }
}

      

I wrote a custom RemoteTokenService because otherwise Spring would not be able to access the OpenAM tokeninfo endpoint, which requires a GET request, not a Post. This connection is working fine now, so I get a valid access token from OpenAM and can also request tokeninfo.endpoint for the / user-Infos token. The Authentication object is created and stored in the Spring security context. I can also access the authentication object in the ZuulFilter.

My problem now is that I had to configure the "OAuth2ClientContext" to get the user credentials from the servletRequest and put it in the "AccessTokenRequest". Otherwise, I would have to hard-code them into ResourceDetails, which doesn't work in my case.

As a result, the ClientContext (and also, as it seems to me, AccessTokenRequest) is common for all users of the System. I need a client context within a session so that I can connect to multiple users and access the correct SecurityContext for each user on every request.

So my question is,

1) how to make the session scope of ClientContext and AccessTokenRequest available?

2) Do I need to use the Spring Session module?

3) Do I need to install sessionStrategy

Thank!

+3


source to share





All Articles