Retrofit 2.0 headers authentication - http-headers

private void setUpRestClient() {
OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("Accept", "application/pyur.v1")
.header("Authorization", new SharedPreferencesUtil(getBaseContext()).getToken())
.header("Content-Type", "application/json")
.method(original.method(),original.body())
.build();
return chain.proceed(request);
}
});
RestClient.getInstance().configureRestAdapter(this, getResources().getString(R.string.base_url),client);
}
public void configureRestAdapter(final Context context, String baseUrl, OkHttpClient client) {
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build();
service = retrofit.create(NetworkServiceInterface.class);
}
This now gives me a failure return in Retrofit 2.0, originally I had it without the "Authorization" header and it was giving me unauthorized, which is understandable. But now I'm authorizing it with my auth token and it fails. New to Retrofit 2.0, thanks --

You can pass Authorization Header as:
#GET("/v1/OrderReport.json")
Call<POJO_Class> getExampleMethod(#Header("Authorization") String token, #Query("id") String id);
and then call as:
getExampleMethod("Basic " + token, id);

You can add Authorization Header for every calls using Interceptor in Retrofit 2, by using the OkHttpClient.Builder class. Like this.
import okhttp3.OkHttpClient;
import okhttp3.Interceptor;
OkHttpClient defaultHttpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
//getAccessToken is your own accessToken(retrieve it by saving in shared preference or any other option )
if(getAccessToken().isEmpty()){
PrintLog.error("retrofit 2","Authorization header is already present or token is empty....");
return chain.proceed(chain.request());
}
Request authorisedRequest = chain.request().newBuilder()
.addHeader("Authorization", getAccessToken()).build();
PrintLog.error("retrofit 2","Authorization header is added to the url....");
return chain.proceed(authorisedRequest);
}}).build();
And add this client object to the retrofit object.
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL) //BaseURL always ends with "/"
.addConverterFactory(GsonConverterFactory.create())
.client(defaultHttpClient)
.build();
Now for every calls that you make using the retrofit object will add the "Authorization" header along with the url. And also we handle the condition that if the authorization value is empty, then we simply omit the Authorization header part for the request call.

From Retrofit:2.0
you have to use OkHttpClient.Builder() class to add Interceptors.
So you have to change your code like this.
OkHttpClient client = new OkHttpClient.Builder();
client.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("Accept", "application/pyur.v1")
.header("Authorization", new SharedPreferencesUtil(getBaseContext()).getToken())
.header("Content-Type", "application/json")
.method(original.method(),original.body())
.build();
return chain.proceed(request);
}
}).build();

Related

Do you know java.io.FileNotFoundException: META-INF/native/netty_tcnative_windows_x86_64.dll error in Spring WebFlux?

everyone
When I try the code below,
private void request() {
HttpClient httpClient = HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)
.resolver(DefaultAddressResolverGroup.INSTANCE)
.responseTimeout(Duration.ofSeconds(60))
.doOnConnected(connection ->
connection.addHandlerLast(new ReadTimeoutHandler(60, TimeUnit.SECONDS))
.addHandlerLast(new WriteTimeoutHandler(60, TimeUnit.SECONDS)));
WebClient webClient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient)).build();
String requestUrl = "https://my-url";
Mono<String> result = webClient.post()
.uri(requestUrl)
.contentType(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(String.class);
String token = result.block();
return token;
}
This error occurred.. What should I do?
Thank you for share your knowledge.

Response code: 400 Bad request/Error Message: No Ids were specified

I am trying to send Get request using RestSharp but getting this message in response:Bad Request/
{"Message":"P1001: No Ids were specified"}. Could someone help please to figure out that? Seems like it's not adding Parameter list to the Request Body...
Here is my code:
public partial class DTO
{
public List<string> evidenceIds { get; set; }
}
public RestRequest GetPlayRequest(Method requestType, string token)
{
DTO MyObject = new DTO();
MyObject.evidenceIds = new List<string>();
MyObject.evidenceIds.Add("6F00CAE1-F16E-47F6-AF3F-D10305DD7859");
string jsonString = JsonConvert.SerializeObject(MyObject);
var restRequest = new RestRequest(requestType);
restRequest.RequestFormat = DataFormat.Json;
restRequest.AddParameter("text/json", jsonString, ParameterType.RequestBody);
restRequest.AddHeader("Organization", "Bofa");
restRequest.AddHeader("Username", "Admin");
restRequest.AddParameter("Authorization", "Bearer " + token, ParameterType.HttpHeader);
return restRequest;
}
The request with all params
The Content response after sending the request
I can suggest the following:
public RestRequest GetPlayRequest(Method method, string token)
{
var obj = new DTO { evidenceIds = new string[]
{"6F00CAE1-F16E-47F6-AF3F-D10305DD7859" }
};
return new RestRequest(method)
.AddJsonBody(obj)
.AddHeader("Organization", "Bofa")
.AddHeader("Username", "Admin");
.AddHeader("Authorization", $"Bearer {token}");
}

