Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

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