Получение доступа к пользовательским атрибутам когнитивных данных из Lambda - PullRequest
1 голос
/ 28 мая 2020

Я использую в своей архитектуре функции Cognito, API Gateway и Lambda.

На клиенте я использую AWS Amplify.API, чтобы сделать запрос, и запрос авторизуется Cognito, как только он попадает в API Gateway . Если запрос авторизован, он передается в функцию Lambda, где мне нужно иметь доступ к вошедшему в систему пользователю, который делает запрос, чтобы иметь возможность запускать мой бизнес-журнал c.

В контексте функции Lambda у меня есть доступ к некоторым переменным среды, CognitoUserPoolId одна из них.

У меня также есть доступ к любому запросу, переданному через API, живущему в event.

{
  "tok": {
    "resource": "/some_resource",
    "path": "/some_resource",
    "httpMethod": "GET",
    "headers": {
      "Accept": "application/json",
      "Accept-Encoding": "gzip, deflate, br",
      "Accept-Language": "en-GB,en;q=0.9,sv;q=0.8,en-US;q=0.7,el;q=0.6,de;q=0.5,el-GR;q=0.4",
      "CloudFront-Forwarded-Proto": "https",
      "CloudFront-Is-Desktop-Viewer": "true",
      "CloudFront-Is-Mobile-Viewer": "false",
      "CloudFront-Is-SmartTV-Viewer": "false",
      "CloudFront-Is-Tablet-Viewer": "false",
      "CloudFront-Viewer-Country": "SE",
      "content-type": "application/json",
      "Host": "XXXXXX.execute-api.eu-central-1.amazonaws.com",
      "origin": "http://localhost:8080",
      "Referer": "http://localhost:8080/some_resource",
      "sec-fetch-dest": "empty",
      "sec-fetch-mode": "cors",
      "sec-fetch-site": "cross-site",
      "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36",
      "Via": "2.0 XXXXXXXXXXXX.cloudfront.net (CloudFront)",
      "X-Amz-Cf-Id": "XXXXXXXXXXXXXXXXXXXXXXXXTelrg==",
      "x-amz-date": "20200527T233945Z",
      "x-amz-security-token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX8fR",
      "X-Amzn-Trace-Id": "Root=1-5XXXXa41-730XXXXXXXXXXabe42f1",
      "X-Forwarded-For": "XXX.XXX.XX.XXX, XXX.XXX.XXX.XXX",
      "X-Forwarded-Port": "443",
      "X-Forwarded-Proto": "https"
    },
    "multiValueHeaders": {
      "Accept": [
        "application/json"
      ],
      "Accept-Encoding": [
        "gzip, deflate, br"
      ],
      "Accept-Language": [
        "en-GB,en;q=0.9,sv;q=0.8,en-US;q=0.7,el;q=0.6,de;q=0.5,el-GR;q=0.4"
      ],
      "CloudFront-Forwarded-Proto": [
        "https"
      ],
      "CloudFront-Is-Desktop-Viewer": [
        "true"
      ],
      "CloudFront-Is-Mobile-Viewer": [
        "false"
      ],
      "CloudFront-Is-SmartTV-Viewer": [
        "false"
      ],
      "CloudFront-Is-Tablet-Viewer": [
        "false"
      ],
      "CloudFront-Viewer-Country": [
        "SE"
      ],
      "content-type": [
        "application/json"
      ],
      "Host": [
        "XXXXXX.execute-api.eu-central-1.amazonaws.com"
      ],
      "origin": [
        "http://localhost:8080"
      ],
      "Referer": [
        "http://localhost:8080/some_resource"
      ],
      "sec-fetch-dest": [
        "empty"
      ],
      "sec-fetch-mode": [
        "cors"
      ],
      "sec-fetch-site": [
        "cross-site"
      ],
      "User-Agent": [
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"
      ],
      "Via": [
        "2.0 XXXXXXXXXXXX.cloudfront.net (CloudFront)"
      ],
      "X-Amz-Cf-Id": [
        "XXXXXXXXXXXXXXXXXXXXXXXXTelrg=="
      ],
      "x-amz-date": [
        "20200527T233945Z"
      ],
      "x-amz-security-token": [
        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX8fR"
      ],
      "X-Amzn-Trace-Id": [
        "Root=1-5XXXXa41-730XXXXXXXXXXabe42f1"
      ],
      "X-Forwarded-For": [
        "XXX.XXX.XX.XXX, XXX.XXX.XXX.XXX"
      ],
      "X-Forwarded-Port": [
        "443"
      ],
      "X-Forwarded-Proto": [
        "https"
      ]
    },
    "queryStringParameters": null,
    "multiValueQueryStringParameters": null,
    "pathParameters": null,
    "stageVariables": null,
    "requestContext": {
      "resourceId": "5qXXXXXXX",
      "resourcePath": "/some_resource",
      "httpMethod": "GET",
      "extendedRequestId": "NNwKXXXXXXXXX=",
      "requestTime": "27/May/2020:23:39:45 +0000",
      "path": "/dev/some_resource",
      "accountId": "18XXXXXXXX",
      "protocol": "HTTP/1.1",
      "stage": "dev",
      "domainPrefix": "XXXXXX",
      "requestTimeEpoch": 1590622785474,
      "requestId": "XXXXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX",
      "identity": {
        "cognitoIdentityPoolId": "eu-central-1:XXXXXX-YYY-YYYY-YYYY-YYYYY",
        "accountId": "181606720624",
        "cognitoIdentityId": "eu-central-1:XXXXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX",
        "caller": "SOME_STRING_HERE:CognitoIdentityCredentials",
        "sourceIp": "XXX.XXX.XXX.XXX",
        "principalOrgId": null,
        "accessKey": "ACCESS_KEY_HERE",
        "cognitoAuthenticationType": "authenticated",
        "cognitoAuthenticationProvider": "cognito-idp.eu-central-1.amazonaws.com/eu-central-1_XXXXXX,cognito-idp.eu-central-1.amazonaws.com/eu-central-1_XXXXXX:CognitoSignIn:XXXXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX",
        "userArn": "arn:aws:sts::XXXXXX:assumed-role/amplify-XXXXXX-dev-XXXXXX-authRole/CognitoIdentityCredentials",
        "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36",
        "user": "SOME_STRING_HERE:CognitoIdentityCredentials"
      },
      "domainName": "XXXXXX.execute-api.eu-central-1.amazonaws.com",
      "apiId": "XXXXXX"
    },
    "body": null,
    "isBase64Encoded": false
  }
}

