AWS API 网关 - 将访问令牌与 Cognito 用户池授权方一起使用?

AWS API Gateway - using Access Token with Cognito User Pool authorizer?

我正在配置具有各种前端(移动和 Web 应用程序)和单个 API 后端的应用程序,由 Lambda 提供支持并通过 AWS API 网关访问。

因为我计划使用 Cognito 对用户进行身份验证和授权,所以我在我的 API 网关上设置了一个 Cognito 用户池授权方和几个 API 方法。

对于这样的架构,从 OAuth 的角度来看,我的应用程序(例如 iOS 或 Vue.js 应用程序)是客户端应用程序似乎是合乎逻辑的,而我的 API 网关后端是资源服务器。基于 this Auth0 forum post 看来我应该在我的客户端应用程序中使用 ID 令牌,并传递一个访问令牌来授权我的 API 网关资源。

当我点击 Cognito /oauth2/authorize 端点以获取访问代码并使用该代码点击 /oauth2/token 端点时,我获得了 3 个令牌 - 一个访问令牌、一个 ID 令牌和一个刷新令牌。到目前为止一切顺利,我应该有我需要的。

这是我 运行 遇到困难的地方 - 使用 API Gateway Cognito 用户池授权器控制台上的测试功能,我可以粘贴 ID 令牌并通过(解码屏幕上的令牌)。但是当我粘贴访问令牌时,我得到 401 - unauthorized.

在我的 Cognito 设置中,我只启用了 Authorization Code Grant 流,具有 emailopenid 范围(这似乎是 Cognito 允许的最小值,因为我在尝试时遇到错误至少不勾选这些即可保存)。

我是否需要添加一些特定范围才能让 API 网关使用访问代码授权请求?如果有,这些配置在哪里?

还是我遗漏了什么? API 网关是否仅允许 ID 令牌与 Cognito 用户池授权方一起使用?

是的,API网关将仅使用 idToken 进行授权。

用户输入正确的凭据后,身份提供商会提供访问代码,授权用户输入正确的凭据,此访问代码由 客户端只是为了从给定用户的 /oauth2/token 端点获取 idToken 和 refreshToken。您以后的所有调用都只会在授权中使用 idToken header。

即使访问代码在您检索用户令牌后也会过期。

您可以使用具有与 id 令牌相同的授权方的访问令牌,但需要在用户池和 APIG 中完成一些额外的设置。

即使完成了这个额外的设置,您也不能使用带有访问令牌的内置授权测试功能,只能使用 ID 令牌。来自 AWS 的典型 80% 解决方案!

要使用访问令牌,您需要在 App Integration -> Resource Servers 下的用户池中设置资源服务器,您使用什么并不重要,但我假设您使用 <site>.com 作为标识符,并且你有一个范围叫做 api.

否转到 APIG 中的方法并输入方法的 Method Request。假设这已经通过使用 id 令牌测试的授权方进行设置,然后将 <site>.com/api 添加到 Settings -> OAuth Scopes 部分。

只需添加 OAuth 范围,即可确保令牌现在必须是访问令牌并且不再接受 ID 令牌。

这里有详细说明:https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-enable-cognito-user-pool.html

对于那些正在寻找答案但未使用 OAuth 而正在使用无服务器框架进行部署的人:

让 APGW 接受 accessToken 的方法是修改我的 serverless.yml 文件,如下所示:

functions:
  my-function:
    handler: path to source file
    events:
      - http:
          path: my-function
          method: post
          cors: true
          authorizer:
            type: COGNITO_USER_POOLS
            scopes:
              - YOUR SCOPE HERE <- THIS IS THE TRICK
            authorizerId:
              Ref: ApiGatewayAuthorizer

可以通过读取 accessToken 的内容找到作用域的值(通过将令牌粘贴到 https://jwt.io/ 调试器)。