Connecting to Service Now Oauth token endpoint from an API using Web Client and Proxy

Lindaseb
Mega Contributor

Hi all,

I am trying to implement  OAuth2 authentication for my API to connect to Service Now. It is connecting to Service Now using a Web Client. The API is registered as a OAuth application in Service Now and they have provided me the credentials. Since we are using "Password Credentials" as the grant-type, they have also created a username and password.


But I am getting a 401 unauthorized exception. 

@Bean
public WebClient serviceNowWebClient() {
String token = fetchAccessTokenSN(
appConfig.getServiceNowOAuthTokenUri(),
appConfig.getServiceNowAuthClientId(),
appConfig.getServiceNowOAuthClientSecret(),
appConfig.getSourceUsername(),
appConfig.getSourcePassword()
);
HttpClient httpClient = getHttpClient();
ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);

return WebClient.builder()
.clientConnector(connector)
.baseUrl(appConfig.getSourceBaseUrl())
.defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.build();
}

private HttpClient getHttpClient() {
int proxyPort = Integer.parseInt(appConfig.getProxyPort());
return HttpClient.create()
.proxy(proxy -> proxy.type(ProxyProvider.Proxy.HTTP)
.address(new InetSocketAddress(appConfig.getProxyHost(), proxyPort)))
.followRedirect(true);
}

public String fetchAccessTokenSN(String tokenUrl, String clientId, String clientSecret, String username, String password) {
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();

form.add("client_id", clientId);
form.add("client_secret", clientSecret);

form.add("username", username);
form.add("password", password);
form.add("grant_type", "password");


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

HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(form, headers);

SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
Proxy proxy = new Proxy(Proxy.Type.HTTP,
new InetSocketAddress(appConfig.getCollibraProxyHost(), Integer.parseInt(appConfig.getCollibraProxyPort())));
requestFactory.setProxy(proxy);

RestTemplate restTemplate = new RestTemplate(requestFactory);
log.info("%%%%%% Requesting token from URL: {}", tokenUrl);


ResponseEntity<Map> response = restTemplate.postForEntity(tokenUrl, request, Map.class);
if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
return (String) response.getBody().get("access_token");
}
throw new RuntimeException("Failed to fetch access token: " + response.getStatusCode());
}

The error I am getting is 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serviceNowWebClient' defined in class path resource [/servicenow/config/RequestClient.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.reactive.function.client.WebClient]: Factory method 'serviceNowWebClient' threw exception; nested exception is java.lang.RuntimeException: Failed to fetch access token due to client error: 401 Unauthorized: [no body]

Can anyone tell me what is wrong here? Is the proxy an issue?

0 REPLIES 0