我在AWS上通过HTTP头(没有AWS API网关SDK)获得Cognito用户池的API授权时遇到问题。
我的设置:
在AWS上:
- 在AWS Lambda上实现的REST API(通过无服务器框架部署)
- 通过使用LAMBDA_PROXY类型的API网关暴露(无手动映射)
- 通过提供的"Cognito用户池授权人"在API网关上进行授权(无"AWS_IAM"选项,无自定义编码授权人)
- 通过Postman测试API
在iOS客户端上
- 通过AWS Cognito注册/登录(SDK和UI复制自AWS Mobile Hub生成的演示Xcode项目)
- 通过RestKit访问REST API,而不是使用AWSAPIGateway SDK
工作原理:
API方法通过无服务器进行正确部署。
我可以通过Postman呼叫公众(未设置为使用用户池)。
对于私有的API方法,我可以看到在API网关管理控制台中设置的Cognito用户池授权器,包括设置为method.request.header.Authorization
(默认)的"身份令牌源",如这里所述
在iOS上,我可以正确注册并以用户身份登录。我可以将AWS凭据的详细信息转储到控制台,显示AccessKey
、SecretKey
和SessionKey
。
在iOS上,我可以通过RestKit查询公共API。
当我试图通过Postman调用一个私有的API方法时,我返回了一个HTTP错误401,主体为{"message": "Unauthorized"}
。(这是意料之中的事,没有设置任何授权。)
失败的原因:
为了测试授权,在Postman中,我尝试了
- 将我从iOS客户端获得的AWSCredentials的
SessionKey
复制/粘贴为HTTPAuthorization
标头-如本文所定义(最后一段-"API网关的Cognito用户池授权程序") - 并作为
X-Amz-Security-Token
报头
结果总是相同的401错误。
为了授权对私有API的调用,我需要将什么设置为HTTP头?"授权"应该有效-也许我缺少一些角色权限
如何更好地调试权限/授权流
以下是获取会话的方法:
AWSCognitoIdentityUserPool *pool = [AWSCognitoIdentityUserPool CognitoIdentityUserPoolForKey:AWSCognitoUserPoolsSignInProviderKey];
AWSCognitoIdentityUser *user = [pool currentUser];
AWSTask<AWSCognitoIdentityUserSession *> *task = [user getSession];
然后,task.result.idToken.tokenString
可以设置为"Authorization"头,它就可以工作了。
谢谢Peter的小费!
适用于iOS(截至2017年5月11日)
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
]
其中awsCredentials,您可以在成功登录时获得,并将其存储在您自己的代码中(AuthorizationService?)。我将"Authorization"值保留了很长时间,这样开发人员就更容易知道这个隐藏对象的完整位置。您应该将其保存在自己的AuthorizationService类中(或者作为AwsCredentials的扩展成员?)
如果您使用Swift 3,您可以通过下面的代码获得身份令牌。
let pool = AWSCognitoUserPoolsSignInProvider.sharedInstance().getUserPool()
let currentUser = pool.currentUser()
let task = currentUser?.getSession()
let identityToken = task?.result?.idToken?.tokenString
print("identityToken: (String(describing: identityToken))")