Skip to content

Support OAuth2 client authentication using X.509 certificate #4498

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jgrandja opened this issue Aug 16, 2017 · 11 comments
Closed

Support OAuth2 client authentication using X.509 certificate #4498

jgrandja opened this issue Aug 16, 2017 · 11 comments
Assignees
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: enhancement A general enhancement

Comments

@jgrandja
Copy link
Contributor

jgrandja commented Aug 16, 2017

The client should have the ability to authenticate with the Authorization Server using X.509 certificate.

See RFC 8705 OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens

** UPDATE ** (April 23, 2024):

Closing this issue as there are no enhancements required to the framework code as mTLS client authentication is possible by simply configuring the underlying HTTP Client.

The various OAuth2AccessTokenResponseClient implementations already expose a setRestOperations(RestOperations restOperations) method and it is the applications responsibility to configure RestTemplate and it's associated ClientHttpRequestFactory to provide HTTPS-enabled connectors. This is typically configured using a KeyStore that contains the client's X509Certificate.

The same rules apply for WebClient, as the application is responsible for configuring the underlying ClientHttpConnector.

See the Demo Sample in Spring Authorization Server, as the demo-client sample provides example configurations for RestTemplate and WebClient using a keystore.p12 file.

@jgrandja jgrandja added the in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) label Aug 16, 2017
@myspri
Copy link

myspri commented Oct 30, 2017

Hello @jgrandja, I have been talking to some security experts(OpenID/OAuth2 spec writers) and got the feedback that using MTLS is the most desirable form of client authentication.

https://tools.ietf.org/html/draft-ietf-oauth-mtls-03

Was wondering if this is still in your radar.
Thanks!

@jgrandja
Copy link
Contributor Author

@myspri Apologize for the delayed response. Yes, we are still planning on implementing this feature. However, we have not scheduled it as of yet.

@jgrandja jgrandja added this to the 5.1.0.M1 milestone Dec 12, 2017
@rwinch rwinch modified the milestones: 5.1.0.M1, 5.1.0.RC1 Dec 19, 2017
@jgrandja jgrandja removed this from the 5.1.0.M2 milestone Jul 24, 2018
@rwinch rwinch added type: enhancement A general enhancement and removed New Feature labels May 3, 2019
@hablutzel1
Copy link

Note that the spec has became the standard RFC 8705, "OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens".

In the other hand, there are already some open source implementations like the one from IdentityServer4 (see https://github.com/IdentityServer/IdentityServer4/tree/master/samples/Clients/src/ConsoleMTLSClient).

@maskedpirate
Copy link

Any updates on if this has been scheduled?

@rwinch
Copy link
Member

rwinch commented Jul 8, 2020

@maskedpirate No updates. Would you be interested in submitting a pull request?

@jgrandja jgrandja added this to the 5.5.x milestone Jul 9, 2020
@praveenbommali
Copy link

any update !!!

@greghall76
Copy link

greghall76 commented Jun 27, 2022

I'd love to hear an update on this. I'm interested in running in OpenShift w/ their internal OAuth server. From looking at their oauth-proxy sidecar, I believe OpenShift's OAuth server is expecting a k8s service account client crt as the auth method.

@rwinch rwinch changed the title Support client authentication using X.509 certificate Support OAuth2 client authentication using X.509 certificate Aug 11, 2022
@rwinch
Copy link
Member

rwinch commented Aug 11, 2022

No updates at this time.

@magnuskkarlsson
Copy link

magnuskkarlsson commented Aug 23, 2023

I think I got it to work in Spring Boot 3

All feedback are welcome!

You need to set

spring.security.oauth2.client.registration.keycloak.client-authentication-method = none

so you send client_id in request body, otherwise will the Authorization Server never know from which client the request comes from.

Then add custom truststore and keystore for accessTokenResponseClient. The solution is quite long since Apache HttpComponents HttpClient, ignores standard Java truststore (-Djavax.net.ssl.trustStore) and keystore (-Djavax.net.ssl.keyStore). Otherwise we would be done by only setting client-authentication-method = none

`
@bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http //
...
.oauth2Client(oauth2Client -> oauth2Client //
.authorizationCodeGrant(authorizationCodeGrant -> authorizationCodeGrant //
.accessTokenResponseClient(this.accessTokenResponseClient())));
return http.build();
}

private OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient() {
    DefaultAuthorizationCodeTokenResponseClient accessTokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient();

    // org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient
    RestTemplate restTemplate = new RestTemplate(
            Arrays.asList(new FormHttpMessageConverter(), new OAuth2AccessTokenResponseHttpMessageConverter()));
    restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
    try {
        // https://github.com/apache/httpcomponents-client/blob/5.2.x/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientCustomSSL.java
        SSLContext sslContext = new SSLContextBuilder() //
                .loadKeyMaterial(Path.of(keyStore), keyStorePassword.toCharArray(), keyStorePassword.toCharArray()) //
                .loadTrustMaterial(Path.of(trustStore), trustStorePassword.toCharArray()) //
                .build();

        final SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder.create() //
                .setSslContext(sslContext) //
                .build();

        final HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create() //
                .setSSLSocketFactory(sslSocketFactory) //
                .build();

        CloseableHttpClient httpClient = HttpClients.custom() //
                .setConnectionManager(cm) //
                .build();

        // "uses https://hc.apache.org/httpcomponents-client-ga Apache HttpComponents HttpClient to create requests"
        ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
        restTemplate.setRequestFactory(requestFactory);
    } catch (Exception e) {
        e.printStackTrace();
    }
    accessTokenResponseClient.setRestOperations(restTemplate);
    return accessTokenResponseClient;
}

`

Complete example https://github.com/magnuskkarlsson/spring-boot-3-oauth2-login-keycloak-mtls

@magnuskkarlsson
Copy link

I concluded wrong about Apache HttpClient v5 and org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient

It does not ignore Java truststore (-Djavax.net.ssl.trustStore) and keystore (-Djavax.net.ssl.keyStore) and hence all that is required for mTLS Access Token Request in Authorization Code Flow are:

spring.security.oauth2.client.registration.keycloak.client-authentication-method = none
and java -Djavax.net.ssl.trustStore -Djavax.net.ssl.keyStore ... -jar myjar.jar

@jgrandja
Copy link
Contributor Author

Closing. Please see comment for update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

9 participants