[英]How to verify accessToken in node/express using aws-amplify?
我在我的前端 React 應用程序上使用 AWS amplify 進行用戶身份驗證。 我的 React 應用程序直接與 amplify 通信,無需任何后端(節點服務器)交互。
我有一個用 node/express 編寫的 REST API。 我想使用放大來保護該 API。
目前,我計划將訪問令牌從我的反應應用程序傳遞到我的節點服務器。 但是我無法找到一種方法來使用放大在后端驗證此令牌。
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;
此中間件獲取授權標頭並使用 AWS Cognito REST API 驗證傳入的 accessToken。
為了在您的前端獲取 accessToken,您可以執行以下操作:
const { accessToken: { jwtToken } } = await Auth.currentSession();
這個jwtToken
是你的 accessToken,你可以在你的Authorization
標頭中發送它,然后使用我編寫的中間件在后端驗證它。
AWS 實際上已經很好地記錄了這一點。 我寫了一個關於我編寫的中間件的要點,用於在我的 express.js 服務器中驗證 AWS Cognito 令牌。
本質上,當您在 Amazon 中創建用戶池時,AWS 會創建一個 JSON Web Key (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
不幸的是,aws-amplify SDK 不提供該功能。 出於這個原因,我創建了一個npm 包來處理它。
該包公開:
authenticate
:一個 Express 中間件,可以添加到任何需要根據 Cognito 用戶池進行身份驗證的路由中。authenticationError
:一個 Express 錯誤處理程序,負責處理由authenticate
中間件生成的任何身份驗證錯誤。JWTValidator
:可以實例化以驗證 Cognito 發布的JWTValidator
的類。 如果您需要自定義身份驗證和錯誤處理邏輯,這將非常有用。 authenticate
中間件在內部使用它。// 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;
有關更高級的用例,請在此處查看文檔。
自 2021 年 9 月 17 日起,我們現在有了這個存儲庫(以及相關的 npm 包):
這允許我們(外部節點應用程序,通常是服務器端面向 Web 的應用程序)驗證由 AWS 簽名的 JWT,例如從 AWS cognito 發出的 JWT。
具體來說,由於令牌是非對稱簽名的,因此節點包的這個經過驗證的 AWS 帳戶發布者指的是 AWS 發布的 JSON Web 密鑰集 (JWKS),從而提高了對我們用來驗證 JWT 中包含的聲明的代碼的信任度,因為它們可以作為不記名令牌提供給我們的應用程序。
取自https://github.com/awslabs/aws-jwt-verify#express的示例代碼(在這種情況下它使用express
)似乎也非常用戶友好:
import express, { Request } from 'express';
import { CognitoJwtVerifier } from 'aws-jwt-verify';
const cognitoJWTVerifier = CognitoJwtVerifier.create({
userPoolId: 'your-user-pool-id', // mandatory, can't be overridden upon calling verify
tokenUse: 'access',
clientId: 'your-client-id',
});
app.get('/authenticated/route', async (req: Request & { verifiedCognitoJWT?: any }, res, next) => {
try {
const verifiedCognitoJWT = await cognitoJWTVerifier.verify(`${req.header('authorization')}`);
req.verifiedCognitoJWT = verifiedCognitoJWT;
next();
} catch (e) {
return res.status(401).json({ statusCode: 401, message: 'Unauthorized' });
}
}, getAuthenticatedRoute);
請注意,您可以選擇在您的應用程序開始偵聽 HTTP 連接之前調用hydrate()
來預取 JWKS,但省略此調用只會延遲對verify()
的第一次調用,該調用會延遲獲取它們。
當然,這個例子可以通過適當的類型進行擴展,或者根據需要內置到中間件等中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.