Имея под рукой всю эту информацию, как я могу получить доступ к пользовательским атрибутам пользователя, который сделал запрос?

Я изучал: Boto3 CognitoIdentityProvider.get_user () и Boto3 CognitoIdentityProvider.admin_get_user () , однако для обоих требуется либо AccessToken, либо userId, и ни один из них не доступен в контексте функции Lambda. Единственный способ, который я придумал, - это передать некоторую дополнительную информацию в полезных данных запроса, но на самом деле это не кажется лучшим способом получить атрибуты пользователя.

EDIT

Я не использую специальный авторизатор в API. При настройке API с помощью Amplify я выбрал защищенные пути, и все запросы аутентифицируются / авторизуются в пуле пользователей Cognito. После amplify push я вижу, что развернутый API имеет AWS_IAM под Auth в запросе метода для всех ресурсов.

Amplify.API.get при выполнении запроса включает заголовки для авторизации, а точнее:

:authority: XXXXXX.execute-api.eu-central-1.amazonaws.com
:method: GET
:path: /dev/some_resource
:scheme: https
accept: application/json
accept-encoding: gzip, deflate, br
accept-language: en-GB,en;q=0.9,sv;q=0.8,en-US;q=0.7,el;q=0.6,de;q=0.5,el-GR;q=0.4
authorization: AWS4-HMAC-SHA256 Credential=ASIAXXXXXXXX/20200528/eu-central-1/execute-api/aws4_request, SignedHeaders=accept;content-type;host;x-amz-date;x-amz-security-token, Signature=b6a7aXXX1c447bXXX...XXX
content-type: application/json
origin: http://localhost:8080
referer: http://localhost:8080/dashboard
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36
x-amz-date: 20200528T075958Z
x-amz-security-token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX...XXXXXXXXXX

