I have problems getting the authorization of my API on AWS for a Cognito User Pool via HTTP headers (without AWS API Gateway SDK) to work.
My setup:
On AWS:
On the iOS client
What is working:
The API methods get properly deployed via serverless.
I can call the public (not set to use the user pool) via Postman.
For the private API methods, I can see the Cognito user pool authorizer set up in the API Gateway management console, including "Identity token source" set to method.request.header.Authorization
(the default) as described here
On iOS, I can properly register and log in as user. I can dump the AWS Credentials details to the console, showing AccessKey
, SecretKey
and SessionKey
.
On iOS, I can query the public API via RestKit.
When I try to call a private API method via Postman, I get back an HTTP error 401 with the body {"message": "Unauthorized"}
. (Which is expected, without setting any authorization.)
What fails:
To test the authorization, in Postman, I have tried
SessionKey
I got from the iOS client as HTTP Authorization
header - as defined here (last paragraph - "API Gateway’s Authorizer for Cognito User Pools")
X-Amz-Security-Token
header The result was always the same 401 error.
What do I need to set as HTTP headers, in order to authorize the calls to the private API? "Authorization" should work - maybe I am missing some role permissions?
How can I better debug the permissions / authorization flow?
To allow users to run Lambda with their Amazon Cognito permissions, follow these steps: Use the API Gateway console to establish your Amazon Cognito user pool as an authorizer. Then, assign the Amazon Cognito user pool as the authorizer for the method of your API.
Step 3: Configure Cognito Authorizer for API GatewayGo to “Resources” and select “GET” method. Select “Method Request” configuration on right pane. Select “Cognito_Authorizer” in “Authorization” drop-down. That should automatically add a new field “OAuth Scopes”.
This is how to get the session:
AWSCognitoIdentityUserPool *pool = [AWSCognitoIdentityUserPool CognitoIdentityUserPoolForKey:AWSCognitoUserPoolsSignInProviderKey];
AWSCognitoIdentityUser *user = [pool currentUser];
AWSTask<AWSCognitoIdentityUserSession *> *task = [user getSession];
Then, task.result.idToken.tokenString
can be set as "Authorization" header, and it works.
Thanks Peter for the tip!
For iOS (As of 11 May 2017)
let headerParameters = [
"Content-Type": "application/json",
"Accept": "application/json",
"AccessKey" : awsCredentials.accessKey,
"SecretKey" : awsCredentials.secretKey,
"SessionKey" : awsCredentials.sessionKey,
"Authorization" :
AWSCognitoUserPoolsSignInProvider.sharedInstance().getUserPool().currentUser()?.getSession().result?.idToken?.tokenString
]
where awsCredentials you can obtain on successful login and store it somewhere in your own code (AuthorizationService?). I kept the "Authorization" value so long so that it is easier for developers to know the full location of this hidden object. You should be keeping it in your own AuthorizationService class (or as extension member to AwsCredentials?)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With