title: Spring fails for userinfo endpoint returning signed JWT
body: <p>We're working on a Spring Boot application that is an OIDC client. The identity provider (IdP) is a third-party service and fully OpenID Connect and OAuth 2.0 compliant (as far as we can tell). As it's built with high security in mind, its <em>UserInfo</em> endpoint returns a <em>signed</em> JWT (instead of a regular one).</p>
  
  <p>It seems that Spring Security does not support it. The authentication flow ends with an error message (displayed in an HTML page generated by our Spring application):</p>
  
  <blockquote>
    <p>[invalid_user_info_response] An error occurred while attempting to
    retrieve the UserInfo Resource: Could not extract response: no
    suitable HttpMessageConverter found for response type
    [java.util.Map] and content type
    [application/jwt;charset=UTF-8]</p>
  </blockquote>
  
  <p>My questions:</p>
  
  <ul>
  <li>Is it correct that Spring does not currently support <em>UserInfo</em> endpoints returning signed JWTs?</li>
  <li>If so, how can we add support for signed JWTs (including verfication of the signature)?</li>
  </ul>
  
  <p>Our analysis has shown that the <code>DefaultOAuth2UserService</code> requests (<code>Accept: application/json</code>) and expects a JSON response from the IdP. However, being configured for high security, the IdP returns a signed JWT with the content type <code>application/jwt</code>. The response looks like the example on <a href="https://jwt.io/#debugger-io" rel="nofollow noreferrer">jwt.io</a>. As the <code>RestTemplate</code> has no message converter capable of handling the content type <code>application/jwt</code>, the authenticaton fails.</p>
  
  <p>Our sample app is as simple as it gets:</p>
  
  <p><strong>build.gradle</strong></p>
  
  <pre><code>plugins {
      id 'java'
      id 'org.springframework.boot' version '2.2.4.RELEASE'
      id 'io.spring.dependency-management' version '1.0.9.RELEASE'
  }
  
  group = 'com.example'
  version = '0.0.1-SNAPSHOT'
  sourceCompatibility = '11'
  
  repositories {
      mavenCentral()
  }
  
  dependencies {
      implementation 'org.springframework.boot:spring-boot-starter-web'
      implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
  }
  </code></pre>
  
  <p><strong>DemoApplication.java</strong></p>
  
  <pre><code>package demo;
  
  import org.springframework.boot.SpringApplication;
  import org.springframework.boot.autoconfigure.SpringBootApplication;
  
  @SpringBootApplication
  public class DemoApplication {
      public static void main(String[] args) {
          SpringApplication.run(DemoApplication.class, args);
      }
  }
  </code></pre>
  
  <p><strong>application.yml</strong></p>
  
  <pre><code>server:
    port: 8081
  
  spring:
    security:
      oauth2:
        client:
          registration:
            demo:
              client-id: our-client-id
              client-secret: our-client-secret
              clientAuthenticationMethod: post
              provider: our-idp
              scope:
                - profile
                - email
          provider:
            our-idp:
              issuer-uri: https://login.idp.com:443/idp/oauth2
  </code></pre>
  
  <p><strong>HomeController.java</strong></p>
  
  <pre><code>package demo;
  
  
  import org.springframework.web.bind.annotation.GetMapping;
  import org.springframework.web.bind.annotation.RestController;
  
  @RestController
  public class HomeController {
      @GetMapping("/")
      String hello() { return "hello"; }
  }
  </code></pre>