微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用用户池和身份池时的 Lambda 授权方与 IAM 授权方

如何解决使用用户池和身份池时的 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 策略有什么区别,就像我在这里看到的那样:

https://github.com/aws-quickstart/saas-identity-cognito/blob/96531568b5bd30106d115ad7437b2b1886379e57/functions/source/custom-authorizer/index.js

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 举报,一经查实,本站将立刻删除。