I'm implementing a login post method using retrofit 2. It works well in Postman but returns 500 error. I've tried different solutions and the ones searched in StackOverFlow didn't worked for me, so here is my implementation:
@FormUrlEncoded
@POST("mobile/login")
Call<JsonObject> login(@Field(value = "_username") String username, @Field(value = "_password") String password);
login
public void login(String _username, String _password, final NetworkRequestObjectResult callBackResult) {
mRoomPresenceAPI = provideApiService();
Call<JsonObject> callObject = mRoomPresenceAPI.login(_username, _password);
callObject.enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if (response.body() != null && response.code() == 200) {
Log.i(TAG, "mobile/login Success code: "+response.code() + " content: "+response.body().toString());
callBackResult.onSuccess(null);
} else {
if (response.errorBody() != null) {
Log.e(TAG, "mobile/login error code: "+response.code() + " error content: "+response.errorBody().toString());
//general error
callBackResult.onError(mContext.getResources().getString(R.string.error_login));
}
}
}
@Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Log.e(TAG, "mobile/login error : "+t.getMessage());
callBackResult.onError(mContext.getResources().getString(R.string.error_login));
}
});
}
provide service
public INetworkAPI provideApiService() {
return provideRetrofit(BASE_URL, provideClient()).create(INetworkAPI.class);
}
//provide client
public OkHttpClient provideClient() {
loadSSLConfig();
OkHttpClient.Builder clientBuilder = getUnsafeOkHttpClient();
clientBuilder.addInterceptor(new ResponseInterceptor());
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
clientBuilder.addInterceptor(loggingInterceptor);
return clientBuilder.build();
}
class ResponseInterceptor implements Interceptor {
@Override
public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException {
okhttp3.Response response = chain.proceed(chain.request());
return response.newBuilder()
}
}
private void loadSSLConfig() {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
InputStream inputStream = mContext.getApplicationContext().getAssets().open("roompresencecom_cert.crt");
//new BufferedInputStream(new FileInputStream("roompresencecom_cert.crt"));
// mContext.getResources().openRawResource(R.raw.roompresencecom_cert);
Certificate certificate = certificateFactory.generateCertificate(inputStream);
inputStream.close();
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", certificate);
// Create a TrustManager that trusts the CAs in our KeyStore.
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm);
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
x509TrustManager = (X509TrustManager) trustManagers[0];
// Create an SSLSocketFactory that uses our TrustManager
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{x509TrustManager}, null);
sslSocketFactory = sslContext.getSocketFactory();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static OkHttpClient.Builder getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
return builder;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
provide retrofit public Retrofit provideRetrofit(String baseURL, OkHttpClient client) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setLenient();
gson = gsonBuilder.create();
return new Retrofit.Builder()
.baseUrl(baseURL)
.client(client)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
base URL public final String BASE_URL = "https://sandbox.roompresence.com/";
[Postman][1]
Problem solved (server problem). One particular note: in the API this request was redirecting internally to the request for the web login, this redirecting was performing well from POstman and IOS but not coming from Android (my coworkers who developed the web version have detected this with Fiddler). This request also did not belong to the mobile API that I was using, so the problem might be there.
The solution was to add a new login request to the mobile API and voilà, it worked.
Retrofit request:
@POST("mobile/login")
Call<JsonObject> login(@Body Map<String,String> parameters);