Getting 403 error during GET request from Java application - java

I am trying to do a GET request with JAVA client using RestTemplate library, resulting in following error:
Exception in thread "main" org.springframework.web.client.HttpClientErrorException$Forbidden: 403 Forbidden
When I am trying to hit the same URL by command line it is working fine. Posting the cURL command and Java code snippet here.
cURL :
curl -X GET -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" https://xxxx-xxxx-xxxx {"key":"value"}
JAVA snippet :
String URL="https://xyz";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
//setting up the required headers
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.set("Authorization", "Bearer "+accessToken);
HttpEntity<String> entity = new HttpEntity<String>("body",headers);
//get request
ResponseEntity<String> responseEntity = restTemplate.exchange(URL, HttpMethod.GET, entity, String.class);
P.S - Is the issue because of the URL being a HTTPS one instead of HTTP ?

Add the user agent header, try and let us know if it works.
String URL="https://xyz";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
//setting up the required headers
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
//settting user agent
headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
headers.set("Authorization", "Bearer "+accessToken);
HttpEntity<String> entity = new HttpEntity<String>("body",headers);
//get request
ResponseEntity<String> responseEntity = restTemplate.exchange(URL, HttpMethod.GET, entity, String.class);

Related

Java - 422 Unprocessable Entity using RestTemplate

I have two services, Am trying to send a GET request from Service A, To make Service B send a Post request to Redmine Server.
Am getting 422 Unprocessable Entity: "{"errors":["Name cannot be blank","Identifier cannot be blank"]}"
And here is what I have already tried :
String url = "http://localhost:3001/projects.json"; //Redmine local server
RestTemplate restTemplate = new RestTemplate();
JSONObject object = new JSONObject(); //Json object that will need to be sent to redmine
object.put("name", "dummyName"); // Should look like this
object.put("identifier", "dummyId"); // {"project":{"identifier":"dummyId","name":"dummyName"}}
JSONObject body = new JSONObject();
body.put("project", object);
String plainCreds = "user:bitnami1"; // default basic auth encoding
byte[] plainCredsBytes = plainCreds.getBytes();
byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
String base64Creds = new String(base64CredsBytes);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Creds);
headers.add("Content-Type", "application/json");
RequestEntity<JSONObject> requestEntity = RequestEntity
.post(new URI(url))
.accept(MediaType.APPLICATION_JSON)
.headers(headers)
.body(body);
ResponseEntity<String> r = restTemplate.exchange(requestEntity, String.class);
This way am getting the same error, 422 Unprocessable Entity: "{"errors":["Name cannot be blank", "Identifier cannot be blank"]}"
And when I try to log.info the Request Entity to check it look ok
<POST http://localhost:3001/projects.json,{"project":{"identifier":"dummyId","name":"dummyName"}},[Accept:"application/json", Authorization:"Basic dXNlcjpiaXRuYW1pMQ==", Content-Type:"application/json"]>
Then I've Tried with entity , As the following
String url = "http://localhost:3001/projects.json"; //Redmine local server
RestTemplate restTemplate = new RestTemplate();
JSONObject object = new JSONObject(); //Json object that will need to be sent to redmine
object.put("name", "dummyName"); // Should look like this
object.put("identifier", "dummyId"); // {"project":{"identifier":"dummyId","name":"dummyName"}}
JSONObject body = new JSONObject();
body.put("project", object);
String plainCreds = "user:bitnami1"; // default basic auth encoding
byte[] plainCredsBytes = plainCreds.getBytes();
byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
String base64Creds = new String(base64CredsBytes);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Creds);
headers.add("Content-Type", "application/json");
HttpEntity<Object> entity = new HttpEntity<Object>(body, headers);
ResponseEntity<String> result = restTemplate.exchange("http://localhost:3001/projects.json",
HttpMethod.POST,
entity,
String.class);
The same result as earlier, When I log.info for entity-body I get the following
<{"project":{"identifier":"dummyId","name":"dummyName"}},[Authorization:"Basic dXNlcjpiaXRuYW1pMQ==", Content-Type:"application/json"]>
Tried To use NetCat to capture what is being sent, In both ways am not getting any body with restTemplate.exchange.
While debugging, It seems that the error came from RestTemplate.doExecute And I cant get why.
----Edit----
Am trying to connect to Redmine API to create new Project, More info can be found here And this is the curl command that successfully create new project
curl --location --request POST 'localhost:3001/projects.json' \
--header 'Authorization: Basic dXNlcjpiaXRuYW1pMQ==' \
--header 'Content-Type: application/json' \
--data-raw '{"project":{"identifier":"dummyId","name":"dummyName"}}'
What I am trying to do, Is to send a request From service A to my Service B so this request will be forwarded to redmine server.
For simplicity, I hard-coded the information in the code above (service B) just to make sure I can map this curl request, But it's not working.
Is there any suggested solution for this situation? Maybe an alternative approach ? Any suggestion would help.
Since your method would accept an object node as an input so you can do something like this:
String url = "http://localhost:3001/projects.json";
RestTemplate restTemplate = new RestTemplate();
Then you can set an HttpEntity like this:
HttpEntity<ObjectNode> entity = new HttpEntity<>(node, headers);
Then call exchange:
ResponseEntity<String> result = restTemplate.exchange("http://localhost:3001/projects.json",
HttpMethod.POST,
entity,
String.class);
I guess this will make your life easier.