OKHttp Authenticator custom http code other than 401 and 407

I have oauth token implemented on server side but upon Invalid token or Token expirey i am getting 200 http status code but in response body i have
{"code":"4XX", "data":{"some":"object"}
When i try to read string in interceptor i get okhttp dispatcher java.lang.illegalstateexception closed because response.body().string() must be called only once.
Also i read from here Refreshing OAuth token using Retrofit without modifying all calls that we can use OkHttp Authenticator class but it works only with 401/407 i havent triedn as i will not get this. Is there any way we can customize Authenticator and proceed our logic inside it.
Thank you
If it possible, try to talk with your server side about response codes. Communication is also a very important skill.
If it inpossible, you can modify response codes manually with reflection, it enables okHttp authentication logic.
public OkHttpClient getOkHttpClient() {
return new OkHttpClient.Builder()
.authenticator((route, response) -> {
System.out.println("it working");
return null;
})
.addNetworkInterceptor(new UnauthorizedCaseParserInterceptor())
.build();
}
public class UnauthorizedCaseParserInterceptor implements Interceptor {
#Override
public Response intercept(#NonNull Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
if (isUnauthorizedResponse(response)) {
try {
Field codeField = response.getClass().getDeclaredField("code");
codeField.setAccessible(true);
codeField.set(response, HttpURLConnection.HTTP_UNAUTHORIZED);
} catch (Exception e) {
return response;
}
}
return response;
}
private boolean isUnauthorizedResponse(Response response) {
//parse response...
}
}
Please use this solution only as a last resort.

SSL Pinning in same request

My question is that do i have to make a separate request to check SSL Pinning before every Get/Post Request
OkHttpClient client = new OkHttpClient.Builder().certificatePinner(
new CertificatePinner.Builder()
.add(pinningUrl, "sha256/invalidPIN")
.build()).build();
Request request = new Request.Builder()
.url(pinningUrl)
.build();
Response response = client.newCall(request).execute();
Or can i check it with every Get/Post like this
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(pinningUrl, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") .build();
OkHttpClient client = new OkHttpClient().newBuilder().certificatePinner(certificatePinner).build();
Request request = new Request.Builder() .url(getResources().getString(R.string.server_url_user_mgmt_services))
.addHeader("Content-Type", "application).post(body)
.build();
client.newCall(request)
.enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
pd.dismiss();
Toast.makeText(LoginActivity.this, "Some error occured!\nTry Again", Toast.LENGTH_SHORT).show();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
String str = response.body().toString();
}
});
If i check it on every request the request is executed but it does not check for certificate help me with this.
Based on your first code example it looks like you are trying to pin with a URL instead of a hostname or wildcard.
You should configure it once on your OkHttpClient per host and then just make your normal requests. The pins you define should have the host as the key, not the url.
https://square.github.io/okhttp/3.x/okhttp/okhttp3/CertificatePinner.html
String hostname = "publicobject.com";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build();
OkHttpClient client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build();
Request request = new Request.Builder()
.url("https://" + hostname)
.build();
client.newCall(request).execute();

Apache HttpClient - Default protocol

I am using Apache HttpClient to send a POST requests. How can I determine which PROTOCOL my Apache HttpClient instance is using for sending "https://" requests. I use following code block to send my POST requests.
public void sendPostURL(String url, HashMap<String, String>params, String user, String pass) {
HttpClient client = new HttpClient();
String urlContent = "";
PostMethod method = new PostMethod("https://...");
// Prepare connection information
client.getParams().setParameter("http.useragent", "MyApp");
if ( (user != null) &&(pass != null) ) {
client.getParams().setAuthenticationPreemptive(true);
client.getState().setCredentials(AuthScope.ANY, (new UsernamePasswordCredentials(user, pass)));
}
// Prepare parameters
for (Map.Entry<String, String> entry : params.entrySet()) {
method.addParameter(entry.getKey(), ((entry.getValue() != null) ? entry.getValue().toString() : ""));
}
try{
// HTTP execution
int returnCode = client.executeMethod(method);
} catch (Exception e) {
// Exception
e.printStackTrace();
} finally {
method.releaseConnection();
}
}
Please guide me on how can I get the PROTOCOL that HttpClient is using to send the request. Also how can I override the PROTOCOL used. Hoping for a solution. Thanks in advance.
The protocol is HTTPS, is it not ?