如何解决使用用户池和身份池时的 Lambda 授权方与 IAM 授权方
在 AWS re-Invent 视频中,该解决方案使用了 Cognito 池 + 身份池
它还在 API 网关使用 lambda 授权器来验证令牌并生成策略。我正在阅读How to authenticate API Gateway calls with Facebook?
它说: 要使用联合身份,请将 API 网关方法设置为使用“AWS_IAM”授权。您使用 Cognito 创建角色并将其与您的 Cognito 身份池相关联。然后,您可以使用身份和访问管理 (IAM) 服务授予此角色调用 API 网关方法的权限。
-> 如果是这种情况,我们如何在使用身份池的同时使用 lambda 授权程序而不是 IAM 授权程序 -> 使用 IAM 授权器和在自定义授权器中生成 IAM 策略有什么区别,就像我在这里看到的那样:
const Promise = require('bluebird');
const jws = require('jws');
const jwkToPem = require('jwk-to-pem');
const request = require('request-promise');
const AWS = require('aws-sdk');
AWS.config.setPromisesDependency(Promise);
const s3 = new AWS.S3({ apiVersion: '2006-03-01' });
const { env: { s3bucket }} = process
// cache for certificates of issuers
const certificates = {};
// time tenant data was loaded
let tenantLoadTime = 0;
// promise containt tenant data
let tenantPromise;
// this function returns tenant data promise
// refreshes the data if older than a minute
function tenants() {
if (new Date().getTime() - tenantLoadTime > 1000 * 60) {
console.log('Tenant info outdated,reloading');
tenantPromise = s3.getobject({
Bucket: s3bucket,Key: 'tenants.json'
}).promise().then((data) => {
const config = JSON.parse(data.Body.toString());
console.log('Tenant config: %j',config);
const tenantMap = {};
config.forEach((t) => { tenantMap[t.iss] = t.id; });
return tenantMap;
});
tenantLoadTime = new Date().getTime();
}
return tenantPromise;
}
// helper function to load certificate of issuer
function getCertificate(iss,kid) {
if (certificates[iss]) {
// resolve with cached certificate,if exists
return Promise.resolve(certificates[iss][kid]);
}
return request({
url: `${iss}/.well-kNown/jwks.json`,method: 'GET'
}).then((rawBody) => {
const { keys } = JSON.parse(rawBody);
const pems = keys.map(k => ({ kid: k.kid,pem: jwkToPem(k) }));
const map = {};
pems.forEach((e) => { map[e.kid] = e.pem; });
certificates[iss] = map;
return map[kid];
});
}
// extract tenant from a payload
function getTenant(payload) {
return tenants().then(config => config[payload.iss]);
}
// Help function to generate an IAM policy
function generatePolicy(payload,effect,resource) {
return getTenant(payload).then((tenant) => {
if (!tenant) {
return Promise.reject(new Error('UnkNown tenant'));
}
const authResponse = {};
authResponse.principalId = payload.sub;
if (effect && resource) {
authResponse.policyDocument = {
Version: '2012-10-17',Statement: [{
Action: 'execute-api:Invoke',Effect: effect,Resource: resource
}]
};
}
// extract tenant id from iss
payload.tenant = tenant;
authResponse.context = { payload: JSON.stringify(payload) };
console.log('%j',authResponse);
return authResponse;
});
}
function verifyPayload(payload) {
if (payload.token_use !== 'id') {
console.log('Invalid token use');
return Promise.reject(new Error('Invalid token use'));
}
if (parseInt(payload.exp || 0,10) * 1000 < new Date().getTime()) {
console.log('Token expired');
return Promise.reject(new Error('Token expired'));
}
// check if iss is a kNown tenant
return tenants().then((config) => {
if (config[payload.iss]) {
return Promise.resolve();
}
console.log('Invalid issuer');
return Promise.reject();
});
}
function verifyToken(token,alg,pem) {
if (!jws.verify(token,pem)) {
console.log('Invalid Signature');
return Promise.reject(new Error('Token invalid'));
}
return Promise.resolve();
}
exports.handle = function handle(e,context,callback) {
console.log('processing event: %j',e);
const { authorizationToken: token } = e;
if (!token) {
console.log('No token found');
return callback('Unauthorized');
}
const { header: { alg,kid },payload: rawToken } = jws.decode(token);
const payload = JSON.parse(rawToken);
return verifyPayload(payload)
.then(() => getCertificate(payload.iss,kid))
.then(pem => verifyToken(token,pem))
.then(() => generatePolicy(payload,'Allow',e.methodArn))
.then(policy => callback(null,policy))
.catch((err) => {
console.log(err);
return callback('Unauthorized');
});
};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。