AWS API Gateway 身份验证(Cognito 与自定义授权者)

Posted

技术标签:

【中文标题】AWS API Gateway 身份验证(Cognito 与自定义授权者)【英文标题】:AWS API Gateway Authentication (Cognito Vs custom authrorizer) 【发布时间】:2017-03-12 10:58:03 【问题描述】:

我正在尝试使用联合身份验证制作无服务器应用程序(ReactJS、API Gateway、AWS Lambda、DynamoDB)。以下是我设想的那种架构(为简洁起见,没有添加 STS。另外我认为我不完全理解流程):

我创建了触发 lambda 函数的 API Gateway 端点。我想先用 google 对我的用户进行身份验证,如果他们成功了,那么他们应该能够使用 API 端点。

第一步是使用标准 Outh2 通过 google 对用户进行身份验证。为此,我创建了 2 个未经身份验证的端点 /signin/google 和 /callback/google。一旦我在回调 lambda 函数中从谷歌获得成功的身份验证响应,我就有了可以使用的 id_token(以及其他)。

目前,我有 2 种方法可用于验证 API。

    构建一个可用于 API 端点的自定义授权方。这是代码(https://github.com/prabhatsharma/api-gateway-custom-authorizer/)。这很简单。我可以使用 google 提供的相同 id_token 来验证 API 端点。自定义授权方将验证 id_token 是否良好并授予对端点的访问权限。它还将缓存结果,以便每次都不需要此验证。 (这样重用google的id_token是不是一个好方法?)你可以用这个授权器(https://github.com/prabhatsharma/lambda-custom-auth)

    我可以使用 AWS cognito 进行身份验证。为此,我创建了一个联合身份池,并将谷歌应用程序客户端 ID 设置为 cognito 控制台。在我的/callback/google lambda 函数中,我使用AWS SDK 来获取identityId、sessionToken 和accessKeyId。 (源码https://github.com/prabhatsharma/lambda-cognito-auth)

    // Add the Google access token to the Cognito credentials login map.
    AWS.config.credentials = new AWS.CognitoIdentityCredentials(
        IdentityPoolId: config.COGNITO_IDENTITY_POOL_ID,   //dauth
        Logins: 
            'accounts.google.com': JSON.parse(body).id_token
        
    );
    

现在我可以使用凭据通过以下代码获取令牌

    // Obtain AWS credentials
    AWS.config.credentials.get(function () 
        // Access AWS resources here.
        // Credentials will be available when this function is called.
        var identityId = AWS.config.credentials.identityId;

        var cognitoidentity = new AWS.CognitoIdentity();

        var params = 
            IdentityId: identityId, /* required */
            Logins: 
                'accounts.google.com': JSON.parse(body).id_token
            
        ;

        cognitoidentity.getOpenIdToken(params, function (err, data) 
            if (err) console.log(err, err.stack); // an error occurred
            else 
                console.log(data);           // successful response
                res.headers = 
                    location: config.APPLICAION_URL + '/auth/google?' + querystring.stringify(data)
                
                callback(null, res);   //redirect to front end application
            
        );

我现在可以将 identityId 和 Token 传递给我的前端 reactJS 应用程序。

这是我在理解这个概念时几乎不需要帮助的地方。我现在可以在浏览器中使用 AWS 开发工具包来访问 AWS 资源。但是坚持!!!通过 Gateway 创建标准 RESTful API 的目的不就是使用标准 javascript 而不依赖任何特定库吗?直接使用 AWS SDK 看起来更适合 android/ios/unity 应用程序的用例。我希望我团队中的开发人员也能够使用他们在这种情况下使用的标准前端 javascript 库。此外,我不想将导出的 API SDK 用于我的 API 端点,并且真的希望保持前端应用程序不受 AWS SDK 细节的影响。手动使用 v4 签名对每个请求进行签名是多余的工作。我们不能使用 Cognito 进行基于标准令牌的 API 端点访问吗?

这种身份验证的最佳做法是什么?我的想法是否正确?

免责声明 - 请不要使用 repos 中的代码。它正在进行中,尚未准备好生产。

【问题讨论】:

【参考方案1】:

您可以将自定义授权函数与 oauth2 令牌一起使用。或者, 您可以使用 Cognito 和相应的 IAM 角色来管理用户对您的 AWS 资源的访问。

您在流程图中描述的第二种方法不需要在每个请求前使用 auth lambda,并允许您控制从前端(例如物联网)对其他 AWS 资源的访问。

一旦你得到了secretKey、accessKey、sessionToken和region,你只需要对APIG的每一个请求进行签名。您不需要 AWS 开发工具包来执行此操作。

如果您不想使用导出的 API,则必须自己签署请求。它在sigV4Client.js 中实现,因此很容易复制。无论如何,您将需要很少的依赖项,那么为什么不使用导出的 API?你已经在使用这么大的 React。

【讨论】:

关于“您在流程图中描述的第二种方法,不需要在每个请求前面都有一个 auth lambda”,我认为自定义授权方方法不需要执行 auth lambda每个请求——它只为第一个 API 调用执行那个 lambda。对吗? 你说得对,ApiG 会将自定义授权方响应缓存一段配置的时间

以上是关于AWS API Gateway 身份验证(Cognito 与自定义授权者)的主要内容,如果未能解决你的问题,请参考以下文章

CloudFront 后面的 API Gateway 不支持 AWS_IAM 身份验证吗?

如何使用 AWS API Gateway 设置 OAuth2 身份验证提供程序?

如何在 AWS API Gateway 中调试“缺少身份验证令牌”?

AWS API Gateway 身份验证(Cognito 与自定义授权者)

如何针对我的 AWS Api Gateway 对后端服务进行身份验证

AWS API Gateway 身份验证错误 IncompleteSignatureException 使用带有 Auth0 的 JWT