Federated User With authorization code fail first time retrieving the token

1

Hello Im having a issue related to the federated user.

Context:

  • We are connecting Azure b2c as and idp
  • We have a lambda trigger in post_confirmation to link the user of azure with the user of cognito, and also we are deleting the user the record of the azure user to have only one record.
  • We get an authorization code when the flow succeed.
  • We change the code using the oauth2/token endpoint (here is were we are having an issue)

Issue:

When we get the code for the first time (azure user is linked to cognito user in the process of the post_confirmation lambda trigger), and then use the endpoint oauth2/token we are getting a 400, and if we execute the flow again the endpoint works and we get the tokens.

Questions:

¿Why fails the first time to get the tokens? ¿How can I have a more descriptive error?

curl example: curl --location 'https://mydomain.amazoncognito.com/oauth2/token'
--header 'Content-Type: application/x-www-form-urlencoded'
--data-urlencode 'grant_type=authorization_code'
--data-urlencode 'client_id=clientId_Cognito_Aplication'
--data-urlencode 'scope=openid offline_access clientId_azure '
--data-urlencode 'code=d3852b2a-87ea-4c72-a2dc-f69254939c0a' \ --data-urlencode 'redirect_uri=https://myRedirectUri/callback'

1 Answer
1

Hello,

From the case description, I understand that you are connecting Azure B2C as an IDP to your Cognito user pool. You have a Post Confirmation Lambda Trigger[1] in the user pool which links IDP users to your Cognito user pool users and deletes the IDP user. When you are hitting the token endpoint using the code obtained during the first login of IdP user, you are getting 400 error. But in the second attempt (with a new code) you are able to get the tokens.

I replicated this scenario at my end and was able to reproduce the issue. Please allow me to explain what is causing the issue:

During the first login of the IdP user, the Post Confirmation lambda would get triggered which would link the users and would delete the IdP user. As the IdP user gets deleted by the Lambda function during the first login so, the generated code is not associated with any existing user. Hence, if you try to hit the token endpoint to get the tokens using that code then you would get an error as the user is already deleted.

But in the second attempt, as the users (IDP user and native user) are already linked so, the code you receive now is for an existing user. Hence, when you hit the token endpoint you get the required tokens.

In order to avoid this scenario, you can use the PreSignup Lambda Trigger[2] instead of Post Confirmation Lambda Trigger. Shortly before Amazon Cognito signs up a new user, it activates the PreSignup AWS Lambda function. That is, the Pre Signup Lambda gets triggered even before the user is created in the pool so, there is no need to delete the IdP user using the Lambda function. You can just link IdP user to Cognito native user in the Pre Signup Lambda function. In this way, the code generated during the first login would be for an existing linked user. Hence, you would be able to get the token using the code obtained during first sign-in as well. I tried implementing this workaround at my end and was able to get the tokens for the IdP user using the code for each login attempt.

Below is a sample code that I used in the Pre Signup Lambda function at my end:

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

response = client.admin_link_provider_for_user(
UserPoolId='<your user pool id>',
DestinationUser={
    'ProviderName': 'Cognito',
    'ProviderAttributeValue': '<username>'
},
SourceUser={
    'ProviderName': '<IDP provider name>',
    'ProviderAttributeName': 'Cognito_Subject',
    'ProviderAttributeValue': '<user-id of idp>'
}
)

return response

[1]. https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-post-confirmation.html

[2]. https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-pre-sign-up.html

AWS
answered 8 months 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