У меня есть типичная установка AWS, использующая API Gateway с аутентификацией пула пользователей Cognito и интегрированная с функциями Lambda.

Все работает нормально, но теперь мне нужно иметь возможность получить идентифицированный идентификатор пользователя внутри Lambda.

Я видел много вопросов / ответов об этом на SO, но ни один из них не помог сделать это. Наиболее близким является этот ответ, который ссылается на эта документация.

Из этих ссылок выше я понимаю, что мне нужно получить доступ к некоторому свойству «$ context.authorizer.claims» в моем шаблоне сопоставления, чтобы получить идентификатор пользователя, но я не смог найти список доступных свойств или какое из них следует использовать.

Я также пытался использовать «$ context.authorizer.principalId», но это только возвращает пустую строку.

В настоящее время я использую шаблон отображения API-интерфейса шлюза «Метод запроса», но до сих пор пробовал много различных шаблонов отображения.

Что я здесь упускаю или делаю не так?

Пожалуйста, дайте мне знать, если требуется дополнительная информация.

5
GCSDC 1 Май 2019 в 21:27

3 ответа

Лучший ответ

Для тех, кто сталкивается с этой проблемой. « $ context.authorizer. * » всегда будет пустым, пока вы не протестируете его с помощью AWS Api Gateway / Lambda test. Просто протестируйте его с помощью внешних инструментов, таких как Postman, и он будет заполнен.

1
Ihor Pavlyk 11 Авг 2019 в 17:06

Я изо всех сил пытался найти ответ на эту проблему некоторое время, потому что нет никаких кратких ответов ни на одну из этих тем в Интернете.

Похоже, вы пытаетесь придумать эффективную стратегию Authorization после того, как у пользователя есть Authenticated свои учетные данные в вашем Cognito User Pool с использованием пользовательских атрибутов.

Я создал библиотеку, которую я использую для экспорта нескольких функций, которые позволяют мне захватывать UserPoolId и Username для пользователя аутентифицированного , чтобы я мог захватить {{X2 }} Мне нужно в своей лямбде, чтобы реализованные мною условия могли использовать API для остальных сервисов AWS, для которых мне необходимо предоставить авторизацию для каждого пользователя, прошедшего проверку подлинности моим приложением.

Вот моя библиотека:

import AWS from "aws-sdk";
// ensure correct AWS region is set
AWS.config.update({
    region: "us-east-2"
});

// function will parse the user pool id from a string
export function parseUserPoolId(str) {
    let regex = /[^[/]+(?=,)/g;
    let match = regex.exec(str)[0].toString();

    console.log("Here is the user pool id: ", match);

    return match.toString();
}

// function will parse the username from a string
export function parseUserName(str) {
    let regex = /[a-z,A-Z,0-9,-]+(?![^:]*:)/g;
    let match = regex.exec(str)[0].toString();

    console.log("Here is the username: ", match);

    return match.toString();
}

// function retries UserAttributes array from cognito
export function getCustomUserAttributes(upid, un) {
    // instantiate the cognito IdP
    const cognito = new AWS.CognitoIdentityServiceProvider({
        apiVersion: "2016-04-18"
    });

    const params = {
        UserPoolId: upid,
        Username: un
    };

    console.log("UserPoolId....: ", params.UserPoolId);
    console.log("Username....: ", params.Username);

    try {
        const getUser = cognito.adminGetUser(params).promise();
        console.log("GET USER....: ", getUser);
        // return all of the attributes from cognito
        return getUser;
    } catch (err) {
        console.log("ERROR in getCustomUserAttributes....: ", err.message);
        return err;
    }
}

После внедрения этой библиотеки она может использоваться любой лямбдой, для которой вам нужно создать стратегию авторизации.

Внутри вашей лямбды вам нужно импортировать библиотеку выше (я пропустил операторы импорта ниже, вам нужно будет добавить их, чтобы вы могли получить доступ к экспортируемым функциям), и вы можете реализовать их использование как таковое:

export async function main(event, context) {
  const upId = parseUserPoolId(
    event.requestContext.identity.cognitoAuthenticationProvider
  );
  // Step 2 --> Get the UserName from the requestContext
  const usrnm = parseUserName(
    event.requestContext.identity.cognitoAuthenticationProvider
  );
  // Request body is passed to a json encoded string in
  // the 'event.body'
  const data = JSON.parse(event.body);

  try {
    // TODO: Make separate lambda for AUTHORIZATION
    let res = await getCustomUserAttributes(upId, usrnm);

    console.log("THIS IS THE custom:primaryAccountId: ", res.UserAttributes[4].Value);
    console.log("THIS IS THE custom:ROLE: ", res.UserAttributes[3].Value);
    console.log("THIS IS THE custom:userName: ", res.UserAttributes[1].Value);

    const primaryAccountId = res.UserAttributes[4].Value;

  } catch (err) {
    // eslint-disable-next-line
    console.log("This call failed to getattributes");
    return failure({
      status: false
    });
  }
}


Ответ от Cognito предоставит массив с нужными вам пользовательскими атрибутами. Console.log ответ от Cognito с console.log("THIS IS THE Cognito response: ", res.UserAttributes); и проверьте номера индексов для атрибутов, которые вы хотите в ваших журналах CloudWatch и скорректируйте индекс, необходимый с:

res.UserAttributes[n]

Теперь у вас есть механизм authorization, который вы можете использовать с различными условиями в вашей лямбде, чтобы позволить пользователю отправлять POST в DynamoDB или использовать любые другие сервисы AWS из вашего приложения с правильной авторизацией для каждого аутентифицированного пользователя.

0
lopezdp 29 Янв 2020 в 18:59