Ресурс API интегрирован в лямбда-функцию с интеграцией лямбда-прокси. Я вижу, что вызывается функция Lambda, поэтому запрос разрешен правильно. Однако все, что у меня есть в event в Lambda, - это то, что я вставил в первый клип выше.

Учитывая, что это интеграция с прокси, я ожидаю, что все, что находится в контексте в API, должно будут перенаправлены в Lambda за API. Однако я не вижу, как получить доступ к атрибутам user_attributes с помощью какой-либо информации, доступной в Lambda. Любые указатели?

EDIT 2

Сейчас я изучаю возможность передачи пользовательских данных от клиента с использованием настраиваемых заголовков, возможно, что-то вроде:

'x-user-sub': '58ce94f6-53vd-4s3e-b088-cd6f85s0ff43'

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

  c_client = boto3.client('cognito-idp')
  response = c_client.admin_get_user(
    UserPoolId='eu-central-1_XXXXXX',
    Username='58ce94f6-53vd-4s3e-b088-cd6f85s0ff43'
  )

Вышеуказанное возвращает:

{
  'Username': '58ce94f6-53vd-4s3e-b088-cd6f85s0ff43',
  'UserAttributes': [
    {
      'Name': 'sub',
      'Value': '58ce94f6-53vd-4s3e-b088-cd6f85s0ff43'
    },
    {
      'Name': 'email_verified',
      'Value': 'true'
    },
    {
      'Name': 'phone_number_verified',
      'Value': 'true'
    },
    {
      'Name': 'phone_number',
      'Value': '+46XXXXXXXXXX'
    },
    {
      'Name': 'email',
      'Value': 'XXXXXX.XXXXX@YYYY.com'
    }
  ],
  'UserCreateDate': datetime.datetime(2020, 5, 14, 15, 43, 3, 370000, tzinfo=tzlocal()),
  'UserLastModifiedDate': datetime.datetime(2020, 5, 15, 16, 32, 43, 424000, tzinfo=tzlocal()),
  'Enabled': true,
  'UserStatus': 'CONFIRMED',
  'ResponseMetadata': {
    'RequestId': 'e441edd4-XXX-46ba-XXX-922691471f2c',
    'HTTPStatusCode': 200,
    'HTTPHeaders': {
      'date': 'Thu, 28 May 2020 12:58:18 GMT',
      'content-type': 'application/x-amz-json-1.1',
      'content-length': '431',
      'connection': 'keep-alive',
      'x-amzn-requestid': 'e441edd4-XXX-46ba-XXX-922691471f2c'
    },
    'RetryAttempts': 0
  }
}

Есть ли что-нибудь очевидное, что я отсутствует с этим решением? Вношу ли я какие-либо риски безопасности, передавая sub в заголовке клиента?

Любая помощь очень ценится.

1 Ответ

1 голос
/ 28 мая 2020

Думаю, этот пост здесь может вам помочь.

В частности, эта часть:

Авторизатор API Gateway для пользовательских пулов Cognito

API Gateway недавно запустил поддержку Cognito User Pool Authorizer. Если вы используете Cognito User Pool Authorizer, вам не нужно настраивать собственный пользовательский авторизатор для проверки токенов. После того, как ваши методы API настроены с помощью Cognito User Pool Authorizer, вы можете передать токен идентификатора с неистекшим сроком действия в заголовке авторизации своим методам API. Если это действительный токен идентификатора для пользователя вашего пула пользователей, вы можете получить доступ ко всем утверждениям идентификатора токена в своем API с помощью $ context.authorizer.claims.

Например, «$ context.authorizer.claims.email» вернет адрес электронной почты пользователя, а «$ context.authorizer.claims.sub» вернет вам уникальный идентификатор пользователя. Если срок действия токена ID истек или он недействителен, Cognito User Pool Authorizer отправит вызывающему абоненту ответ «Неавторизованный» (401).

Здесь есть несколько примеров того, как переопределить apigateway параметры запроса / ответа

Здесь вы можете увидеть, как настроить интеграцию и какие данные передаются в API Gateway.

Стоит проверить ссылки на data сопоставление и доступ к журналу

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...