如何使用 aws-amplify 验证 node/express 中的 accessToken?
Posted
技术标签:
【中文标题】如何使用 aws-amplify 验证 node/express 中的 accessToken?【英文标题】:How to verify accessToken in node/express using aws-amplify? 【发布时间】:2020-07-12 12:00:06 【问题描述】:我正在使用 AWS amplify 在我的前端 React 应用程序上进行用户身份验证。 我的 React 应用直接与 amplify 通信,无需任何后端(节点服务器)交互。
我有一个用 node/express 编写的 REST API。我想使用放大来保护该 API。
目前,我正计划将访问令牌从我的反应应用程序传递到我的节点服务器。但我无法找到一种方法可以在后端使用放大验证此令牌。
aws-amplify 包是否提供任何我可以传递访问令牌来验证它的功能?
类似Auth.verifyToken(<access_token>)
【问题讨论】:
【参考方案1】:很遗憾,官方的 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;
此中间件采用授权标头并使用 AWS Cognito REST API 验证传入的 accessToken。
为了在您的前端获取 accessToken,您可以执行以下操作:
const accessToken: jwtToken = await Auth.currentSession();
这个jwtToken
是你的accessToken,你可以在你的Authorization
标头中发送它,然后使用我编写的中间件在后端验证它。
【讨论】:
【参考方案2】:AWS 实际上已经很好地记录了这一点。我写了一个关于我编写的中间件的要点,用于在我的 express.js 服务器中验证 AWS Cognito 令牌。
本质上,当您在 Amazon 中创建用户池时,AWS 会创建一个 JSON Web 密钥 (JWK)。 JWT 包含一个公钥,您可以使用它来验证 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
);
完整 express.js 实现的我的 GIST: 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
【讨论】:
重要提示:对于阅读本文的任何人,请记得验证“iss”声明和“exp”声明!如果您不检查“iss”声明,任何拥有 AWS 账户的人都可以创建一个用户池并发出 JWT,这些 JWT 将通过您的应用程序进行身份验证。听起来很明显,但万一你忘记了!【参考方案3】:很遗憾,aws-amplify SDK 不提供该功能。为此,我创建了一个npm package 来处理它。
工作原理
包暴露:
authenticate
:一个 Express 中间件,可以添加到任何需要针对 Cognito 用户池进行身份验证的路由。
authenticationError
:一个 Express 错误处理程序,负责处理由 authenticate
中间件生成的任何身份验证错误。
JWTValidator
:可以实例化以验证 Cognito 发布的 JWT 的类。如果您需要自定义身份验证和错误处理逻辑,这很有用。 authenticate
中间件在内部使用它。
包含的功能
JWT 签名验证。 JWT 声明验证。 验证令牌未过期。 验证受众 (aud) 声明是否与有效声明之一匹配 配置中提供的受众群体。 验证颁发者 (iss) 声明对配置的用户是否有效 游泳池。 验证 token_use 声明与有效令牌用途之一匹配 在配置中提供。 支持 JWK 轮换,如 JWT signing key rotation thread 中所述。 能够为本地测试设置自定义 pem,而无需 创建用户池。基本用法
// 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。
【讨论】:
请不要只发布一些工具/包或库作为答案。至少在答案本身中展示how it solves the problem。 @Shree 我刚刚更新了它。谢谢你让我知道:) 这没有提供问题的答案。一旦你有足够的reputation,你就可以comment on any post;相反,provide answers that don't require clarification from the asker. @StevenSiebert 我刚刚编辑了我的答案,以明确 aws-amplify SDK 目前不提供此功能。感谢您的建议。以上是关于如何使用 aws-amplify 验证 node/express 中的 accessToken?的主要内容,如果未能解决你的问题,请参考以下文章
无法解析模块“@aws-amplify/ui-react/styles.css”的路径
如何在我的 Vuejs 项目中迁移 aws-amplify 以使用 Typescript?
如何按日期(createdAt)对aws-amplify中列表查询中的字段进行排序?