[英]Verify and decode Cognito json web token from Lambda - Node Js
我已经设置了一个使用 Cognito、Lambda 和 API 网关的小型 Web 应用程序,用户通过 UI 中的 Cognito 进行身份验证。 我还为我的 ApiGateway 端点设置了一个 Cognito Authorizer,我从 UI 中测试了它,我复制并粘贴了我的令牌,它返回了 200。但是我需要在他请求一项服务时识别我的用户,所以我想解码和验证我在 lambda 的事件对象中获得的 JSON Web 令牌以获取有效负载和用户属性但我现在需要验证和解码 JSON Web 令牌,如库https://github.com/awslabs/aws的文档-jwt-verify要访问事件对象,我正在使用 aws-serverless-express/middleware 库,如下所示:
app.use(awsServerlessExpressMiddleware.eventContext())
现在可以像这样访问事件对象
const event = req.apiGateway.event;
这是我在 lambda 处理程序中的代码
const event = req.apiGateway.event;
const authToken = event.headers['Authorization'];
const verifier = CognitoJwtVerifier.create({
userPoolId: 'us-east-1_cDd9TR9a5',
tokenUse: "access",
clientId: '1irae6vkl1v4f8so6o09h787ev',
scope: "read"
});
try {
const payload = await verifier.verify(authToken);
console.log('Token is valid. Payload:', payload);
} catch (err) {
console.log(err);
console.log('Token not valid!');
}
但我收到这个错误
JwtInvalidScopeError:缺少范围。 预期:阅读
我也尝试像文档的第一个示例一样删除属性范围,但我也遇到了另一个错误
CognitoJwtInvalidTokenUseError:不允许使用令牌:id。 预期:访问
使用此代码:
节点 js 中 Cognito 的身份验证中间件
const AmazonCognitoIdentity = require("amazon-cognito-identity-js")
const { JwtRsaVerifier } = require("aws-jwt-verify")
const request = require("request")
const jwkToPem = require("jwk-to-pem")
const jwt = require("jsonwebtoken")
const poolData = {
UserPoolId: process.env.COGNITO_USER_POOL_ID,
ClientId: process.env.COGNITO_CLIENT_ID
}
const pool_region = process.env.AWS_REGION
const idTokenVerifier = JwtRsaVerifier.create({
issuer: `https://cognito-idp.${pool_region}.amazonaws.com/${poolData.UserPoolId}`,
jwksUri: `https://cognito-idp.${pool_region}.amazonaws.com/${poolData.UserPoolId}/.well-known/jwks.json`,
audience: process.env.COGNITO_CLIENT_ID
})
const renewToken = async (refreshToken, next, req, res) => {
const RefreshToken = new AmazonCognitoIdentity.CognitoRefreshToken({
RefreshToken: refreshToken
})
const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData)
const userData = {
Username: "",
Pool: userPool
}
const cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData)
await cognitoUser.refreshSession(RefreshToken, async (err, session) => {
if (err) {
console.log(err)
res.status(401).send({
success: false,
message: err.message
})
return
} else {
const tokenObj = {
access_token: session.accessToken.jwtToken,
id_token: session.idToken.jwtToken,
refresh_token: session.refreshToken.token
}
const userPayload = await idTokenVerifier.verify(tokenObj.id_token)
req.user = userPayload
next()
}
})
}
const auth = async (req, res, next) => {
if (
req.headers.authorization &&
req.headers.authorization.split(" ")[0] === "Bearer"
) {
const token = req.headers.authorization.split(" ")[1]
const idToken = req.headers.authorization.split(" ")[2]
const refreshToken = req.headers.authorization.split(" ")[3]
try {
await new Promise((_, reject) => {
request(
{
url: `https://cognito-idp.${pool_region}.amazonaws.com/${poolData.UserPoolId}/.well-known/jwks.json`,
json: true
},
function (error, response, body) {
if (!error && response.statusCode === 200) {
var pems = {}
var keys = body["keys"]
for (var i = 0; i < keys.length; i++) {
//Convert each key to PEM
var key_id = keys[i].kid
var modulus = keys[i].n
var exponent = keys[i].e
var key_type = keys[i].kty
var jwk = { kty: key_type, n: modulus, e: exponent }
var pem = jwkToPem(jwk)
pems[key_id] = pem
}
//validate the token
var decodedJwt = jwt.decode(token, { complete: true })
if (!decodedJwt) {
reject({
success: false,
message: "Not a valid JWT token"
})
}
var kid = decodedJwt.header.kid
var pem = pems[kid]
if (!pem) {
reject({
success: false,
message: "Invalid token"
})
}
jwt.verify(token, pem, async (err, payload) => {
if (err) {
// console.log("Invalid Token or JWT Token expired")
if (err.message === "jwt expired") {
await renewToken(refreshToken, next, req, res)
} else {
reject({
success: false,
message: "Token Expired"
})
}
} else {
if (payload.username) {
const userPayload = await idTokenVerifier.verify(idToken)
req.user = userPayload
next()
} else {
reject({
success: false,
message: "Invalid token"
})
}
}
})
} else {
console.log("Error! Unable to get JWKs")
return {
success: false,
message: "Error! Unable to get JWKs"
}
}
}
)
})
} catch (err) {
console.log(err)
res.status(401).send({
success: false,
message: "Unauthorized"
})
}
} else {
res.status(401).send({
success: false,
message: "No token provided"
})
}
}
module.exports = auth
使用示例:
const express = require("express")
const router = express.Router()
// ** import middleware **
const auth = require("../middleware/auth")
// ** import controllers **
const user = require("../controller/user")
// ** user routes
router.get("/user/get-profile", [auth], user.getProfile)
我希望这能帮到您!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.