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 详细信息转储到控制台,显示 AccessKeySecretKeySessionKey

在 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 tokenAccess 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:AWSCognitoUserPoolsSignInProvi‌​derKey]; 
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 的扩展成员?)

【讨论】:

谢谢 - 这基本上就是我在下面描述的内容。我不需要设置AccessKeySecretKeySessionKey 标头,只需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