AWS Cognito: Лучшая практика для обработки входа одного и того же пользователя (с тем же адресом электронной почты) от разных провайдеров идентификации (Google, Facebook) - PullRequest
5 голосов
/ 07 января 2020

При входе пользователя с тем же адресом электронной почты через провайдеров идентификации Google и Facebook AWS Cognito создает несколько записей в пуле пользователей, по одной записи для каждого провайдера идентификации:

Screenshot of AWS Cognito user pool

Я использовал пример кода, приведенный в этом руководстве, для настройки AWS Cognito: Полное руководство по аутентификации пользователей с помощью Amplify Framework

  • Как я могу создать только одного пользователя вместо нескольких пользователей?
  • Возможно ли иметь AWS Cognito автоматически объединяет (объединяет) записи от нескольких провайдеров в одну запись или должна AWS Lambda функции, используемые для достижения sh этого?

1 Ответ

6 голосов
/ 08 января 2020

Да. Вы можете сделать это, используя AdminLinkProviderForUser https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminLinkProviderForUser.html

Идея такова:

  1. В лямбда-хуке PreSignUp мы связываем провайдера с пользователем, если пользователь уже подписали. Например:
import CognitoIdentityServiceProvider from 'aws-sdk/clients/cognitoidentityserviceprovider'

const cognitoIdp = new CognitoIdentityServiceProvider()
const getUserByEmail = async (userPoolId, email) => {
 const params = {
   UserPoolId: userPoolId,
   Filter: `email = "${email}"`
 }
 return cognitoIdp.listUsers(params).promise()
}

const linkProviderToUser = async (username, userPoolId, providerName, providerUserId) => {
 const params = {
   DestinationUser: {
     ProviderAttributeValue: username,
     ProviderName: 'Cognito'
   },
   SourceUser: {
     ProviderAttributeName: 'Cognito_Subject',
     ProviderAttributeValue: providerUserId,
     ProviderName: providerName
   },
   UserPoolId: userPoolId
 }

 const result = await (new Promise((resolve, reject) => {
   cognitoIdp.adminLinkProviderForUser(params, (err, data) => {
     if (err) {
       reject(err)
       return
     }
     resolve(data)
   })
 }))

 return result
}

exports.handler = async (event, context, callback) => {
 if (event.triggerSource === 'PreSignUp_ExternalProvider') {
   const userRs = await getUserByEmail(event.userPoolId, event.request.userAttributes.email)
   if (userRs && userRs.Users.length > 0) {
     const [ providerName, providerUserId ] = event.userName.split('_') // event userName example: "Facebook_12324325436"
     await linkProviderToUser(userRs.Users[0].Username, event.userPoolId, providerName, providerUserId)
   } else {
     console.log('user not found, skip.')
   }

 }
 return callback(null, event)
}
Затем, когда пользователь использует OAuth с Facebook / Google с пулом пользователей, пул вернет этого пользователя связанным.

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

...