AWS Amplify: Как сопоставить атрибуты социальных провайдеров для аутентификации на основе электронной почты? - PullRequest
2 голосов
/ 08 мая 2020

У меня есть веб-приложение React, созданное с помощью AWS Amplify Я добавил аутентификацию с пулами пользователей Cognito, я не использую имена пользователей, я выбрал логин, используя только электронную почту / телефон, мне не нужны имена пользователей, но Cognito в любом случае создает случайное имя пользователя.

Я хочу, чтобы пользователь входил в систему, используя свою электронную почту или одного социального провайдера (Facebook или Google), и это не имеет значения, они должны иметь доступ к той же учетной записи на основе электронное письмо.

Думаю, вполне нормальная практика. Однако, когда я впервые попытался войти в систему с помощью социального провайдера, я заметил, что вместо Cognito предоставляет мне ту же учетную запись, он создал новую, с другим именем пользователя и с EXTERNAL_PROVIDER в качестве статуса учетной записи в пуле пользователей

Итак, я подумал, что это может быть просто некорректное сопоставление, я перешел к сопоставлению атрибутов в разделе Федерации и увидел, что идентификатор Facebook и подписка Google были назначены имени пользователя, я попытался удалить его и для к моему удивлению, он вернулся к имени пользователя. Затем я подумал: «Я могу просто создать настраиваемый атрибут для хранения этой информации, и все будет хорошо».

Итак, я сделал это, создал один атрибут для Facebook, один для GoogleId ... попробовал еще раз ... нет, все еще возвращаюсь к имени пользователя, но без сообщения об ошибке, ничего ...

Я обратился за помощью по документации и нашел это

В настоящее время с атрибутом имени пользователя Amazon Cognito User Pools можно сопоставить только идентификатор Facebook, подписку Google, логин с помощью Amazon user_id и подписку на подписку Apple.

Если это всегда связывает идентификатор каждого провайдера с username, то нет возможности объединить эти учетные записи, я думал, что мне может понадобиться настроить пул федеративной идентификации, но, читая об этом, кажется, что он используется для предоставления ролей / разрешений IAM внешним пользователям, что я не Не хочу.

Есть идеи, как я могу этого добиться?

1 Ответ

3 голосов
/ 09 мая 2020

Покопавшись немного, я нашел решение. Таким образом, вам следует:

  • Создать триггер в Cognito для предварительной регистрации на лямбда-функцию
  • Эта лямбда-функция должна найти соответствующую учетную запись и связать обоих пользователей
  • Возвращает событие из лямбда-функции

Вы можете создать триггер из Amplify cli, запустив amplify auth update, выполнив «Прохождение всех конфигураций аутентификации», в конце концов, он будет спросите вас, хотите ли вы создать триггер, подтвердите его и выберите Триггер предварительной регистрации

Затем отредактируйте созданный файл функции, время выполнения по умолчанию - nodejs, я изменил свой на Python

Это код, который я использую

import boto3

client = boto3.client('cognito-idp')


def handler(event, context):
    print("Event: ", event)
    email = event['request']['userAttributes']['email']

    # Find a user with the same email
    response = client.list_users(
        UserPoolId=event['userPoolId'],
        AttributesToGet=[
            'email',
        ],
        Filter='email = "{}"'.format(email)
    )

    print('Users found: ', response['Users'])

    for user in response['Users']:
        provider = None
        provider_value = None
        # Check which provider it is using
        if event['userName'].startswith('Facebook_'):
            provider = 'Facebook'
            provider_value = event['userName'].split('_')[1]
        elif event['userName'].startswith('Google_'):
            provider = 'Google'
            provider_value = event['userName'].split('_')[1]

        print('Linking accounts from Email {} with provider {}: '.format(
            email,
            provider_value
        ))

        # If the signup is coming from a social provider, link the accounts
        # with admin_link_provider_for_user function
        if provider and provider_value:
            print('> Linking user: ', user)
            print('> Provider Id: ', provider_value)
            response = client.admin_link_provider_for_user(
                UserPoolId=event['userPoolId'],
                DestinationUser={
                    'ProviderName': 'Cognito',
                    'ProviderAttributeValue': user['Username']
                },
                SourceUser={
                    'ProviderName': provider,
                    'ProviderAttributeName': 'Cognito_Subject',
                    'ProviderAttributeValue': provider_value
                }
            )
    # Return the event to continue the workflow
    return event
...