Access TD Ameritrade API using Reactive Spring OAuth 2.0 Client with just refresh token

226 views Asked by At

I am trying to configure WebClient to access Oauth 2.0 token based TD Ameritrade protected resource without user interaction. I was able to do with Reddit client_credentials but unable to figure out using refresh_token for TD Ameritrade. Any ideas how to configure with Spring Security OAuth2.0 Client?

TD Ameritrade Protected Endpoint

https://api.tdameritrade.com/v1/accounts/<<account_number>>/transactions
Authorization: Bearer {{access_token}}

TD Ameritrade Access Token Endpoint

https://api.tdameritrade.com/v1/oauth2/token
grant_type: refresh_token
refresh_token: <<valid for 90days>> 
client_id: <<generated @ TD Ameritrade Dev Portal>>@AMER.OAUTHAP

Reference: https://developer.tdameritrade.com/content/authentication-faq

With below configuration, it is not requesting access token for TD Ameritrade and how to pass the refresh code when requesting access token.

application.yml

spring:
  security:
    oauth2:
      client:
        provider:
          td-ameritrade:
            token-uri: https://api.tdameritrade.com/v1/oauth2/token
          reddit:
            token-uri: https://ssl.reddit.com/api/v1/access_token
        registration:
          td-ameritrade:
            client-id:<<client id/key>>@AMER.OAUTHAP
            authorization-grant-type: refresh_token
          reddit:
            client-id: <<client-id>>
            client-secret:<<client-secret>>
            authorization-grant-type: client_credentials

Oauth2ClientConfiguration.java

@Configuration
public class Oauth2ClientConfiguration {

    @Bean("reddit-client")
    public WebClient redditWebClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
        ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
                authorizedClientManager);
        oauth.setDefaultClientRegistrationId("reddit");

        return WebClient.builder().filter(oauth).build();
    }

    @Bean("td-ameritrade-client")
    public WebClient tdWebClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
        ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
                authorizedClientManager);
        oauth.setDefaultClientRegistrationId("td-ameritrade");

        return WebClient.builder().filter(oauth).build();
    }

    @Bean
    public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
            ReactiveClientRegistrationRepository clientRegistrationRepository,
            ReactiveOAuth2AuthorizedClientService authorizedClientService) {

        ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder
                .builder().authorizationCode().refreshToken().clientCredentials().password().build();

        AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
                clientRegistrationRepository, authorizedClientService);
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

        return authorizedClientManager;
    }

}

ExternalServices.java

@Service
public class ExternalServices {

    @Autowired
    @Qualifier("td-ameritrade-client")
    private WebClient webClient;

    @Autowired
    @Qualifier("reddit-client")
    private WebClient redditWebClient;

    @Autowired
    private RedditConfigurationProperties redditConfigProperties;

    @Autowired
    private TdAmeritradeConfigurationProperties tdAmeritradeConfigProperties;

    public Mono<String> fetchTransactions() {
        return this.webClient
                .get()
                .uri(this.tdAmeritradeConfigProperties.getUrl())
                .retrieve()
                .bodyToMono(String.class);
    }

    public Mono<String> fetchComments() {
        return this.redditWebClient
                .get()
                .uri(this.redditConfigProperties.getUrl())
                .retrieve()
                .bodyToMono(String.class);
    }

}

Reference: https://docs.spring.io/spring-security/reference/reactive/oauth2/client/index.html

0

There are 0 answers