0
votes

We use AWS V4 signature mechanism to make calls to our API Gateway endpoint from our iOS app. We had embedded the access key id and secret key in the code, which was working fine. Obviously this is not a secure way and the recommended way is to use AWS Cognito. I wanted to know how do we use the temporary access key and secret (and session key probably as well) that we get from the AWSCredentials object in my Objective-C iOS code to make secure requests to our API Gateway endpoint.

We tried to use the temporary access key and secret retrieved from Cognito to generate the V4 signature in place of account access key and secret, but this does not seem like the correct approach. The API Gateway method is enabled with AWS_IAM as the authorization setting.

This is the error we get:

{ status code: 403, headers {
    Connection = "keep-alive";
    "Content-Length" = 69;
    "Content-Type" = "application/json";
    Date = "Fri, 13 Jan 2017 10:26:38 GMT";
    Via = "1.1 .....cloudfront.net (CloudFront)";
    "X-Amz-Cf-Id" = "...";
    "X-Cache" = "Error from cloudfront";
    "x-amzn-ErrorType" = UnrecognizedClientException;
    "x-amzn-RequestId" = "...";
} }

The IdentityPoolId used is from the Identity Pool created under federated identities in AWS Cognito

AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 identityPoolId:@"us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"];

We are using unauthenticated role since we do not need any form of user specific authentication. And this role has the following policies: AmazonAPIGatewayInvokeFullAccess AmazonAPIGatewayPushToCloudWatchLogs CloudFrontFullAccess AmazonCognitoDeveloperAuthenticatedIdentities AmazonAPIGatewayAdministrator CloudFrontReadOnlyAccess IAMReadOnlyAccess AmazonCognitoPowerUser

Can you please help here as to how can I use Cognito to generate V4 signatures or completely bypass the process.

2
Have you registered the configuration that is using your credential provider?donkon

2 Answers

0
votes

It looks you are getting UnrecognizedClientException as response, but API Gateway doesn't return UnrecognizedClientException. Do you have the request id that was getting the error?

Just in case you might forget to register the configuration, you need to register the configuration to service manager.

AWSCognitoCredentialsProvider *creds = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 identityPoolId:your_cognito_pool_id];

AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:creds];

AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;

For your unauthenticated role policy, I think you are granting too powerful permission to the unauthenticated users. if you want them to be able to invoke your API, you can just give them AmazonAPIGatewayInvokeFullAccess or even scope down to method level.

0
votes

Sending an HTTP header "x-amz-security-token" with the value of variable sessionKey obtained from the AWSCredentials object solved the problem:

[request setValue:sessionToken forHTTPHeaderField:@"X-Amz-Security-Token"];

The AWSCredentials object is retrieved using:

[[credentialsProvider credentials] continueWithBlock:^id(AWSTask<AWSCredentials *> *task) {
        if (task.error) {
            DDLogCError(@"failed getting credentials: %@", task.error);
        }
        else {
            AWSCredentials *credentials = task.result;
        }
        return nil;
    }]

And yes, have trimmed the policies to just one - AmazonAPIGatewayInvokeFullAccess. Thanks you for your feedback.