HttpClientErrorException: 401 Unauthorized Exception in Tomcat - java

We are trying to access the Lithium Rest Api using HTTPS through Spring Rest Template as below
String plainCreds = lswUserName + ":" + lswPassword;
byte[] plainCredsBytes = plainCreds.getBytes();
byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
String base64Creds = new String(base64CredsBytes);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Creds);
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<String> sRawResp = restTemplate.exchange(completeURL.toString(), HttpMethod.GET, request, String.class);
Above code always gives
org.springframework.web.client.HttpClientErrorException: 401 Unauthorized Exception
There were no issues when invoking the same web service through postman, however when ever accessed through java code, getting the above 401 unauthorized exception
Previously I faced this issue with Windows OS, and I added below entry related to proxy in to catalina.bat:
JAVA_OPTS=%JAVA_OPTS% -Dhttp.proxyHost=hy**1.*****.co.in -Dhttp.proxyPort=8080`
Now we moved the entire setup to Linux OS and I get the same error. In Linux I don't have any proxy set. I checked through wget http://www.google.com and no proxy details are displayed.
How do I resolve this issue in Linux when no proxy is set?
Please Help.

Related

Java Spring boot - Rest Template (request with no response, no error)

I'm trying to create a GET request to retrieve commercial flights from latam. But I only get the answer through insomnia/postman...
I'm making the request through RestTemplate in Java, as shown below:
public class LatamRequest {
public void consumerAPILatam(){
RestTemplate template = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
//h.ttps://www.latamairlines.com/bff/air-offers/offers/search
UriComponents uri = UriComponentsBuilder.newInstance()
.scheme("https")
.host("www.latamairlines.com")
.path("bff/air-offers/offers/search")
.queryParam("sort","RECOMMENDED")
.queryParam("cabinType","Economy")
.queryParam("origin","GRU")
.queryParam("destination","BSB")
.queryParam("inFlightDate","null")
.queryParam("inFrom","null")
.queryParam("inOfferId","null")
.queryParam("outFlightDate","null")
.queryParam("outFrom","2022-11-15T15%3A00%3A00.000Z")
.queryParam("outOfferId","null")
.queryParam("adult","1")
.queryParam("child","0")
.queryParam("infant","0")
.queryParam("redemption","true")
.build();
headers.set("User-Agent", "test");
headers.set("Accept", "*/*");
headers.set("Content-Type", "application/json");
headers.set("X-latam-App-Session-Id", "84196897-1687-4d8c-8e63-083091ac204f");
headers.set("X-latam-Action-Name", "search-result.flightselection.offers-search");
headers.set("X-latam-Application-Name", "web-air-offers");
headers.set("X-latam-Client-Name", "web-air-offers");
headers.set("X-latam-Track-Id", "3a4ae189-e218-4606-bd9e-8b17efc93463");
headers.set("X-latam-Request-Id", "ff44ef24-e6d0-4cb0-984c-df1db18cee19");
headers.set("X-latam-Application-Country", "BR");
headers.set("X-latam-Application-Oc", "br");
headers.set("X-latam-Application-Lang", "pt");
HttpEntity<String> httpEntity = new HttpEntity<>(headers);
ResponseEntity<String> response = template.exchange(uri.toUriString(), HttpMethod.GET, httpEntity, String.class); //todo: No response, no error...
System.out.println(response);
}
}
I don't get any response or status after executing the above block. OBS: With the same parameters and headers I get status 200 in postman or insomnia.
I've tried several ways, but I can't get a response. Does anyone have any ideas for a more effective debug?
The reason that you don't get any response and no exception is because the server side gets your request and keeps holding it and doesn't respond. So you are still in a waiting mode. I ran your request from java code using different http client but used exact your params and I noticed that response never returns. I waited for over 10 minutes and I saw that the program was still running. So I modified the code and added connection timeout for 5 sec and read timeout for 30 seconds. When I ran it it I got read timeout exception after 30 seconds. So the code manages to connect to server side, but server side just doesn't respond. So you are in endless wait. So, I don't know why it works from postman. May be some headers values issues.

Gitlab API download file + RestTemplate

Please help with following problem.
When I try to do request to gitlab with Postman or curl everithing works fine, I got answer with the file
curl --header "PRIVATE-TOKEN: xxxxxxxx" "https://gitlabXXXX/api/v4/projects/13/repository/files/src%2Fcom%2Fgre%2Fjenkins%2FConstants.groovy?ref=foo"
But when I try to do the same in code I get error with this message = "404 File not found"
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("PRIVATE-TOKEN", "xxxxxxx");
System.out.println(restTemplate.exchange("https://gitlabXXXX/api/v4/projects/13/repository/files/src%2Fcom%2Fgre%2Fjenkins%2FConstants.groovy?ref=foo", HttpMethod.GET, new HttpEntity<>(httpHeaders), String.class).getBody());
Why it does not work? Maybe something in RestTempate change the URL or I do not know...
RestTemplate encodes your URL once again, so your request URL is:
https://gitlabXXXX/api/v4/projects/13/repository/files/src%252Fcom%252Fgre%252Fjenkins%252FConstants.groovy?ref=foo
So your % turns into %25 and this is not what gitlab API is waiting for.
Solution
You can use UriComponentsBuilder.build(true) method to tell your URI is already encoded:
String gitlabUriString = "https://gitlabXXXX/api/v4/projects/13/repository/files/src%2Fcom%2Fgre%2Fjenkins%2FConstants.groovy?ref=foo";
// true in build(true) tells parameters are already encoded
URI gitlabUri = UriComponentsBuilder.fromHttpUrl(gitlabUriString)
.build(true).toUri();
System.out.println(restTemplate.exchange(gitlabUri, HttpMethod.GET, new HttpEntity<>(httpHeaders), String.class).getBody());

Jenkins giving 403 in EC2 Server after passing the crumb in the request headers

i am using the CSRF Jenkins crumbs in the API call to create a new job in Jenkins from Java.
I tried the following
Called the API to get the crumb data
http://admin:11542c80972c3a2b863453d234de68b1d#10.139.163.33/crumbIssuer/api/json
I also tried with the below URL
http://10.139.163.33/crumbIssuer/api/json
The below is the JSON response obtained from the server
{"_class":"hudson.security.csrf.DefaultCrumbIssuer","crumb":"b272a09b604e7b7cc8ee1431f0a0143fa1422db2fb5f92955b0356a31da37463","crumbRequestField":"Jenkins-Crumb"}
In the next step, I am making a call to the Jenkins to create a new job with the header as
Jenkins-Crumb:b272a09b604e7b7cc8ee1431f0a0143fa1422db2fb5f92955b0356a31da37463
Jenkins is giving me 403, I am using HttpGet to get the token and using HttpPost with the header as above and sending to jenkins.
When i try with postman, it is not giving this error. I am running the Java application in 1 ec2 server and jenkins on another ec2 server.
There are no proxies, I also tried to use the various options like the enable proxy compatibilty, restarting jenkins etc, but not working.
Please give any pointers.
Java code used is
HttpPost postRequest = new HttpPost(url);
JenkinsCrumb crumb = jenkinsHelper.getCrumb();
String encodedPassword = Base64.getEncoder().encodeToString((user + ":" + pwd).getBytes());
postRequest.addHeader(HttpHeaders.AUTHORIZATION, "Basic " + encodedPassword);
postRequest.addHeader(new BasicHeader(crumb.getCrumbRequestField(), crumb.getCrumb()));
return postRequest;
The code to get the crumb is
String urlWithToken = "http://" + (user + ":" + pwd) + "#";
HttpGet request = new HttpGet(jenkinsBaseUrl.replace("http://", urlWithToken) + "crumbIssuer/api/json");
request.addHeader(HttpHeaders.AUTHORIZATION, "Basic " + encodedPassword);
CloseableHttpResponse httpResponse = httpClient.execute(request);
I have also tried with the CURL command and still getting the same response
I was able to fix this issue by using the same HttpClient (CloseableHttpClient) for both the CRUMB and the POST Request. Earlier, I was using 2 separate clients one for getting the crumb and new one for the posting of the data. Using a shared httpclient for both of these resulted in success state.
Hope this helps any other developer facing similar issue.

How to do OAuth 2 API call and get the response

I want to create a Spring boot application, that will call an API through OAuth2 process.
I've already checked this but can some explain it to me in a simple way.
All I have is the URL (that gets the Bearer token), Client ID and Client Secret.
Once the bearer token is retrieved I want to get the call the actual API with the retrieved bearer token put in the header, So I get the response.
In Spring,
you can use the RestTemplate.exchange method to make API calls.
Since the API is secured using an OAuth2.0 - Access token (bearer token),
the token must be passed in the "Authorization" header.
Try the code shown below to make an API call with header request:
String url = "https://you-api-url";
RestTemplate restTemplate = new RestTemplate();
// set the headers
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " + token_value);
HttpEntity entity = new HttpEntity(headers);
// send the GET request
HttpEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
// display the response
System.out.println("Response" + response.getBody());
Hope it helps!

Credentials for ActiveMQ/Jolokia/HawtIO through Java

I know the default password for 5.9.0's HawtIO/Jolokia is set in the \conf\ folder and is
admin/admin
system/manager
etc
However, none of those password are working when trying to execute the restful commands through Java:
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(null, -80), new UsernamePasswordCredentials("admin", "admin"));
CloseableHttpClient httpclient0 = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
URI uri0 = URI.create("http://localhost:8161/hawtio/auth/login/");
HttpGet httpget = new HttpGet(uri0);
HttpResponse r0 = httpclient0.execute(httpget);
System.out.println("Login form get: " + r0.getStatusLine());
for (Header h : r0.getAllHeaders())
System.out.println(h.getName() + "/" + h.getValue());
HttpEntity entity = r0.getEntity();
InputStream is0 = entity.getContent();
String resp = IOUtils.toString(is0);
System.out.println("Response0: " + resp);
The following code just spits back a 403 Forbidden reply! I've tried many combinations of username and passwords.
Login form get: HTTP/1.1 403 Forbidden
Access-Control-Allow-Origin/*
Content-Length/0
Server/Jetty(7.6.9.v20130131)
What works here?
I recall when running 5.8.0 that "admin/admin" worked, but I'd like to use 5.9.0 instead. It would be lame to back out of this version just because the username and password changed.
Further, which \conf file dictates this password...?
you've almost got it, you just need to POST to that URL instead of doing a GET. And you just set your username/password in the Authorization header. The authentication filter in hawtio avoids sending back a 401 as that makes the browser authentication prompt appear, hence why you don't see 401 returned instead.

Categories

Resources