400 Bad Request using postman copied request code

I have taken the request code from
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
String json = String.format("{'sex': %s,'age': %d,'evidence': []}", gender, age);
RequestBody body = RequestBody.create(mediaType, json);
Request request = new Request.Builder()
.url("https://api.infermedica.com/covid19/diagnosis")
.post(body)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "*/*")
.addHeader("App-Id", "XXXXXX")
.addHeader("App-Key", "XXXXXXXXXXXXXXXXXXXXX")
.addHeader("User-Agent", "PostmanRuntime/7.19.0")
.addHeader("Accept", "*/*")
.addHeader("Cache-Control", "no-cache")
.addHeader("Postman-Token", "58fbac21-182b-41e0-bceb-0905d0605858,cd9580e6-f262-4440-ba33-b85877dd087c")
.addHeader("Host", "api.infermedica.com")
.addHeader("Accept-Encoding", "gzip, deflate")
.addHeader("Content-Length", "56")
.addHeader("Connection", "keep-alive")
.addHeader("cache-control", "no-cache")
.build();
com.squareup.okhttp.Response response = client.newCall(request).execute();
I am attempting to make a post request. I have successfully run the request in postman. And I have copied the code from postman. But when I run the request in java I get a 400 Bad Request. And I dont know why because all of the headers and the body is exactly the same as in postman.
You are missing quotes for Sex in your input
Confirmed here https://developer.infermedica.com/docs/covid-19
curl "https://api.infermedica.com/covid19/diagnosis" \
-X "POST" \
-H "App-Id: XXXXXXXX" -H "App-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" -d '{
"sex": "male",
"age": 30,
"evidence": []
}'

Problem with spring RestTemplate POST request

