2

I am currently trying to configure a REST API I added using AWS Amplify. I have already configured user authentication in which users can sign-up and sign-in by following the steps outlined in the authentication docs. I then added a REST API using the api steps.

At the moment, I am just trying to retrieve a list of items from DynamoDB. The api is successful when I test it on the aws console, however, when I make the call from my android api, it returns the following error:

{"message":"Authorization header requires 'Credential' parameter. Authorization header requires 'Signature' parameter. Authorization header requires 'SignedHeaders' parameter. Authorization header requires existence of either a 'X-Amz-Date' or a 'Date' header. Authorization=[a long string of characters]

I understand that amplify automatically sets the API to be restricted using AWS_IAM, which I think is why the above message is returned. I am trying to get it to authenticate using the user pools I setup before with the authentication steps. The code in my android that app that makes the call to the API is as follows:

RestOptions options = new RestOptions("/models");

Amplify.API.get("modelsapi", options, new ResultListener<RestResponse>() {
    @Override
    public void onResult(RestResponse restResponse) {
        Log.i(TAG, restResponse.toString());
        Log.i(TAG, restResponse.getData().asString());
    }

    @Override
    public void onError(Throwable throwable) {
        Log.e(TAG, throwable.toString());
    }
});

Do I need to setup a Authorizer on AWS api console? And if so, How do I pass the authorization header with the user token. I have a seen a few responses from people using react native but not with android: AWS-amplify Including the cognito Authorization header in the request

The function which the Api invokes is as follows if needed:

app.get(path, function(req, res) {

  let queryParams = {
    TableName: tableName
  }

  dynamodb.scan(queryParams, (err, data) => {
    if (err) {
      res.statusCode = 500;
      res.json({error: 'Could not load items: ' + err});
    } else {
      res.json(data.Items);
    }
  });
});

Any points/help would be greatly appreciated! Thanks!

Aido
  • 150
  • 4
  • 9
  • Updated: I reconfigured the API to use a Cognito User Pool Authorizer. I followed these steps: https://github.com/aws-amplify/amplify-cli/issues/3390?fbclid=IwAR0-if8PT0aOhDcY2UgOFwFK3HN-R1yVY5KdqTv-U4mM_tVnQgmrHWSnYj4#issue-562734908 . However now the error message just returns a `{"message":"Unauthorized"}`. – Aido Feb 17 '20 at 19:34

1 Answers1

5

Have figured it out. Even though Amplify is meant to take the credentials automatically when making an API call, it seemed to throw up the unauthorized error anyway. When I tested using the console it worked fine. I had to manually add the authorization header to the Rest options:

RestOptions options = RestOptions.builder()
                .addPath("models")
                .addHeader("Authorization", token.getTokenString())
                .build();
Aido
  • 150
  • 4
  • 9
  • 1
    The token can come from lots of places, I used the `AWSMobileClient.getInstance().getTokens` which returns the auth tokens for the app context. The docs around the authentication for Amplify seem to have changed quite a lot since I last used them, but the authentication docs can be found here https://docs.amplify.aws/lib/auth/getting-started/q/platform/android#initialize-amplify-auth – Aido Feb 21 '21 at 13:33
  • By default, the ApiPlugin uses the Access Token rather than Id Token for the authorization header. If your using an Authorizer for API Gateway then you need the Id Token, so just add it like above or (Amplify.Auth.fetchAuthSession() as AWSCognitoAuthSession).userPoolTokens.value?.idToken.toString(). This will concatenate the id token before the access token, making it a valid authorization header, even though it only needs the first. – Isaac I9 Aug 24 '22 at 15:01