Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to add aws signature in android and call aws api gateway

I have written this code but I'm getting an error. How can I get to work? But the same token works with postman.

Error:

 {"message":"The security token included in the request is invalid."}

Code :

public class test extends AppCompatActivity {

    private final AWS4Signer signer = new AWS4Signer();
    Request<?> aws;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test);

         AWSCredentials credentials = new BasicAWSCredentials("AccessKey", "SecretKey");
        aws = generateBasicRequest();
        signer.setServiceName("execute-api");
        signer.sign(aws, credentials);

        new get_aws().execute();

    }

    private Request<?> generateBasicRequest() {
         Request<?> request = new DefaultRequest<Void>("execute-api");
        request.addHeader("Content-type", "application/json");
         String securityToken = "Session Token";

        request.addHeader("X-Amz-Security-Token", securityToken);
        request.addHeader("Host", "********.amazonaws.com");
        request.addHeader("x-amz-archive-description", "test  test");
        request.setResourcePath("/");
        request.setEndpoint(URI.create("https://******.execute-api.****.amazonaws.com/data/all"));
        return request;
    }


    private class get_aws extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... params) {

            BufferedReader in = null;
            String data = null;

            try {
                HttpClient httpclient = new DefaultHttpClient();

                HttpGet request = new HttpGet();
                request.addHeader("Authorization", aws.getHeaders().get("Authorization"));
                request.addHeader("X-Amz-Date",request_aws.getHeaders().get("X-Amz-Date"));
                request.addHeader("Content-Type","application/x-www-form-urlencoded");

                URI website = new URI("https://********.execute-api.*******.amazonaws.com/data/all");
                request.setURI(website);
                HttpResponse response = httpclient.execute(request);
                in = new BufferedReader(new InputStreamReader(
                        response.getEntity().getContent()));

                String line = in.readLine();
                Log.d("line", line);

            } catch (Exception e) {
                Log.e("log_tag", "Error in http connection " + e.toString());
            }


            return null;
        }

        @Override
        protected void onPostExecute(Void result) {

        }

        @Override
        protected void onPreExecute() {
        }

        @Override
        protected void onProgressUpdate(Void... values) {
        }
    }
}
like image 803
jason Avatar asked Jan 09 '18 20:01

jason


People also ask

How do I make an AWS signature?

Use the canonical request and additional metadata to create a string for signing. Derive a signing key from your AWS secret access key. Then use the signing key, and the string from the previous step, to create a signature. Add the resulting signature to the HTTP request in a header or as a query string parameter.

How do I authenticate an API AWS?

The Amazon S3 REST API uses a custom HTTP scheme based on a keyed-HMAC (Hash Message Authentication Code) for authentication. To authenticate a request, you first concatenate selected elements of the request to form a string. You then use your AWS secret access key to calculate the HMAC of that string.


1 Answers

To answer your immediate question, AWS can generate a Java SDK from your API Gateway for you.

Using the generated SDK, you can then pass an AWSCredentialsProvider object into your SDK.

         AWSCredentials credentials = new BasicAWSCredentials("AccessKey", "SecretKey");

ApiClientFactory factory = new ApiClientFactory()
  .credentialsProvider(credentials);

But...

You should never ship IAM access keys in a shipped application. These credentials can be retrieved by anyone who has installed your application by opening the .apk file.

Those credentials can then be used to access any other AWS actions the associated IAM User has access to in your account. This means anyone with access to the application apk (ie: anyone who can download the app from the app store) has access to your AWS account.

Depending what problem you're trying to solve will dictate the correct solution to the problem.

My Lambda needs an IAM Role to run

This is a fairly common mistake to make with API gateway when people see the "Invoke with caller credentials" option from API Gateway.

Uncheck this box and the Lambda will run with the IAM Role you defined in Lambda.

If requests fail after doing this, you need to make sure API Gateway has permission to invoke your lambda.

Restrict API to the application itself without users

Your application can't keep a secret and you have no user credentials.

You should disable Authorization completely, this is effectively a public API.

Requiring an API Key (and usage plan) to rate limit your API can be useful, but keep in mind this is not a security measure as, again - your application can't keep that key secret.

You want users to log in first (no existing source of users)

This makes sense if your API call is only designed to be called by registered users.

You'll need to configure Cognito User Pools for this. This shouldn't be confused with Cognito Federated Identities - which focuses on a different part of the problem. You can use it to solve this, but trust me - you'll be happier if you don't go down that path.

To get cracking you'll need to take a few steps:

  1. Create a User Pool (detailed settings explained here).

  2. Configure a Cognito Authorizer on your API Gateway.

  3. Create an App Client for your pool. Don't generate a client secret key when you do this.

  4. Integrate with your Android application. There's a prebuilt Android example available from AWS for getting the client side going: AmazonCognitoYourUserPoolsDemo

You want users to log in first (existing source of users)

If you can use SAML or OAuth2.0 / OpenID Connect to authenticate your users, follow the instructions and then configure federation.

If not, this is possibly the time to consider Cognito Federated Identities, specifically using the Developer Authenticated Identities process. But again, I'd really recommend against it.

API Gateway & Cognito is a massive topic. Hopefully the instructions provided are a great entry point to the relevant parts of the documentation.

like image 62
bly Avatar answered Oct 16 '22 16:10

bly