Search code examples
javaspring-bootcertificatehttprequesttoken

OAuth 2.0 Access Tokens and Client Certificate


So I'm currently developing a Spring boot MS that needs to connect to an external API which has OAuth 2.0 implemented.

The API Store uses a custom version of a grant type called a Client Certificate.

This grant type uses a combination of Mutual SSL and Application level credentials.

It requires two identity factors:

  • Identity Factor 1 – Mutual SSL: Certificate created by me signed by the API store owner
  • Identity Factor 2 – Application Level Credentials: {consumerKey:consumerSecret}

The curl command for obtaining this token is:

curl -k -d "grant_type=client_cert" --basic -u "{consumer key}:{consumer secret}" -H "Content-Type: application/x-www-form-urlencoded" --cert {Certificate Pem} https://api.examplestore.com/token

How can I translate this to my Spring boot application?

I've currently written this piece of code, but I think I'm far off.

public void TokenRequest() {
    ResponseEntity<String> response = null;
    RestTemplate restTemplate = new RestTemplate();

    String credentials = String.format("%s:%s", consumerKey, consumerSecret);
    String encodedCredentials = new String(Base64.getEncoder().encodeToString(credentials.getBytes()));


    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

    //headers.setCertificate??

    headers.add("Authorization", "Basic " + encodedCredentials);

    HttpEntity<String> request = new HttpEntity<String>(headers);

    response = restTemplate.exchange(tokenUrl, HttpMethod.POST, request, String.class);

}

Any help is welcome. Thank you :)


Solution

  • I think you are not that far off.

    You defenitely need to include the body:

    HttpEntity<String> request = new HttpEntity<String>("grant_type=client_cert", headers);
    

    Also you need to include the certificate, maybe like this:

    SSLContext sslContext = SSLContextBuilder.create()
        .loadTrustMaterial(new URL("/path/to/your/cert"), "certpassword".toCharArray())    
        .setProtocol("yourProtocol")
        .build();
     
    final HttpClient httpClient = HttpClientBuilder.create()
            .setSSLContext(sslContext)
            .build();
    
        final ClientHttpRequestFactory requestFactory =
            new HttpComponentsClientHttpRequestFactory(httpClient);
    
    RestTemplate restTemplate = new RestTemplate(requestFactory);
    
    ...