AWS API Gateway + Cognito 用户池授权方 + Lambda - 我需要设置哪些 HTTP 标头和权限?
Posted
技术标签:
【中文标题】AWS API Gateway + Cognito 用户池授权方 + Lambda - 我需要设置哪些 HTTP 标头和权限?【英文标题】:AWS API Gateway + Cognito User Pool Authorizer + Lambda - Which HTTP-headers and permissions do I need to set? 【发布时间】:2017-06-18 01:04:07 【问题描述】:我无法通过 HTTP 标头(没有 AWS API Gateway SDK)在 AWS 上授权我的 API 以使 Cognito 用户池正常工作。
我的设置:
在 AWS 上:
在 AWS Lambda 上实现的 REST API(通过 Serverless 框架部署), 使用 LAMBDA_PROXY 类型通过 API 网关公开(无手动映射) 通过提供的“Cognito 用户池授权方”对 API 网关进行授权(无“AWS_IAM”选项,无自定义编码授权方) 通过Postman测试API在 ios 客户端上
通过 AWS Cognito 注册/登录(从 AWS Mobile Hub 生成的演示 Xcode 项目复制的 SDK 和 UI) 通过RestKit 访问 REST API,不使用 AWSAPIGateway SDK什么是有效的:
API 方法通过无服务器正确部署。
我可以通过 Postman 呼叫公众(未设置为使用用户池)。
对于私有 API 方法,我可以看到在 API Gateway 管理控制台中设置的 Cognito 用户池授权方,包括“身份令牌源”设置为 method.request.header.Authorization
(默认值),如 here 所述
在 iOS 上,我可以正确注册并以用户身份登录。我可以将 AWS Credentials 详细信息转储到控制台,显示 AccessKey
、SecretKey
和 SessionKey
。
在 iOS 上,我可以通过 RestKit 查询公共 API。
当我尝试通过 Postman 调用私有 API 方法时,我返回一个 HTTP 错误 401,正文为 "message": "Unauthorized"
。 (这是预期的,没有设置任何授权。)
失败的地方:
为了测试授权,我在 Postman 中尝试过
复制/粘贴 AWSCredentials 的SessionKey
我作为 HTTP Authorization
标头从 iOS 客户端获得 - 定义为 here (last paragraph - "API Gateway’s Authorizer for Cognito User Pools")
和X-Amz-Security-Token
标头
结果总是相同的 401 错误。
为了授权对私有 API 的调用,我需要设置什么作为 HTTP 标头? "Authorization" 应该可以工作 - 也许我缺少一些角色权限?
如何更好地调试权限/授权流程?
【问题讨论】:
你提到SessionKey
的使用;这是参考ID token
或Access Token
之一吗?换句话说,据我所知,它应该是JSON Web Key Token
。根据docs.aws.amazon.com/cognito/latest/developerguide/…
谢谢彼得 - 你似乎是对的,有两种令牌在使用,我不清楚使用哪一种。如果需要 JWT,我没有找到有关如何获取它的任何信息(android SDK docs.aws.amazon.com/cognito/latest/developerguide/… 中有一个方法,但 iOS SDK docs.aws.amazon.com/cognito/latest/developerguide/… 中没有)
我认为您使用类似于getSession(username, password: password, validationData: nil, scopes: nil)
的方法登录您的用户,该方法应该返回session
类型的AWSCognitoIdentityUserSession
对象;令牌可通过session.accessToken?.tokenString
访问
我正在使用来自 AWS 生成的演示项目的代码。它使用 [[AWSIdentityManager defaultIdentityManager] loginWithSignInProvider:[AWSCognitoUserPoolsSignInProvider sharedInstance] completionHandler:...]
我以为我可以通过重用 AWS 演示中的代码和 UI 来节省一些时间,但我开始后悔这个决定......
@PeterPajchl 你是对的,我发现了如何获得会话:AWSCognitoIdentityUserPool *pool = [AWSCognitoIdentityUserPool CognitoIdentityUserPoolForKey:AWSCognitoUserPoolsSignInProviderKey]; AWSCognitoIdentityUser *user = [pool currentUser]; AWSTask<AWSCognitoIdentityUserSession *> *task = [user getSession];
。然后,我可以使用task.result.idToken.tokenString as
Authorization` HTTP 标头,它可以工作。
【参考方案1】:
这是获取会话的方法:
AWSCognitoIdentityUserPool *pool = [AWSCognitoIdentityUserPool CognitoIdentityUserPoolForKey:AWSCognitoUserPoolsSignInProviderKey];
AWSCognitoIdentityUser *user = [pool currentUser];
AWSTask<AWSCognitoIdentityUserSession *> *task = [user getSession];
然后,task.result.idToken.tokenString
可以设置为“授权”标头,就可以了。
感谢彼得的提示!
【讨论】:
【参考方案2】:对于 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?)。我将“授权”值保留了很长时间,以便开发人员更容易知道这个隐藏对象的完整位置。您应该将其保存在您自己的 AuthorizationService 类中(或作为 AwsCredentials 的扩展成员?)
【讨论】:
谢谢 - 这基本上就是我在下面描述的内容。我不需要设置AccessKey
、SecretKey
和SessionKey
标头,只需Authorization
就足够了。【参考方案3】:
如果您使用 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))")
【讨论】:
以上是关于AWS API Gateway + Cognito 用户池授权方 + Lambda - 我需要设置哪些 HTTP 标头和权限?的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 Cognito 用户 ID 限制访问 AWS API Gateway 端点
AWS Cognito 和 AWS API Gateway 中的用户管理和基于令牌的身份验证
AWS API Gateway 身份验证(Cognito 与自定义授权者)
AWS API Gateway + Cognito 用户池授权方 + Lambda - 我需要设置哪些 HTTP 标头和权限?
如何为 CORS 预检请求绕过 AWS API Gateway 代理资源上的 Cognito 授权方?
具有 Cognito 身份验证的 AWS API Gateway Lambda 函数返回 415 Unsupported Media Type