提问者:小点点

认知身份验证流失败,并显示“已找到用户名Facebook_10155611263153532的条目”


目标是实现社交提供程序身份验证流,如用户池应用集成和联合中所述。

一件重要的事情,我想满足,是合并用户池帐户,有相同的电子邮件地址。

我通过调用adminLinkProviderForUser内PreSignUp_ExternalProvider认知lambda触发器来实现这一点。

所以有了这个,一切都正常了。新的社交提供用户正在注册并与已经存在的Cognito(用户通行证)用户链接。

但是,从用户的角度来看,身份验证流不会完成。它在调用回调 uri(在 cognito 用户池中定义)的最后一步失败:

错误:invalid_request

error_description:已找到用户名条目Facebook_10155611263152353

但是,如果用户重试社交身份验证流程,一切正常,并将获得代表原始Cognito用户池用户(已经拥有该电子邮件的用户)的会话令牌。

注意,我正在一个空用户池上测试身份验证流,没有用户帐户。


共3个答案

匿名用户

对于所有在 2020 年仍然以同样的方式与这个问题作斗争的可怜灵魂:

    < li >我最终解决了这个问题,在我的客户端应用程序中捕捉到“已经找到用户名的条目”,并再次重复整个验证流程。 < li >幸运的是,该错误仅在初始外部提供商注册时触发,而不会在同一用户的后续登录中触发(因为它发生在注册触发期间,duh)。我大胆猜测一下,但我认为是这样的: < ul > < li >在我的案例中,facebook提供商成功地与预先存在的cognito电子邮件/密码用户链接。链接到电子邮件/密码用户的新脸书用户池条目已成功创建。 < li >尽管如此,cognito似乎试图在内部注册过程中注册完全独立的脸书_id用户(即使在上一步中已经创建了具有相同用户名的链接用户条目)。由于用户名为脸书id的“链接用户”已经存在,cognito抛出了一个“已经找到用户名脸书id错误的条目”的内部错误。 < li >自2017年以来,该错误已多次向AWS开发人员反映,甚至有一些他们正在处理的回复,但在2020年,该错误仍未修复。

匿名用户

是的,这就是它目前的设置方式。如果您尝试使用预注册触发器链接用户,则第一次将不起作用。处理此问题的更好方法(我认为)是在 UI 中提供一个选项,以便在登录时链接外部帐户。在预注册触发器中,搜索具有相同唯一属性(例如电子邮件)的用户,并查看注册是否来自外部提供商。然后显示一条消息,例如电子邮件已存在。登录

匿名用户

详细说一下@agent420的回答,这是我目前在用的(Typescript示例)。

当社交身份尝试注册并且电子邮件地址已经存在时,我使用PreSignUp触发器捕捉到这一点,然后向用户返回错误消息。在应用程序内部,在用户的配置文件页面上,有一个选项可以链接一个身份提供者,该提供者调用adminLinkProviderForUserAPI。

import {
    Context,
    CognitoUserPoolTriggerEvent,
    CognitoUserPoolTriggerHandler,
} from 'aws-lambda';
import * as aws from 'aws-sdk';
import { noTryAsync } from 'no-try';

export const handle: CognitoUserPoolTriggerHandler = async (
    event: CognitoUserPoolTriggerEvent,
    context: Context,
    callback: (err, event: CognitoUserPoolTriggerEvent) => void,
): Promise<any> => {
    context.callbackWaitsForEmptyEventLoop = false;

    const { email } = event.request.userAttributes;

    // pre sign up with external provider
    if (event.triggerSource === 'PreSignUp_ExternalProvider') {
        // check if a user with the email address already exists

        const sp = new aws.CognitoIdentityServiceProvider();

        const { error } = await noTryAsync(() =>
            sp
                .adminGetUser({
                    UserPoolId: 'your-user-pool-id',
                    Username: email,
                })
                .promise(),
        );

        if (error && !(error instanceof aws.AWSError)) {
            throw error;
        } else if (error instanceof aws.AWSError && error.code !== 'UserNotFoundException') {
            throw error;
        }
    }

    callback(null, event);
};