Retrofit 2 for OAuth (Convert cURL) - android

So I am trying to use retrofit to get the access token from our OAuth secured backend.
Basically I need to covert the following cURL command into retrofit :
curl -X POST -d "grant_type=password&phone_number=123123123&password=12345" -u"Client_Id:Client_Secret" http://baseURL/o/token
Here is my service
public interface LoginService {
#POST("/o/token")
#FormUrlEncoded
Observable<LoginEntity> getAccessToken(#Field("grant_type") String grantType,
#Field("phone_number") String phoneNumber,
#Field("password") String password,
#Header("Authorization") String authorization);
}
Here is my service generator code:
public void login(final MySubscribe<LoginEntity> subscriber, String pn, String psw) {
mRetrofit = new Retrofit.Builder()
.baseUrl(MyFeeds.APP_BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
//encode pn
String real_pn = getRealPN(pn);
//encode the credential using base64
String credential = MyFeeds.CLIENT_ID+":"+MyFeeds.CLIENT_SECRET;
String auth = null;
try {
auth = "Basic " + getBase64String(credential);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
LoginService service = mRetrofit.create(LoginService.class);
Observable<LoginEntity> observable = service.getAccessToken("password", real_pn, psw, auth);
mSubscription = observable.subscribeOn(Schedulers.newThread())
.doOnSubscribe(new Action0() {
#Override
public void call() {
subscriber.onBegin();
}
})
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
}
However I keep getting http500 error.
I have read the following post but it doesn't help
CURL -u request with Retrofit
Can anyone help? Thanks

Related

Retrofit server response is getting 307 in android

Step1:
Need to give input to server.as below image
step2:
get response from server ,as below image.
![enter image description here][2]
step3:
MainActivity.java
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.URL_BASE)
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiInterface apiInterface = retrofit.create(ApiInterface.class);
// prepare call in Retrofit 2.0
try {
JSONObject paramObject = new JSONObject();
paramObject.put("merchant_id", "aaaaa");
paramObject.put("secret_key", "bbbbb");
Call<RequestBody> userCall = apiInterface.getUser(paramObject.toString());
userCall.enqueue(this);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onResponse(Call<RequestBody> call, Response<RequestBody> response) {
Log.d("TEST","TEST--onResponse1---"+call);
Log.d("TEST","TEST--onResponse2---"+response);
}
#Override
public void onFailure(Call<RequestBody> call, Throwable t) {
Log.d("TEST","TEST--onFailure1--"+call);
Log.d("TEST","TEST--onFailure1--"+t);
}
========================================================
step4: ApiInterface.hava
public interface ApiInterface {
#Headers("Content-Type: application/json")
Call<RequestBody> getUser(#Body String body);
}
Log is going to "onResponse.code()" is getting 307" but i count able
to get proper data.
I am new to Retrofit service.Can please help me.
You can't send String to Retrofit without using some other library.
Since you're using Gson already. Create a class that Gson can serialize.
class Credentials {
#SerializedName("merchant_id")
public String merchantId;
#SerializedName("secret_key")
public String secretKey;
}
Interface method. #Notice the input type.
#Headers("Content-Type: application/json")
Call<RequestBody> getUser(#Body Credentials credentials);
307 is Temporary Redirect - and you might have to follow that redirect.
Which means, that you need to configure the OkHttpClient to do so:
OkHttpClient client = new OkHttpClient.Builder()
.followSslRedirects(true)
.followRedirects(true)
.build();
and then set it as the client for retrofit2:
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(Constants.API_BASE_URL)
.client(client)
.build();

Error in make post reques using RETROFIT

I have a problem in using retrofit. I have a API https://raakar.ir/addProject and want to send some information. API works fine in postman. I want to make post request. I think, I do every think correctly. But when I run the app, It crash.
I used these libraries:
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
and these are my interface of retrofit :
public interface APIInterface {
#Multipart
#POST("addProject")
Call<AddProjectResponse> post(
#Header("token") String token,
#Field("name") String name,
#Field("amount") String amount,
#Field("description") String description,
#Field("category") String category,
#Field("deadline") String deadline,
#Field("projectFile")Bitmap bitmap
);
}
------------------------------------------------------------------------------------------------------------------------------------
Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl("https://raakar.ir/")
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
APIinterface retroInterface = retrofit.create(APIinterface.class);
Call<AddProjectResponse> call = retroInterface.post(token,
"طراحی راکار",
"50000000",
"خالی است",
"برنامه نویسی",
"5",
null);
call.enqueue(new Callback<AddProjectResponse>() {
#Override
public void onResponse(Call<AddProjectResponse> call, Response<AddProjectResponse> response) {
Log.d("Resposne:", response.toString());
}
#Override
public void onFailure(Call<AddProjectResponse> call, Throwable t) {
Log.d("Respone:", "Error");
}
});
PLEASE HELP me!
i thing if you are not post any image and other file like video etc then you can not used #Multipart and also pass in post method paremater make one pojo class for that and only pass your object like below that...sample code
MyEventRequestModel myEventListRequestModel = new MyEventRequestModel(); // define your pojo class object
myEventListRequestModel.setDate(mDate);
Call<MyEventResponseModel> call = apiInterface.getAllEvent(myEventListRequestModel);
and header will be set on retrofit intialized..
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.readTimeout(60, TimeUnit.SECONDS);
client.writeTimeout(60, TimeUnit.SECONDS);
client.connectTimeout(60, TimeUnit.SECONDS);
client.addInterceptor(interceptor);
client.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (context == null) {
request = request
.newBuilder()
.build();
} else {
request = request
.newBuilder()
.addHeader("Authorization", "Bearer " + AppSetting.getStringSharedPref(context, Constants.USER_KEY_TOKEN, "")) // hear define your header.
.build();
}
return chain.proceed(request);
}
});
If You use #Multipart than use #Part not #Field
public interface APIInterface {
#Multipart
#POST("addProject")
Call<AddProjectResponse> post(
#Part ("token") String token,
#Part ("name") String name,
#Part ("amount") String amount,
#Part ("description") String description,
#Part ("category") String category,
#Part ("deadline") String deadline,
#Part MultipartBody.Part img
);
}

How to send Token in Header to server in Android

In my application I want to create a Login/Register page.
In the login page I send the Username, Password, Token from client to Server.
I should get Username and Password from USER, and get Token from HEADER of Request.
For connect client to server I use Retorfit 2.2.0 library.
Code from the Interface class :
#POST("User/Authenticate")
Call<LoginResponse> getLoginResponse(#Header("Token") String token, #Body LoginDatum loginDatum);
Code within the Activity :
public void getLogin(String username, String password) {
final LoginDatum loginDatum = new LoginDatum();
loginDatum.setUsername(username);
loginDatum.setPassword(password);
InterfaceApi api = ApiClient.getClient().create(InterfaceApi.class);
Call<LoginResponse> call = api.getLoginResponse(sendToken, loginDatum);
Log.e("tokenTAG", "Token : " + sendToken);
call.enqueue(new Callback<LoginResponse>() {
#Override
public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
LoginResponse loginResponse = response.body();
String token = response.headers().get("Token");
if (token != null) {
sendToken = token;
Log.e("tokenTAG", "Token : " + sendToken);
}
if (loginResponse.getStatusCode() == 200) {
Toasty.success(context, context.getResources().getString(R.string.welcome) + " " +
loginResponse.getData().getName(), Toast.LENGTH_LONG, true).show();
} else {
Toasty.error(context, loginResponse.getStatusMessage() + "", Toast.LENGTH_LONG, true).show();
}
loadProgress.get(0).setVisibility(View.GONE);
loginBtn.setVisibility(View.VISIBLE);
btnShadow.setVisibility(View.VISIBLE);
}
#Override
public void onFailure(Call<LoginResponse> call, Throwable t) {
loadProgress.get(0).setVisibility(View.GONE);
loginBtn.setVisibility(View.VISIBLE);
btnShadow.setVisibility(View.VISIBLE);
Toasty.error(context, context.getResources().getString(R.string.failRequest),
Toast.LENGTH_LONG, true).show();
}
});
}
And show me this in LogCat :
tokenTAG: Token : null
tokenTAG: Token : MKGKFPOVRMU4MRK0STNDO20RA2MPEWT7Y1N2WUM5QLIXJX2TEOM9APGUTYJMD8R42WFVESD8GRXCTCINA2LZKU7JV2I7KA2R4N5W
But when I want to send the token with this code : Call<LoginResponse> call = api.getLoginResponse(sendToken, loginDatum); it shows me null.
I have use this line : Call<LoginResponse> call = api.getLoginResponse(sendToken, loginDatum); to generate the request callBack, although this line Token is not NUll.
How can I fix it?
if you use Retrifit get onNetwork request,in order to add Header to your requese,you must be write an Intercepter.
just replace getClient menthod with this one
public static Retrofit getClient(final Context context) {
if (retrofit == null) {
Log.d("AuthTokenTest", "getClient: null");
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
dispatcher = new Dispatcher();
httpClient.dispatcher(dispatcher);
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Log.d("INTERCEPTOR", original.url().toString());
//System.out.print(original.toString());
Request request;
user=User.getLoggedInUserInstance(context);
String authToken="";
if(user!=null)
authToken=user.getAuthToken();
Log.d("AuthTokenTest", "intercept: authtoken:"+authToken);
request = original.newBuilder()
.header("X-AUTH-TOKEN", authToken)
.header("x-requested-with", "XMLHttpRequest")
.method(original.method(), original.body())
.build();
okhttp3.Response response = chain.proceed(request);
Log.d("INTERCEPTOR-", "response_code: "+response.code());
// Log.d("INTERCEPTOR", response.body().string());
return response;
}
});
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
if(BuildConfig.DEBUG){
//print the logs in this case
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
}else{
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
}
httpClient.addInterceptor(loggingInterceptor);
OkHttpClient client = httpClient.build();
Gson gson = new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.TRANSIENT)
.setLenient()
.create();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
return retrofit;
}
let me know if this solution works or not

