title: Spring OAuth 2 and OpenAM integration, ClientContext per Session
body: <p>at the moment I am trying to integrate Spring-Security-Oauth2, Zuul, OpenAM as OAuth2 authorization Server and a WCF REST API as resource Server. The final Setup should look something like the following:</p>
  
  <p><a href="https://i.stack.imgur.com/wDLLp.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/wDLLp.png" alt="Security"></a>
  </p>
  
  <p>I read the tutorial, which explains how to setup a SSO Environment with spring and AngularJS (<a href="https://spring.io/guides/tutorials/spring-security-and-angular-js/#_sso_with_oauth2_angular_js_and_spring_security_part_v" rel="nofollow noreferrer" title="sso with spring and angularJS">sso with spring and angularJS</a>), however in my case I would like to use OpenAM and password grant flow to authenticate useres.
  So in the Spring Boot application my current config Looks as follows:</p>
  
  <pre><code>@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
                                  &amp;&amp; !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();
          }
  
      }
  }
  </code></pre>
  
  <p>I wrote a custom RemoteTokenService, because otherwise Spring could not access the tokeninfo endpoint of OpenAM, which requires a GET-request and not a Post. This Connection works fine now, so that i get a valid access-token from OpenAM and can also query the tokeninfo.endpoint for token/user-Infos. The Authentication object gets created and is stored in the security-context of Spring. I can also access the Authentication Object in the ZuulFilter.</p>
  
  <p>My Problem now is, that i had to tweek the "OAuth2ClientContext" to grab the users credentials from the servletRequest and put it on the "AccessTokenRequest". Otherwise I would have to hard-code them in the ResourceDetails, which is not appropriate in my case.</p>
  
  <p>The result is, that the ClientContext (and also AccessTokenRequest I guess) is shared between all users of the System. What i want is a session scoped Client Context, so that I can have multiple useres logged in and can access the right SecurityContext for each user on every request.</p>
  
  <p>So my question are,</p>
  
  <p>1) how can I make the ClientContext and AccessTokenRequest session scoped? </p>
  
  <p>2) Do I need to use Spring Session module? </p>
  
  <p>3) Do I need to set the sessionStrategy</p>
  
  <p>Thank you!</p>