I am using Spring Rest Template inside a Spring Boot Application.
I always get 401 Unauthorized error even though I am passing the credentials.
I am able to access this service by Chrome REST Web Service Client.
Is there a simplified way to access the REST template in SpringBoot.
Below is the code snippet done so far which results in 401 error
private DetailsBean invokeDetailsRestService(UserParam userParam){
ResponseEntity<DetailsBean> responseEntity = null;
String url = "https://dev.com/app/identifyuser/";
RestClientConfig restClientConfig =new RestClientConfig("user123","pass123");
responseEntity= restClientConfig.postForEntity(url, userParam, DetailsBean.class);
log.debug("User Details : {} ", responseEntity.getBody());
return responseEntity.getBody();
}
public ClientHttpRequestFactory getRequestFactory(String userName,String password){
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials( new AuthScope(null, -1), new UsernamePasswordCredentials(userName,password) );
HttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
return new HttpComponentsClientHttpRequestFactory(httpClient);
}
RestClientConfig class
public RestClientConfig(String username, String password) {
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(null, -1),
new UsernamePasswordCredentials(username, password));
HttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
}
Error:
WARN c7af55b5-1cac-4db6-a202-202416c27ba4
12612 --- [apr-8082-exec-8] o.a.http.impl.auth.HttpAuthenticator
: NEGOTIATE authentication error:
No valid credentials provided (Mechanism level:
No valid credentials provided (Mechanism level:
Failed to find any Kerberos tgt))
The authorization issue was fixed with the below code..
Credentials should be passed to a Spring REST Template with the below code:
String userAndPass = "Test:Test123";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
headers.add("Authorization", "Basic " + Base64Utility.encode(userAndPass.getBytes()));
I faced similar issue when i'm trying to make call to webservice, this solved my issue:
restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor("userName", "password"));
restTemplate.postForObject('','',''');
Pass the credentials like this, it should solve the issue.
I used spring boot 2.2.4.RELEASE version. then I work below way.
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(username, password));
RequestDto requestDto = new RequestDto();
// set parameter
ResponseDto response = restTemplate.postForObject(URL, requestDto, ResponseDto.class);
Or
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(username, password);
RequestDto requestDto = new RequestDto();
// set parameter
HttpEntity<RequestDto> request = new HttpEntity<>(requestDto, headers);
ResponseDto response = restTemplate.postForObject(URL, request, ResponseDto.class);
Related
I tried to call oauth 2 using Spring RestTemplate but ended up with this error 404 Not Found: [{"message":"no Route matched with those values"}]
below is my code .OauthRequest is class created by me .
String oauthurl = serverurl + GET_TOKEN;
HttpHeaders headers = buildHeader();
OauthRequest oathRequest = new OauthRequest();
oathRequest.setClient_id(clientid);
oathRequest.setClient_secret(clientsecret);
oathRequest.setAuthenticated_userid(usercode);
oathRequest.setScope(scope);
oathRequest.setGrant_type(grantTypePassword);
oathRequest.setProvision_key(key);
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Host", hostname);
headers.set("Accept-Version", "1.0");
headers.set("Content-Length", MAX_TRANSFER_SIZE);
HttpEntity<OauthRequest> requestEntity = new HttpEntity<>(oathRequest, headers);
ResponseEntity<OauthResponse> result = restTemplate.exchange(oauthurl, HttpMethod.POST, requestEntity,
OauthResponse.class);
return result.getBody();
Is there any limitation on calling from RestTemplate rather than using OAuth2RestTemplate .My understanding is it will be achievable using RestTemplate also.Must i use OAuth2RestTemplate ?Any help?
RestTemplate does not set hostname in
headers.set("Host", hostname);
Adding below it worked
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
I want to push some archived files into GITHub from my local spring application.
repos/{:user}/{:repo}/git/refs/heads/{:branchname}
{
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("XXXXXX", 8080));
requestFactory.setProxy(proxy);
RestTemplate restTemplate = new RestTemplate(requestFactory);
String url = new String("https://api.github.com/repos/XXX/MyApplication/git/refs/heads/XXX");
Map<String, String> req = new HashMap<String,String>();
req.put("sha", "9a7fd370e28ea7a4bc8242e7f234s5ed07042cb88");
String jsonObject = JSONParser.quote(payload);
HttpEntity<Object> httpEntity = new HttpEntity<>(headers1);
restTemplate.exchange(url, HttpMethod.POST,httpEntity,Object.class);
}
Error: Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 404 Not Found
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:700)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:653)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:531)
Using the below POST API, I get '404 not found error'.
Method : POST
URL : https://api.github.com/repos/{:user}/{:repo}/git/refs/heads/{:branchname}
{
"sha": "{:new-commit-sha}"
}
Can you any one provide sample Spring RestTemplate implementation for above api?
i found issue in above scenario. for this above POST client userId and password in Headers and it is wrong.
we need to provide userId and Password in BasicAutherizationInceptors class like below.
resttemplate.getInterceptors().add(new BasicAutherizationInterceptor(userId,Pwd));
Please don't mistake it as already asked question. The main difference here is, this issue is coming in Get method call. All the solutions discussed here or other places talks about either POST method or multipart form data.
Configuration I have provided is as below:
String url = env.getProperty(ApplicationConstants.PMCC_MANAGER_REGION_QUERY_URL);
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url).queryParam("inTIS_PMA_NUMBER","ALL");
URI uri = builder.build().toUri();
RestTemplate restTemplate = getRestTemplateBuilder().build();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
private RestTemplateBuilder getRestTemplateBuilder() {
Integer connectionTimeOut = 2000;
Integer readTimeOut = 3000;
RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder();
restTemplateBuilder.setConnectTimeout(connectionTimeOut);
restTemplateBuilder.setReadTimeout(readTimeOut);
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setBufferRequestBody(false);
restTemplateBuilder.requestFactory(factory);
return restTemplateBuilder;
}
This code is part of Spring Boot application and deployed in WebLogic server.
Background
I am trying to consume a REST endpoint hosted on IBM Cloud API from my SpringBoot application using RestTemplate. I am using the following snippet to make the call:
RestTemplate send = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setCacheControl(CacheControl.noCache());
headers.set("x-ibm-client-id", clientId);
headers.set("x-ibm-client-secret", clientSecret);
HttpEntity<BodyEntity> httpEntity = new HttpEntity<>(bodyEntity, headers);
send.exchange(ENDPOINT_URL, HttpMethod.POST, httpEntity, Object.class);
I used the following snippet to configure RestTemplate
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
Problem
Using this snippet, when the call is made I receive 401 Unauthorized. When I made the same call using Postman, I received correct response from server without any problem.
Since I received 401 response code I set to further investigate the request by logging headers and body and other parts of request.
I implemented ClientHttpRequestInterceptor to log outgoing requests to further debug the issue and added this interceptor to my RestTemplate config as follows:
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
// new code
builder.interceptors(new LoggingClientHttpRequestInterceptor());
return builder.build();
}
After making the request again, I could see in the log that the outgoing call contained all details as it should e.g. Headers and Body were correct.
After this, I changed the whole thing to use Apache HTTP Client as follows:
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(URL);
String reqString = "BODY";
httpPost.setEntity(new StringEntity(reqString, ContentType.APPLICATION_JSON));
httpPost.setHeader("accept", "application/json");
httpPost.setHeader("content-type", "application/json");
httpPost.setHeader("cache-control", "no-cache");
httpPost.setHeader("x-ibm-client-id", clientId);
httpPost.setHeader("x-ibm-client-secret", clientSecret);
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
System.out.println("Response status: " + response.getStatusLine());
HttpEntity entity1 = response.getEntity();
System.out.println("Response :" + entity1.toString());
} finally {
response.close();
}
Using the snippet above, I executed the request and received correct response.
Question
Why RestTemplate call returns and error whereas HttpClient returns correct response?
Do I need to further configure RestTemplate?
What have I missed?
I need to authenticate against OAuth2.0 Microsoft Dynamics CRM from a background Java application; background because it's an integration app between the ERP of the customer and its Dynamics online instance.
I tried to use spring-security-oauth2 classes to get an high level set of resource to handle authentication, but i can't retrieve the initial token, while I'm successful if I try with building "manually" the http requests needed.
I wrote a simple Java application to test the authentication and I had this piece of code working, with content that is the String representation of the access token JSon:
String accessTokenURL = "https://login.microsoftonline.com/common/oauth2/token";
CloseableHttpClient client = HttpClients.createDefault();
HttpPost requestToken = new HttpPost(accessTokenURL);
requestToken.addHeader("Cache-Control", "no-cache");
requestToken.addHeader("Content-Type", "application/x-www-form-urlencoded");
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("grant_type", "password"));
params.add(new BasicNameValuePair("client_id", clientId));
params.add(new BasicNameValuePair("resource", resource));
params.add(new BasicNameValuePair("username", username));
params.add(new BasicNameValuePair("password", password));
params.add(new BasicNameValuePair("client_secret", clientSecret));
requestToken.setEntity(new UrlEncodedFormEntity(params));
CloseableHttpResponse response = client.execute(requestToken);
InputStream is = response.getEntity().getContent();
String content = IOUtils.toString(is);
System.out.println(content);
client.close();
resource is the Dynamics online instance of the customer.
I tried something similar using Spring Security OAuth2 client classes but I always get "401 Unauthorized":
ResourceOwnerPasswordResourceDetails resourceObj = new ResourceOwnerPasswordResourceDetails();
resourceObj.setClientId(clientId);
resourceObj.setClientSecret(clientSecret);
resourceObj.setGrantType("password");
resourceObj.setAccessTokenUri(accessTokenURLWithResource);
// resourceObj.setId(resource);
resourceObj.setTokenName("bearer_token");
resourceObj.setUsername(username);
resourceObj.setPassword(password);
AccessTokenRequest atr = new DefaultAccessTokenRequest();
Map<String, List<String>> headersMap = new HashMap<String, List<String>>();
headersMap.put("Cache-Control", Arrays.asList("no-cache"));
headersMap.put("Content-Type", Arrays.asList("application/x-www-form-urlencoded"));
atr.add("client_id", clientId);
atr.add("resource", resource);
atr.add("client_secret", clientSecret);
atr.add("username", username);
atr.add("password", password);
OAuth2ClientContext context = new DefaultOAuth2ClientContext(atr);
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceObj, context);
OAuth2AccessToken token = restTemplate.getAccessToken();
System.out.println(new Gson().toJson(token));
I tried using different ways to pass the access token URL and resource but the result is always the same.
Any help or any other advice about other high level library to be used in this case are appreciated, thanks.
Thanks to some hints of #fateddy I came to a solution. This piece of code works, now I'll try to integrate in my application
ResourceOwnerPasswordResourceDetails resourceObj = new ResourceOwnerPasswordResourceDetails();
// resourceObj.setClientId(clientId);
// resourceObj.setClientSecret(clientSecret);
resourceObj.setGrantType("password");
resourceObj.setAccessTokenUri(accessTokenURLWithResource);
// resourceObj.setId(resource);
resourceObj.setTokenName("bearer_token");
// resourceObj.setUsername(username);
// resourceObj.setPassword(password);
AccessTokenRequest atr = new DefaultAccessTokenRequest();
Map<String, List<String>> headersMap = new HashMap<String, List<String>>();
headersMap.put("Cache-Control", Arrays.asList("no-cache"));
headersMap.put("Content-Type", Arrays.asList("application/x-www-form-urlencoded"));
atr.add("client_id", clientId);
atr.add("resource", resource);
atr.add("client_secret", clientSecret);
atr.add("username", username);
atr.add("password", password);
OAuth2ClientContext context = new DefaultOAuth2ClientContext(atr);
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceObj, context);
OAuth2AccessToken token = restTemplate.getAccessToken();
System.out.println(new Gson().toJson(token));