Get OAuth Token from Web API to android

I'm trying to get ِِOAuth token in android from my web api. I have tested the api in Postman and it's working perfect.
Screenshot for the successful call from Postman
now I need to call this Api from my android app using retrofit 2 to get the token, for that I tried to use the following interface but it's not working.
#FormUrlEncoded
#POST("/Token")
public Call<String> Token(#Field("grant_type") String grant_type, #Field("username") String username, #Field("password") String password);
How can I get this done?
In my case I using this below way to call Web Api in Android Application.
Note : I am using OkHttp library.
Create Token class
public class Token {
public String access_token;
public String token_type;
public int expires_in;
public Token(){
}
}
Now add OkHttp library jar to your Project.
for more detail visit this :
http://square.github.io/okhttp/
Now to get OAuth Token call this way
OkHttpClient client = new OkHttpClient();
Request.Builder builder = new Request.Builder();
builder.url(write your url here);
builder.addHeader("Content-Type", "application/x-www-form-urlencoded");
builder.addHeader("Accept", "application/json");
FormEncodingBuilder parameters = new FormEncodingBuilder();
parameters.add("grant_type", "password");
parameters.add("username", edituser);
parameters.add("password", editpassword);
builder.post(parameters.build());
try {
Response response = client.newCall(builder.build()).execute();
if (response.isSuccessful()) {
String json = response.body().string();
}
catch(Exception e){
// catch Exception here
}
finally in response you will get your Token.
Late but it might help someone
Interface class
#FormUrlEncoded
#POST("/Token")
void getTokenAccess(#Field("grant_type") String grantType, #Field("username") String username, #Field("password") String password, Callback<TokenResponse> callback);
TokenResponse class
public class TokenResponse {
private String access_token,token_type,expires_in,userName;
public String getAccess_token() {
return access_token;
}
public String getToken_type() {
return token_type;
}
public String getExpires_in() {
return expires_in;
}
public String getUserName() {
return userName;
}
}
I am using retrofit 1.9.0
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(ENDPOINT_URL).setLogLevel(RestAdapter.LogLevel.FULL)
.build();
NetApi api = adapter.create(NetApi.class);
api.getTokenAccess("password", email, password, new Callback<TokenResponse>() {
#Override
public void success(TokenResponse tokenResponse, Response response) {
showProgress(false);
try{
MainActivity.tokenResponse = tokenResponse;
startActivity(new Intent(LoginActivity.this, MainActivity.class));
}catch (Exception e){
Toast.makeText(LoginActivity.this,"Unknown Error",Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
#Override
public void failure(RetrofitError error) {
Toast.makeText(LoginActivity.this,""+error.getMessage(),Toast.LENGTH_LONG).show();
showProgress(false);
}
});

Retrofit 2 - null response body

I am trying to convert following response with Retrofit 2
{
"errorNumber":4,
"status":0,
"message":"G\u00f6nderilen de\u011ferler kontrol edilmeli",
"validate":[
"Daha \u00f6nceden bu email ile kay\u0131t olunmu\u015f. L\u00fctfen giri\u015f yapmay\u0131 deneyiniz."
]
}
But I am allways getting null response in onResponse method. So I tried to look at error body of the response with response.errorBody.string(). Error body contains exactly same content with raw response.
Here is my service method, Retrofit object and response data declerations:
#FormUrlEncoded
#POST("/Register")
#Headers("Content-Type: application/x-www-form-urlencoded")
Call<RegisterResponse> register(
#Field("fullName") String fullName,
#Field("email") String email,
#Field("password") String password);
public class RegisterResponse {
public int status;
public String message;
public int errorNumber;
public List<String> validate;
}
OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
final String content = UtilityMethods.convertResponseToString(response);
Log.d(TAG, lastCalledMethodName + " - " + content);
return response.newBuilder().body(ResponseBody.create(response.body().contentType(), content)).build();
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
domainSearchWebServices = retrofit.create(DomainSearchWebServices.class);
I have controlled response JSON with jsonschema2pojo to see if I modled my response class wright and it seems OK.
Why Retrofit fails to convert my response?
UPDATE
For now as a work around I am building my response from error body.
I have solved the problem. When I make a bad request (HTTP 400) Retrofit doesn't convert the response. In this case you can access the raw response with response.errorBody.string(). After that you can create a new Gson and convert it manually:
if (response.code() == 400 ) {
Log.d(TAG, "onResponse - Status : " + response.code());
Gson gson = new Gson();
TypeAdapter<RegisterResponse> adapter = gson.getAdapter(RegisterResponse.class);
try {
if (response.errorBody() != null)
registerResponse =
adapter.fromJson(
response.errorBody().string());
} catch (IOException e) {
e.printStackTrace();
}
}

Categories

Resources