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