By using AWS re:Post, you agree to the Terms of Use

Cognito auth flow fails with "Already found an entry for username [<USERNAME>]"

1

This is just a repost from stackowerflow. Cognito team seems to be unwilling to fix this serious bug.

https://stackoverflow.com/questions/47815161/cognito-auth-flow-fails-with-already-found-an-entry-for-username-facebook-10155

The goal is to implement a social provider auth flow as described in User Pools App Integration and Federation. One important thing that I want to satisfy, is to merge user pool accounts that have the same email address. I am accomplishing that by calling adminLinkProviderForUser within the PreSignUp_ExternalProvider cognito lambda trigger. So with this, everything works. The new social provided user is being registered and linked with the already existing Cognito (user+pass) user. However, the authentication flow, from user's perspective doesn't complete. It fails at the last step where the callback uri (defined in cognito user pool) is being called:

error: invalid_request
error_description: Already found an entry for username Facebook_10155611263152353

But then, if the user retries the social auth flow, everything works, and would get session tokens that represent the original Cognito User Pool user (the one that already had that email). Note that I'm testing the auth flow on an empty User Pool, zero user accounts.

asked 2 months ago152 views
2 Answers
0

Hello,

I understand that you are trying to link/merge the social provider account of your user to the existing native Cognito account in the user pool and to implement the above, you are using AdminLinkProviderForUser API call in PreSignUp lambda trigger. However, when implementing the same, you observed that the user needs to sign-in twice.

Limitation :

Currently, this is a known limitation in Cognito where AdminLinkProvider actions aren't supported in the pre-signup Lambda. I've added your case to the internal feature request in an effort to push for a resolution.


Behavior :

When calling AdminLinkProviderForUser in Pre Sign-up Lambda Trigger is that it will pop up an aliasExistsException in for the user's first time sign-in from the 3rd party IdP(say google) side and the first time sign-in would always fail. [1]


Feature Request :

I apologize for the inconvenience this lack of functionality might cause you. However, we already have a feature request in place on our internal tracker to add this functionality, and I have added your request to it, to increase it's visibility to the service team. However at this point, I cannot comment on an ETA of release of this feature. The AWS service teams use these feature requests, in conjunction with other avenues of customer feedback, to plan and prioritize the features they deliver. I recommend to keep an eye on our News Blog for this or any future feature releases.

What's New at AWS - https://aws.amazon.com/new/

AWS Blog - https://aws.amazon.com/blogs/aws/


Workaround :

Unfortunately, currently there is no official workaround for this scenario, however if you still have any questions or concerns then please feel free to create a support case with our premium support team to discuss this issue with us.


Posibilities without PreSignUp Trigger Usage:

Please note again that this is not an official solution. You may evaluate this possible workaround where you are using this API programmatically and change it accordingly to your own use case.

  • Prerequisites

    1. Use code grant or implicit grant flow for the OAuth2 flow. Code Grant flow would be more recommended.
    2. Avoid pre-sign-up lambda set up for link providers.
    3. The app client of the user pool has enabled custom auth flow. The custom auth flow is using passwordless login which is using UserPool token would as authentication method.

Scenario A: A native user with the same email address already exists in the User Pool. And the user having the same email address first time login via 3rd party IdP.

Steps

1.When the Federated user first time sign-in from 3rd Party IdP, eg. Google. User Pool will create a new External_provider user and return the user pool tokens. Then the browser will redirect to the URL as defined in the User Pool App Client settings. For example, the callback url is https://yourappdomain.com/cuplogin
2. Your application server or script on the above callback url should make following steps to link the users. 

A. Fetch the tokens from Cognito OAuth2 token endpoint (code grant flow) or from the callback URL (implicit grant)

B. Client application sends the user's id token to a backend endpoint which can be built with APIGateway and lambda. Inside that lambda fuction, do the following steps:

  1. get External_provider user's userid and IdP name.
  2. search the native user pool user's user name by the email, Note, if your user pool is using email/phone as username, the actual username should be the SUB value.
  3. delete the External_provider User
  4. call adminLinkProviderForUser API with Source User (External IdP userid and IdP name got from step a.) and Destination User (The existing User Pool native user).
  5. response back to the client application that link is done.

C. Client application receives the response.

D. Save the current user's id token. Then logout the current user.

E. Use the User Pool custom auth flow to sign-in the user. This custom auth flow shall use the external IdP's Id token got from step a as the custom auth flow's challenge. More precisely, it will make a new passwordless login with the existing user pool native username and the token of federated external User. Once the custom auth flow is done successfully, it will return the native user's token.

  • The implementation method of the custom auth flow in step E. would be similar to the blog content [2]. The difference is, here it shall use federated user's token instead of the email OTP code.

  • The proposal of step E is to avoid using the External Federated User token/Session while the External User has been deleted in step B3. As the adminLinkProviderForUser API is called for the first time user sign-in, the following External IdP sign-in will return the linked Native User's token.

Scenario B: A Federated user with an email address already exists in the User Pool. And the user is using the same email address sign-up to the userpool. Then a new native user created. If the hosted UI is used for user sign-up, it will also landed to the callback url endpoint after sign-up along with the authorization code or tokens.

Your application server or script on the callback url shall use the following process -

a. fetch the tokens from Cognito OAuth2 token endpoint (code grant flow) or from the callback URL (implicit grant) Then do the following actions in backend, for example APIGateway + lambda. The backend endpoint should be protected by the User pool as the authorizor and inside the lambda to fetch the info from the token accordingly to perform the following operations.

b. search for the existing External_provider user in the userpool by the native user's email. Store the External_provider user's providerName and userid.

c. delete the External_provider user from the userpool.

d. call adminLinkProviderForUser API with Source User (External IdP userid and IdP name got from step b.) and Destination User (The User Pool native user).


Resources :

[1] AdminLinkProviderForUser - https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminLinkProviderForUser.html

[2] Blogpost - https://aws.amazon.com/blogs/mobile/implementing-passwordless-email-authentication-with-amazon-cognito/

SUPPORT ENGINEER
answered 2 months ago
  • Thanks, Yash. The community seems to have complained about this since 2017. 5 years have passed. Really disappointed with the Cognito team deliverables and the service itself. Thinking about switching providers.

0

Workaround - stay away from Cognito.

answered 24 days ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions