OkHttpClient - Sending a get request with Bearer token fails due to auth - java

I'm using OkHttpClient in a Java service and I'm trying to send a get request with an Authorization header.
For some reason, the below fails with response code 401 as if the token isn't sent within the headers.
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder();
.url(url)
.header("Authorization", "Bearer " + token)
.build();
var response = client.newCall(request).execute()
I also tried out using the headers builder param and passing a Headers object containing Authorization Bearer some-token, and also tried with addHeader("Authorization", token) but same happens.
OkHttpClient version: 4.9.2
What's wrong with the above code? Is OkHttpClient stripping off the Authorization header for some reason?

Related

How to send a Request Body in GET method using the Java 11 HttpClient library?

I have to request data from an API but the API needs a JSON in the request body and it has to be sent using the GET method. My project uses the Java 11 HttpClient library so I want solutions that only include using this library. How do I send the body in GET method?
HttpRequest request = HttpRequest.newBuilder(uri)
.header("Content-Type", "application/json")
.GET(BodyPublishers.ofString(jsonObject.toString()))
.build();
HttpClient client = AppHttpClient.getInstance();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
Code issue
Builder class doesn't have a predefined GET method with the ability to pass request body. In this case just use more generic approach:
HttpRequest request = HttpRequest.newBuilder(uri)
.header("Content-Type", "application/json")
.method("GET", BodyPublishers.ofString(jsonObject.toString()))
.build();
HttpClient client = AppHttpClient.getInstance();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
General
Usually, passing body in the GET request is not recommended, so I would recommend reconsidering your API design. Instead of a body, you can use URL query parameters or think about using the POST method if the request body is quite big and can't be mapped to the query parameters.

Grant_type missing in request

I'm trying to get token access (protocol oauth2) to dynamics 365.
That's the code that build and execute the http post request:
URI uri = new URIBuilder()
.setScheme("https")
.setHost("login.microsoftonline.com")
.setPath("/"+PropertyUtils.getInstance().getProperty("AD_TENANT_ID")+"/oauth2/token")
.setParameter("grant_type", "client_credentials")
.setParameter("client_id", PropertyUtils.getInstance().getProperty("CLIENT_ID"))
.setParameter("resource", PropertyUtils.getInstance().getProperty("RESOURCE"))
.setParameter("client_secret", PropertyUtils.getInstance().getProperty("CLIENT_SECRET"))
.build();
HttpPost post = new HttpPost(uri);
HttpResponse response = client.execute(post);
the response json is:
{"error":"invalid_request","error_description":"AADSTS900144: The request body must contain the following parameter: 'grant_type'.\r ...
why response tell me that grant_type is missing when it's in the request as a parameter?
You are trying to perform the request putting those parameters in the URI as query parameters. Although those parameters needs to be put in the body of the request as form url encoded.
{"Content-Type": "application/x-www-form-urlencoded"}

ERROR in JSON Header while writing in JAVA

I'm getting error while posting JSON data in java, error states that, unable to find valid certification path to requested target.
I feel it's because of Authorization.
Can anyone please guide me how to write Authorization header in JSON for JAVA..
Share your code and detail explanation.
Below is the code to add header in request using okhttp.
private final OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("add api url")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "add auth header here")
.build();
For reference here

How to get response from GET-request to API in okhttp?

How can i get some response from API through GET-request?
The way i'm sending GET:
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(5, TimeUnit.SECONDS);//Connect timeout
client.setReadTimeout(5, TimeUnit.SECONDS);//Socket timeout
Request request = new Request.Builder().url(String.valueOf(message)).build();
Response response = client.newCall(request).execute();
The way i'm trying to get response:
response.message();
What i get:
OK
What i need to get from API:
OK|ID (Example: OK|2122988149)
You should try:
response.body().string()

failure : retrofit.RetrofitError: 307 Temporary Redirect?

I am using the library com.squareup.retrofit:retrofit:1.9.0, in order to send data to my server from my android Application.
In fact,when I want to send a request to the server, I found this error:
failure : retrofit.RetrofitError: 307 Temporary Redirect
I try many idea but the same problem persist.
Please Expert help me to resolve this issue.
Regards
Edit: if you must not use Retrofit 1.9, switching to a newer version (ie 2.0+) should handle the solution covered below automatically.
Looks like your HTTP client (on Android side) should handle this redirection by reading the Location value in the response header you are receiving when this happens, which supposed to contain a target redirection URL you ought to hit from the client again.
See their comment here.
So for now you need to implement this at the application level (which
is hard with Retrofit 1, easier with the forthcoming Retrofit 2) or
wait until OkHttp 3.1(ish) when we implement the newest spec.
See also what 307 means.
Fixing 307 errors - general The 307 response from the Web server
should always include an alternative URL to which redirection should
occur. If it does, a Web browser will immediately retry the
alternative URL. So you never actually see a 307 error in a Web
browser, unless perhaps you have a corrupt redirection chain e.g. URL
A redirects to URL B which in turn redirects back to URL A. If your
client is not a Web browser, it should behave in the same way as a Web
browser i.e. immediately retry the alternative URL.
If the Web server does not return an alternative URL with the 307
response, then either the Web server sofware itself is defective or
the Webmaster has not set up the URL redirection correctly.
See javadoc for Retrofit 1.9.0 to grab the Location header value(URL) from response;
http://static.javadoc.io/com.squareup.retrofit/retrofit/1.9.0/retrofit/client/Response.html#getHeaders--
// omitting null check for brevity
for (Header header : response.getHeaders())
{
if (header.getName().equals("Location")) {
redirectURL = header.getValue();
}
}
// do a redirect to redirectURL
I got the solution after a lot of efforts. May be this will help you. If you are getting this error "203 HTTP 307 Temporary Redirect" then this trick will help you.
Append '/' to your web service at the end and then check this error goes away. I don't know the reason behind this but it works for me.
For me, my old request web service: https://mydomain/rest/Search.
Using this URL I was getting "203 HTTP 307 Temporary Redirect" where I was able to get a response in POSTMAN and web browser.
My new request web service with the trick: https://mydomain/rest/Search/.
This '/' resolve the issue.
You are Using Old dependency
Change your dependency from
"com.squareup.retrofit:retrofit:1.9.0"
to
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
compile 'com.squareup.okhttp3:okhttp:3.4.1'
also add this dependency to get full log
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'.
Add this method in your Retrofit Client Class
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.connectTimeout("Your_Time", TimeUnit.SECONDS);
httpClient.readTimeout("Your_Time", TimeUnit.SECONDS);
httpClient.addInterceptor(logging);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("BASE URL")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
Below code is to Handle the Http protocol Exception
public Response post(String url, String content) throws IOException {
RequestBody body = RequestBody.create(PROTOCOL, content);
Request.Builder requestBuilder = new Request.Builder().url(url).post(body);
Request request = requestBuilder.build();
Response response = this.client.newCall(request).execute();
if(response.code() == 307) {
String location = response.header("Location");
return post(location, content);
}
return response;
}
If you want to handle all 307 responses, you can create and add an Interceptor to do the job; This interceptor simply creates a new request with the new path which is indicated in the response header "location".
val client = OkHttpClient.Builder()
.addInterceptor {
val request = it.request()
val response = it.proceed(request)
if (response.code() == 307) {
val url = HttpUrl.Builder()
.scheme(request.url().scheme())
.host(request.url().host())
.addPathSegment(response.header("location", request.url().url().path)?: "")
.build()
val newRequest = Request.Builder()
.method(request.method(), request.body())
.url(url)
.headers(request.headers())
.build()
return#addInterceptor it.proceed(newRequest)
}
response
}
.build()
Retrofit.Builder().client(client).build()
Solution 1
You can create an extra interceptor to handle 307
private static class RedirectInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(chain.request());
if (response.code() == 307) {
request = request.newBuilder()
.url(response.header("Location"))
.build();
response = chain.proceed(request);
}
return response;
}
}
and add the RedirectInterceptor to your okHttpClient(okhttp2 for example)
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.interceptors().add(new RedirectInterceptor());
okHttpClient.setFollowRedirects(false);
Solution 2
You can create an ApacheClient with LaxRedirectStrategy
private ApacheClient createRedirectClient(){
return new ApacheClient(HttpClients.custom()
.setRedirectStrategy(new LaxRedirectStrategy()).build());
}
RestAdapter.Builder builder = new RestAdapter.Builder()
.setEndpoint("http://yourendpoint")
.setClient(createRedirectClient());
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
Try to put HttpLoggingInterceptor and check the logs. Also cross check with Rest Client if your server is returning back with proper response or not for provided input along with parameters.
For HttpLoggingInterceptor, this is the following way to configure
public RestClient() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(logging);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("BASEURL")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
//APIInterface initiation
service = retrofit.create(APIInterface.class);
}
Below are the dependencies for the same
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
Go through this Sample tutorial of Retrofit, if you are following some other possibilities of initiating the rest client

Categories