我正在尝试设计一个系统,在该系统中在我的 AWS 用户池中创建用户并将其分配给四个用户组之一。这些用户组具有附加到他们的角色,这些角色指定了他们被允许进行的 API 调用。我为每个组创建了一个用户,并且能够在我的 Android 应用程序中成功登录到他们。我的用户池也附加到一个身份池,用于使用身份联合处理单点登录。
问题是,当我登录用户时,不是假设分配给用户组的角色,而是分配给用户的角色似乎来自身份池而不是他们的用户组,因此他们无法进行他们应该有权访问的 api 调用。
我试图通过在 Node.js 中实现自定义授权器来解决此问题,但脚本似乎遇到了一些问题。每当它进入ValidateToken()方法时,它都无法说明令牌不是 JWT 令牌。
console.log('Loading function');
var jwt = require('jsonwebtoken');
var request = require('request');
var jwkToPem = require('jwk-to-pem');
var groupName = 'MY_GROUP_NAME';
var roleName = 'MY_ROLE_NAME';
var policyName = 'MY_POLICY_NAME';
var userPoolId = 'MY_USER_POOL_ID';
var region = 'MY_REGION';
var iss = 'https://cognito-idp.' + region + '.amazonaws.com/' + userPoolId;
var pems;
exports.handler = function(event, context) {
//Download PEM for your UserPool if not already downloaded
if (!pems) {
//Download the JWKs and save it as PEM
request({
url: iss + '/.well-known/jwks.json',
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
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;
}
//Now continue with validating the token
ValidateToken(pems, event, context);
} else {
//Unable to download JWKs, fail the call
context.fail("error");
}
});
} else {
//PEMs are already downloaded, continue with validating the token
ValidateToken(pems, event, context);
};
};
function ValidateToken(pems, event, context) {
var token = event.authorizationToken;
//Fail if the token is not jwt
var decodedJwt = jwt.decode(token, {complete: true});
if (!decodedJwt) {
//THIS IS WHERE THE SCRIPT ENDS UP
console.log("Not a valid JWT token");
context.fail("Unauthorized - Invalid Token Provided");
return;
}
//Fail if token is not from your UserPool
if (decodedJwt.payload.iss != iss) {
console.log("invalid issuer");
context.fail("Unauthorized - Invalid Issuer Provided");
return;
}
//Reject the jwt if it's not an 'Access Token'
if (decodedJwt.payload.token_use != 'access') {
console.log("Not an access token");
context.fail("Unauthorized - Not an Access Token");
return;
}
//Get the kid from the token and retrieve corresponding PEM
var kid = decodedJwt.header.kid;
var pem = pems[kid];
if (!pem) {
console.log('Invalid access token');
context.fail("Unauthorized - Invalid Access Token Provided");
return;
}
//Verify the signature of the JWT token to ensure it's really coming from your User Pool
jwt.verify(token, pem, { issuer: iss }, function(err, payload) {
if(err) {
console.log(err, err.stack); // an error occurred
context.fail("Unauthorized - Could not verify token signature");
}
else {
//Valid token. Generate the API Gateway policy for the user
//Always generate the policy on value of 'sub' claim and not for 'username' because username is reassignable
//sub is UUID for a user which is never reassigned to another user.
var principalId = payload.sub;
var username = payload.username;
var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
var params = {
UserPoolId: userPoolId, /* ID of the Target User Pool */
Username: username, /* Provided by event object??? */
Limit: 0,
NextToken: '' //May need actual token value
};
cognitoidentityserviceprovider.adminListGroupsForUser(params, function(err, data) {
if (err){
console.log(err, err.stack); // an error occurred
context.fail("Unauthorized - Could not obtain Groups for User");
}
else{
var groups = data.Groups;
var numGroups = groups.length;
var isFound = false;
for(var i = 0; i < numGroups; i++){
if(groups[i].GroupName == groupName){
isFound = true;
}
}
if(isFound){
var iam = new AWS.IAM();
var iamParams = {
PolicyName: policyName, /* Name of the Policy in the User Group Role */
RoleName: roleName /* Name of the User Group Role */
};
iam.getRolePolicy(params, function(err, data) {
if (err){
console.log(err, err.stack); // an error occurred
context.fail("Unauthorized - Could not acquire Policy for User Group Role");
}
else {
var policy = data.PolicyDocument;
context.succeed(policy); //May need to build policy
}
});
}
else{
context.fail("Unauthorized - Could not find the required User Group under the User");
}
}
});
}
});
}
谁能确定这个脚本的问题,或者帮助我确定为什么设置的令牌不是有效的 JWT 令牌?令牌由 Android 应用程序使用 AWS Cognito 开发工具包发送。
编辑:经过进一步调查,从 event.authorizationToken 检索到的令牌具有以下格式([VALUE] 块用于隐藏潜在的敏感信息):
AWS4-HMAC-SHA256 Credential=[VALUE1]/20170329/us-east-1/execute-api/aws4_request,
SignedHeaders=host;x-amz-date;x-amz-security-token,
Signature=[VALUE2]