Search code examples
javaspringspring-bootswaggerswagger-codegen

Consume OAuth2 secured REST API using swagger generated ApiClient


I am trying to use an ApiClient generated by swagger-codegen-maven-plugin (Version 3.0.0), to consume an OAuth2 secured REST API from within my spring boot application. The auth server (keycloak) provides a JWT and refresh token, but I cannot figure out how to best handle tokens in my bean. At the moment my bean looks like this:

@Configuration
public class SomeApiClientConfiguration {

    @Bean
    public SomeApi someApi() {
        return new SomeApi(apiClient());
    }

    @Bean
    public ApiClient apiClient() {
        ApiClient apiClient = new ApiClient();

        OAuth oAuth = (OAuth) apiClient.getAuthentication("auth");
        oAuth.setAccessToken("");

        return apiClient;
    }
}

Question is: What is the best approach for getting the token and handling the refresh token?

EDIT: In order to get the token I want to use client ID, username, and password. Grant type: Password Credentials.

Best,

Marc


Solution

  • I was able to solve this problem and want to share the solution for future reference:

    This is my SomeApiClientConfiguration:

    @Configuration
    public class SomeApiClientConfiguration{
    
        @Value("${app.api.url}")
        private String apiURL;
    
        @Bean
        public SomeApi someApi(OAuth2RestTemplate restTemplate) {
            return new SomeApi(apiClient(restTemplate));
        }
    
        @Bean
        public ApiClient apiClient(OAuth2RestTemplate restTemplate) {
            var apiClient = new ApiClient(restTemplate);
            apiClient.setBasePath(apiURL);
            return apiClient;
        }
    }
    

    Additionally I needed a SomeApiOAuth2Config class, which look as follows:

    @Configuration
    @EnableOAuth2Client
    public class SomeApiOAuth2Config {
    
        @Value("${app.api.client-id}")
        private String clientId;
    
        @Value("${app.api.token-endpoint}")
        private String accessTokenUri;
    
        @Value("${app.api.name}")
        private String username;
    
        @Value("${app.api.password}")
        private String password;
    
        @Bean
        public ClientHttpRequestFactory httpRequestFactory() {
            return new HttpComponentsClientHttpRequestFactory(httpClient());
        }
    
        @Bean
        public HttpClient httpClient() {
            var connectionManager = new PoolingHttpClientConnectionManager();
            var maxPoolSize = 1;
            connectionManager.setMaxTotal(maxPoolSize);
            // This client is for internal connections so only one route is expected
            connectionManager.setDefaultMaxPerRoute(maxPoolSize);
            return HttpClientBuilder.create().setConnectionManager(connectionManager).build();
        }
    
        @Bean
        public OAuth2ProtectedResourceDetails oauth2ProtectedResourceDetails() {
            var details = new ResourceOwnerPasswordResourceDetails();
            var resourceId = "";
            details.setId(resourceId);
            details.setClientId(clientId);
            var clientSecret = "";
            details.setClientSecret(clientSecret);
            details.setAccessTokenUri(accessTokenUri);
            details.setClientAuthenticationScheme(AuthenticationScheme.form);
            return details;
        }
    
        @Bean
        public AccessTokenProvider accessTokenProvider() {
            var tokenProvider = new ResourceOwnerPasswordAccessTokenProvider();
            tokenProvider.setRequestFactory(httpRequestFactory());
            return new AccessTokenProviderChain(
                Collections.<AccessTokenProvider>singletonList(tokenProvider)
            );
        }
    
        @Bean
        @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
        public OAuth2RestTemplate restTemplate(@Qualifier("oauth2ClientContext") OAuth2ClientContext oauth2ClientContext) {
        var template = new OAuth2RestTemplate(oauth2ProtectedResourceDetails(),     oauth2ClientContext);
            template.setRequestFactory(httpRequestFactory());
            template.setAccessTokenProvider(accessTokenProvider());
            template.getOAuth2ClientContext().getAccessTokenRequest().set("username", username);
            template.getOAuth2ClientContext().getAccessTokenRequest().set("password", password);
            return template;
        }
    }