如何使用 aws-amplify 验证 node/express 中的 accessToken?

How to verify accessToken in node/express using aws-amplify?

我在我的前端 React 应用程序上使用 AWS amplify 进行用户身份验证。 我的 React 应用直接与 amplify 通信,无需任何后端(节点服务器)交互。

我有一个用 node/express 编写的 REST API。我想使用放大来确保 API。

目前,我正计划将访问令牌从我的 React 应用程序传递到我的节点服务器。但是我找不到一种方法可以在后端使用 amplify 验证此令牌。

aws-amplify 包是否提供任何功能,我可以在其中传递访问令牌来验证它?

类似于Auth.verifyToken(<access_token>)

很遗憾,官方aws-amplify SDK 中没有这样的方法。 在做了很多研究之后,我不得不为此编写自己的中间件。这并不像看起来那么困难,但唯一困难的部分是从庞大的 AWS 文档中收集正确的信息。

我已经编写了这个中间件来实现相同的目的,希望这对您有所帮助

import axios from 'axios'
import awsconfig from '../../aws-exports';

const COGNITO_URL = `https://cognito-idp.${awsconfig.aws_project_region}.amazonaws.com/`;

const authentication = async (req, res, next) => {
    try {
        const accessToken = req.headers.authorization.split(" ")[1];

        const { data } = await axios.post(
            COGNITO_URL,
            {
                AccessToken: accessToken
            },
            {
                headers: {
                    "Content-Type": "application/x-amz-json-1.1",
                    "X-Amz-Target": "AWSCognitoIdentityProviderService.GetUser"
                }
            }
        )

        req.user = data;
        next();
    } catch (error) {
        return res.status(401).json({
            message: 'Auth failed'
        });
    }
};

export default authentication;

此中间件获取授权 header 并使用 AWS Cognito REST 验证传入的 accessToken API。

为了在您的 front-end 上获取 accessToken,您可以这样做:

const { accessToken: { jwtToken } } = await Auth.currentSession();

这个 jwtToken 是您的 accessToken,您可以将它发送到您的 Authorization header,然后使用我编写的中间件在后端验证它。

AWS 实际上对此有很好的记录。我写了一个关于我编写的中间件的要点,用于在我的 express.js 服务器中验证 AWS Cognito 令牌。

本质上,当您在 Amazon 中创建用户池时,AWS 会创建一个 JSON Web 密钥 (JWK)。 JWT 包含一个 public 密钥,您可以使用它来验证 JWT 的签名。

处于高水平 Javascript:

import jwt from "jsonwebtoken";

const authToken = getJwtFromHeader(request);

// please remember to verify the "iss" claim and "exp" claim!
validateAuthToken(authToken);

// convert a jwk to a PEM for use by OpenSSL or crypto
const jwk = getJwkFromAWS();
const pem = jwkToPem(jwk);

// verify the signature of the token using the public key from AWS
await jwt.verify(authToken, pem, {algorithms: ['RS256']}, (err, decoded) =>{
  console.log('decoded', decoded);
  // TODO -- verify claims from decoded token
}); 

我的 GIST 完整 express.js 实现: https://gist.github.com/fourgates/92dc769468497863168417c3524e24dd

AWS 资源:

https://github.com/awslabs/aws-support-tools/tree/master/Cognito/decode-verify-jwt https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html

遗憾的是,aws-amplify SDK 不提供该功能。出于这个原因,我创建了一个 npm package 来处理它。

工作原理

包公开:

  • authenticate:一个 Express 中间件,可以添加到任何需要针对 Cognito 用户池进行身份验证的路由。
  • authenticationError:一个 Express 错误处理程序,负责处理由 authenticate 中间件生成的任何身份验证错误。
  • JWTValidator:一个 class,可以实例化以验证 Cognito 发布的 JWT。如果您需要自定义身份验证和错误处理逻辑,这将很有用。 authenticate 中间件在内部使用它。

包含的功能

  • JWT 签名验证。
  • JWT 声明验证。
  • 确认令牌未过期。
  • 验证观众 (aud) 声明是否与有效的声明之一相匹配 配置中提供的受众。
  • 验证颁发者 (iss) 声明对配置的用户有效 池.
  • 验证 token_use 声明是否与有效令牌使用之一匹配 配置中提供。
  • 按照 JWT 签名密钥中的描述支持 JWK 轮换 旋转线程.
  • 能够为本地测试设置自定义 PEMS,而无需 创建用户池。

基本用法

// app.js
'use strict';

const express = require('express');
const { authenticate, authenticationError } = require('aws-cognito-express');

const app = express();

// Add the authentication middleware.
app.use(authenticate({
  region: 'us-east-2',
  userPoolId: 'us-east-2_6IfDT7ZUq',
  tokenUse: ['id', 'access'],
  audience: ['55plsi2cl0o267lfusmgaf67pf']
}));

// Protected route.
app.get('/articles', (req, res, next) => {
  console.log('JWT payload: ', req.cognito);
});

// Add the authentication error handler.
app.use(authenticationError());

module.exports = app;

有关更高级的用例,请查看文档 here