John Riley
John Riley

Reputation: 498

AWS API Gateway Calls not working for Android

I have a custom API set up on AWS for passing a message to the server. The server then responds to that message in a simple fashion. The API calls work from the browser and Postman, but do not work via the mobile client. I've removed authorization on the API, deployed it, and triple checked my api calls, but I continue to receive the 403 "Forbidden" error. I'm calling the API using Retrofit. Here is my client code:

API Calls:

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Headers;
import retrofit2.http.POST;

public interface MyAPI {
    @Headers({
            "content-type: application/json",
            "Accept: application/json"
    })
    @POST("/chat/new")
    Call<ChatMessageBody> postMessage(@Body ChatMessageBody message);
}

ChatMessageBody class:

public class ChatMessageBody {

    private String messageBody;

    public ChatMessageBody(String body){
        this.messageBody = body;
    }

    public String body() {
        return messageBody;
    }
}

Theoretically, the Request Body of my call as a result of the set up should be something like this:

{
     "messageBody" : "This is my message"
}

Am I missing a vital aspect of calling the API from a mobile setting? It doesn't make sense to me that I'd be able to call the API endpoint from my browser and through Postman and have it work, yet I can't seem to do so via Android.

EDIT: Response Body from a successful call (via postman or API Gateway test)

{\"messageBody\": \"You said \\\"test\\\"\"}

Response Body from the 403 error

{"message":"Forbidden"}

Postman generates code based on your desired client and your calls. Here is the code generated for this call by Postman (with respect to OkHTTP. I'm not using this code, but it could provide insight into why Postman works and my client doesn't):

OkHttpClient client = new OkHttpClient();

MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"messageBody\" : \"test\"\n}");
Request request = new Request.Builder()
  .url("https://qj2wkyi91c.execute-api.us-east-1.amazonaws.com/prototype_mvp/chat/new")
  .post(body)
  .addHeader("content-type", "application/json")
  .addHeader("cache-control", "no-cache")
  .addHeader("postman-token", "dccf1f20-f20e-fd53-dd24-a9f4ae7b5c69")
  .build();

Response response = client.newCall(request).execute();

Here is a stack trace of my requests/responses in the Android Environment:

03-27 12:32:27.835 29985-31080/com.dev.example.debug D/OkHttp: --> POST [MY_API_ENDPOINT] http/1.1
03-27 12:32:27.835 29985-31080/com.dev.example.debug D/OkHttp: Content-Type: application/json
03-27 12:32:27.835 29985-31080/com.dev.example.debug D/OkHttp: Content-Length: 36
03-27 12:32:27.835 29985-31080/com.dev.example.debug D/OkHttp: Accept: application/json
03-27 12:32:27.836 29985-31080/com.dev.example.debug D/OkHttp: {"messageBody":"This is my message"}
03-27 12:32:27.836 29985-31080/com.dev.example.debug D/OkHttp: --> END POST (36-byte body)
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: <-- 403  [MY_API_ENDPOINT] (239ms)
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: content-type: application/json
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: content-length: 24
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: date: Mon, 27 Mar 2017 16:32:28 GMT
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: x-amzn-requestid: [REQUEST_ID]
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: x-amzn-errortype: ForbiddenException
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: x-cache: Error from cloudfront
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: via: 1.1 [CLOUDFRONT_URL] (CloudFront)
03-27 12:32:28.077 29985-31080/com.dev.example.debug D/OkHttp: x-amz-cf-id: [CF_ID]
03-27 12:32:28.077 29985-31080/com.dev.example.debug D/OkHttp: {"message":"Forbidden"}
03-27 12:32:28.077 29985-31080/com.dev.example.debug D/OkHttp: <-- END HTTP (24-byte body)
03-27 12:32:28.079 29985-29985/com.dev.example.debug E/MyAPI: Your request did not receive a successful response.
03-27 12:32:28.079 29985-29985/com.dev.example.debug E/MyAPI: Response Error Code: 403
03-27 12:32:28.079 29985-29985/com.dev.example.debug E/MyAPI: Response Body: {"message":"Forbidden"}

Upvotes: 2

Views: 2568

Answers (4)

Ghedeon
Ghedeon

Reputation: 1673

Created an AWS Gateway OkHttp Interceptor for those who prefer Retrofit over the AWS sdk. It still uses AWS4Signer from aws-android-sdk-apigateway-core tho, so you have to keep this dependency in your project.

Upvotes: 0

John Riley
John Riley

Reputation: 498

I ended up solving this issue by abandoning Retrofit and designing an OKHttp client which interfaces with AWS. My requests are now being properly signed for AWS, and I'm no longer receiving 403 errors.

Upvotes: 0

Bob Kinney
Bob Kinney

Reputation: 9040

403 (Permission Denied) can also occur if you send a request to the wrong path.

I'm not familiar with retrofit, but see you only have /chat/new listed in your annotation. How do you configure the root path in retrofit?

Are you sure you are including the full path including stage?

Upvotes: 0

Remario
Remario

Reputation: 3863

There is no authorization in that request, therefore the response given back is forbidden accessing that route.

Also the content type can affect that, postman conveniently deals with this behind the scenes, application/x-www-form-urlencoded.

Upvotes: 2

Related Questions