Да. Вы можете сделать это, используя AdminLinkProviderForUser
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminLinkProviderForUser.html
Идея такова:
- В лямбда-хуке 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 записи, но при доступе к записи пользователя подробно, они уже слились.