Trying to make a post call on one of our servers, but getting 400 BAD_REQUEST all the time
static void postUserToken()
{
final String url = "SERVER ADDRESS";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
MultiValueMap<String, String> requestBody= new LinkedMultiValueMap<>();
requestBody.add("userName", "TESTUSER");
requestBody.add("password", "TESTPASSWORD");
requestBody.add("auth", "secEnterprise");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class );
System.out.println(response);
}
get request to the same address works, post request via Postman works fine with the same body and headers
what am I missing ?
EDIT
calls from postman
POST /api/call/ HTTP/1.1
Host: SEREVERADDRESS:6405
Content-Type: application/json
Accept: application/json
User-Agent: PostmanRuntime/7.15.0
Cache-Control: no-cache
Postman-Token: token1,token2
Host: SEREVERADDRESS:6405
accept-encoding: gzip, deflate
content-length: 92
Connection: keep-alive
cache-control: no-cache
{
"password": "PASSWORD",
"auth": "secEnterprise",
"userName": "USER"
}
in response I get an object like this {"token":"longtoken"}
You are using a MultiValueMap however the json you send from postman looks like a simple Map.
This will produce {"key1":["val1"]} instead of {"key1":"val1"}
The problem might be in the
headers.setContentType(MediaType.APPLICATION_JSON);
Try using headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); or convert your data to a proper JSON.
More on this: https://www.baeldung.com/rest-template (4.4. Submit Form Data)
As far as I understand the problem and since I do not know your rest call details, I provide below the approach you can try.
Remove the following line.
requestBody.add("auth", "secEnterprise");
Add the line
headers.setHeader("auth", "secEnterprise");
If you are using other version of Apache Http Client, you can use the following code snippet.
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("header-name" , "header-value");

Can get response from browser, but 401 unauthorized from resttemplate

Can get from the response from Chrome, but when I want to get it with resttemplate it gives me 401 response.
I try to add the exact Content Types with rest template but it still gives the 401 error.
here is the request that i get it from Chrome :
GET URL HTTP/1.1
Host: host
Connection: keep-alive
Cache-Control: max-age=0
Authorization: Basic auth
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en,de;q=0.9,tr;q=0.8
and here is the code that i used in java to connect the service :
RestTemplate restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_XHTML_XML, MediaType.APPLICATION_XML, MediaType.TEXT_HTML));
messageConverters.add(converter);
restTemplate.setMessageConverters(messageConverters);
HttpEntity<Map<String, String>> entity = new HttpEntity<>(params,createHeaders(username, password));
restTemplate.getForObject("URL",String.class, entity);
public static HttpHeaders createHeaders(String username, String password) {
String auth = username + ":" + password;
byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII")));
String authHeader = "Basic " + new String(encodedAuth);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("Authorization", authHeader);
return httpHeaders;
}
It appears to be a problem with encoding the authorization token generation.
If you are sure about the username and password is correct, the only possibility is that the method/encoding used to generate the token is different on the browser(or the UI application which is generating the token) and the implementation of your createHeaders() method.
Please refer to the below links for more details:
What encoding should I use for HTTP Basic Authentication?
https://github.com/request/request/issues/1334
Hope it'll help.

Translate authorized curl -u post request with JSON data to RestTemplate equivalent

I am using github api to create repositories using curl command as shown below and it works fine.
curl -i -u "username:password" -d '{ "name": "TestSystem", "auto_init": true, "private": true, "gitignore_template": "nanoc" }' https://github.host.com/api/v3/orgs/Tester/repos
Now I need to execute the same above url through HttpClient and I am using RestTemplate in my project.
I have worked with RestTemplate before and I know how to execute simple url but not sure how to post the above JSON data to my url using RestTemplate -
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// Create a multimap to hold the named parameters
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.add("username", username);
parameters.add("password", password);
// Create the http entity for the request
HttpEntity<MultiValueMap<String, String>> entity =
new HttpEntity<MultiValueMap<String, String>>(parameters, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
Can anyone provide an example how would I execute the above URL by posting JSON to it?
I have not had the time to test the code, but I believe this should do the trick. When we are using curl -u, to pass the credentials, it has to be encoded and passed along with the Authorization header, as noted here http://curl.haxx.se/docs/manpage.html#--basic. The json data, is simply passed as a HttpEntity.
String encoding = Base64Encoder.encode("username:password");
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Basic " + encoding);
headers.setContentType(MediaType.APPLICATION_JSON); // optional
String data = "{ \"name\": \"TestSystem\", \"auto_init\": true, \"private\": true, \"gitignore_template\": \"nanoc\" }";
String url = "https://github.host.com/api/v3/orgs/Tester/repos";
HttpEntity<String> entity = new HttpEntity<String>(data, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity , String.class);

Categories