title: OAuth2ClientContext is not accessible when handling /error
body: <p>I'm setting up a spring cloud application with OAuth2 sso. I have set up a spring boot application named user-service and provided an OAuth2 authentication server. </p>
  
  <p>I also set up another spring boot application named demo-service as a resource server application and have successfully gotten access to the demo-service in the scenario where my controllers do not throw any exceptions. </p>
  
  <p>But when my controllers throw an exception, I will receive a 401 Unauthorized response (said that I have provided an invalid token, but the log has illustrated that my controller has worked correctly and throw an exception) instead of a 500 Internal Error response with message about the exception. </p>
  
  <p>I have stepped into the source code of spring-security-oauth2 and spring-boot-autoconfigure-oauth2. I find that if my controllers throws an exception, the exception would be catched by the embeded tomcat server and forwarded to /error (which defined in application.yml with property server.error.path), but even if I set that /error needn't to be authenticated (I have confirmed that I can get access with /error without any credentials like access_token), I still cannot receive the 500 Internal Error.</p>
  
  <p>I have searched the google and found an issue in Github:<a href="https://github.com/spring-projects/spring-security-oauth2-boot/issues/84" rel="nofollow noreferrer">Issue 84</a>. After "solved" the issue, they suggested to add /error to not authenticate but it doesn't work on me.</p>
  
  <p>The version of spring-cloud I using is GreenWich.RELEASE, with dependency plugins, the Maven provided spring-security-oauth2:2.3.3.RELEASE and spring-boot-autoconfigure-oauth2:2.1.0.M4. Here are some related configurations:</p>
  
  <p>The dependencies I added to pom.xml</p>
  
  <pre><code>&lt;dependencies&gt;
          &lt;!-- Spring Boot --&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;!-- Spring Boot Web --&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;!-- Spring Cloud --&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
              &lt;artifactId&gt;spring-cloud-starter&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;!-- Eureka --&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
              &lt;artifactId&gt;spring-cloud-starter-eureka&lt;/artifactId&gt;
              &lt;version&gt;LATEST&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;!-- Security --&gt;
          &lt;dependency&gt;
          &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
          &lt;artifactId&gt;spring-cloud-starter-security&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;!-- OAuth2 --&gt;
          &lt;dependency&gt;
          &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
          &lt;artifactId&gt;spring-cloud-starter-oauth2&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;!-- MyBatis --&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.mybatis.spring.boot&lt;/groupId&gt;
              &lt;artifactId&gt;mybatis-spring-boot-starter&lt;/artifactId&gt;
              &lt;version&gt;LATEST&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;!-- MySQL--&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;mysql&lt;/groupId&gt;
              &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
              &lt;scope&gt;runtime&lt;/scope&gt;
          &lt;/dependency&gt;
      &lt;/dependencies&gt;
      &lt;dependencyManagement&gt;
          &lt;dependencies&gt;
              &lt;dependency&gt;
                  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                  &lt;artifactId&gt;spring-boot-dependencies&lt;/artifactId&gt;
                  &lt;version&gt;2.1.3.RELEASE&lt;/version&gt;
                  &lt;type&gt;pom&lt;/type&gt;
                  &lt;scope&gt;import&lt;/scope&gt;
              &lt;/dependency&gt;
              &lt;dependency&gt;
                  &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
                  &lt;artifactId&gt;spring-cloud-dependencies&lt;/artifactId&gt;
                  &lt;version&gt;Greenwich.RELEASE&lt;/version&gt;
                  &lt;type&gt;pom&lt;/type&gt;
                  &lt;scope&gt;import&lt;/scope&gt;
              &lt;/dependency&gt;
          &lt;/dependencies&gt;
      &lt;/dependencyManagement&gt;
  </code></pre>
  
  <p>The main class:</p>
  
  <pre><code>@SpringBootApplication
  @EnableDiscoveryClient
  @MapperScan(basePackages = {"demo.mapper"})
  public class DemoServiceApplication{
  
      public static void main(String[] args) {
          SpringApplication.run(DemoServiceApplication.class, args);
      }
  
  }
  </code></pre>
  
  <p>resource server configuration class:</p>
  
  <pre><code>@Configuration
  @EnableResourceServer
  public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
      @Autowired
      private ServerProperties serverProperties;
  
      @Override
      public void configure(HttpSecurity http) throws Exception {
          http
                  .authorizeRequests()
                  .antMatchers("/error").permitAll()
                  .anyRequest().authenticated();
      }
  }
  </code></pre>
  
  <p>a simple controller that will produce an exception:</p>
  
  <pre><code>@RestController
  public class DemoController{
      @GetMapping
      public void testMethod(){
      // this can be run correctly and get the right principal information from user-service
  
   //System.out.println(SecurityContextHolder.getContext().getPrincipal());
          throw new RuntimeException("some message wanted to see in 500 response");
      }    
  }
  </code></pre>
  
  <p>the application.yml. I think if I can get access with controller's methods, the yml configuration probaly has no errors.</p>
  
  <pre><code>server:
    port: 8002
  spring:
    application:
      name: demo-service
    datasource:
      # some jdbc configuration
  mybatis:
    #some mybatis configuration
  eureka:
    #eureka configuration
  
  security:
    oauth2:
      client:
        access-token-uri: http://localhost:8000/oauth/token
        client-id: webclient
        client-secret: webclientsecret
      resource:
        user-info-uri: http://localhost:8000/user/current
        prefer-token-info: false
        service-id: user-service
  logging:
    level:
      org: debug
  </code></pre>
  
  <p>If I send a request to /error directly, I can receive a correct json response(which was generated in BaseErrorController)
  But if I send to my controller and be forwarded to /error I got these:</p>
  
  <pre><code>{
      "error": "invalid_token",
      "error_description": "&lt;ACCESS_TOKEN&gt;"
  }
  </code></pre>
  
  <p>and an unusual log output:</p>
  
  <pre><code>DEBUG - [T2] o.a.coyote.http11.Http11InputBuffer      : Received [GET / HTTP/1.1
  Authorization: Bearer &lt;ACCESS_TOKEN&gt;
  User-Agent: PostmanRuntime/7.13.0
  Accept: */*
  Cache-Control: no-cache
  Host: localhost:8002
  cookie: JSESSIONID=&lt;JSESSIONID&gt;
  accept-encoding: gzip, deflate
  Connection: close
  
  ]
  ...
  ERROR - [T2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: some message wanted to see in 500 response] with root cause
  
  java.lang.RuntimeException: some message wanted to see in 500 response
      at demo.controller.DemoController.testMethod(DemoController.java:53) ~[classes/:na]
      ....
  
  DEBUG - [T2] o.a.c.c.C.[Tomcat].[localhost]           : Processing ErrorPage[errorCode=0, location=/error]
  ...
  DEBUG - [T2] o.s.security.web.FilterChainProxy        : /error at position 5 of 11 in additional filter chain; firing Filter: 'OAuth2AuthenticationProcessingFilter'
  DEBUG - [T2] o.s.b.a.s.o.r.UserInfoTokenServices      : Getting user info from: http://localhost:8000/user/current
   WARN - [T2] o.s.b.a.s.o.r.UserInfoTokenServices      : Could not fetch user details: class org.springframework.beans.factory.BeanCreationException, Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
  DEBUG - [T2] o.s.b.a.s.o.r.UserInfoTokenServices      : userinfo returned error: Could not fetch user details
  DEBUG - [T2] p.a.OAuth2AuthenticationProcessingFilter : Authentication request failed: error="invalid_token", error_description="&lt;ACCESS_TOKEN&gt;"
  DEBUG - [T2] o.s.b.a.audit.listener.AuditListener     : AuditEvent [timestamp=2019-06-06T04:59:03.634Z, principal=access-token, type=AUTHENTICATION_FAILURE, data={type=org.springframework.security.authentication.BadCredentialsException, message=&lt;ACCESS_TOKEN&gt;}]
  DEBUG - [T2] s.s.o.p.e.DefaultOAuth2ExceptionRenderer : Written [error="invalid_token", error_description="&lt;ACCESS_TOKEN&gt;"] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@9b22a11]
  DEBUG - [T2] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
  DEBUG - [T2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    :  Disabling the response for further output
  
  </code></pre>