- Newest
- Most votes
- Most comments
I have exactly the same behavior for custom OIDC provider: original Cognito user gets identity added to the list of identities, but along that one more external user is added alongside to users. It's identity differs only by date created and primary set to true. I am also able to get access and id token, but they are for separate identity (the "second" user).
Interestingly enough, with second provider - Google- behavior is as expected: after the same pre-sign up lambda executes AdminLinkProviderForUser command, original Cognito user gets all attributes updated, as well as list of identities expanded. When id and access tokens are examined - it is still original Cognito user.
This article puts some light on it https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminLinkProviderForUser.html
I have tried linking custom OIDC provider (LinkedIn) with id, user_id, sub instead of Custom_Subject; with full (linkedin_xyz), and partial (xyz) username - but no luck. It does not get better than behavior above.
Some piece of information is missing on how to set up linking for custom OIDC like LinkedIn.
Any advice would be appreciated. Max.
Few things to remember
- When user authenticates with federated linked account, the user will be authenticated as native cognito user and generated tokens will hold identity of native account.
- Any mapped attributes from federated IdP to native user and will be overwritten with each login.
- Linking external account (source) to Destination account should be two step a. Delete the external account source account in user pool. b. Creating a link to native account using AdminLinkProviderForUser
I posted the original question and the official answer didn't solve it for me. But I did some trial and error and figured it out by deducing based on the behaviors I was seeing from Cognito. What fixed it for me, though, may not solve your problem, but here goes.
Through debugging I found that the generated identifiers, which are composed from, among other info, the external username, were getting lowercased before being sent to the pre-signup trigger and, through token inspection, I saw that the corresponding usernames from the source tokens were mixed case (in my situation). Based on those observations, I tried changing my case-insensitive userpool to case-sensitive and it worked. I'll explain why.
What appears to be happening is that, during login, Cognito is always checking for a match in the userpool based on the exact string from the external token. But, for case-insensitive userpools, as I said, on first login, it is always transforming it to lowercase before sending it to the pre-sign trigger. So, when the source idp uses mixed-case or uppercase, it never finds a match. To be clearer, I think the sequence Cognito follows is like this for login: 1. inspect the token and check the userpool for an exact (case-sensitive) match, 2. if no exact match is found, generate a new identifier (with a lowercased value) and send it to the pre-sign function for linking. Think through that for a second and I think you will see the problem.
The reason it always works with Google turned out to be because Google always uses lowercase for the values. What I did to work around it was to make the userpools case-sensitive, so that the pre-sign trigger would receive values with the correct case. This, of course, meant that I had to abstract access to cognito for the application so that users don't get created with the wrong case. One other note, you cannot change the case-sensitivity for a userpool once you create it, so if you have a userpool that is already in use, this solution would require a user migration.
I think the right solution is for Cognito to to either stop lowercasing the identifiers it generates, even on case-insensitive userpools, when it calls the triggers or for the login for case-insensitive userpools to allow any case when detecting a match. But, I didn't have the time to wait around for AWS to fix that. Good luck.
Found the issue. When provider has letters in the userId, cognito transforms their case to lower one within userId. That's the issue as sub is case-sensitive.
Solution is to add one more mapping: custom:sub. Go to sign up experience, and then add "sub" into custom mapping. It will be added as custom:sub Then go to sign in experience > LinedIn and map sub into custom:sub there. This will allow for pre-sign up function to be as follows for linkedin provider to work:
console.log(`Linking ${userName} (ID: ${userId}).`);
console.log(`Linking userAttributes (ID: ${JSON.stringify(event)}).`);
const finalUserId = providerName === 'linkedin' ? event.request.userAttributes["custom:sub"]: userId;
const command = new AdminLinkProviderForUserCommand ({
// Existing user in the user pool to be linked to the external identity provider user account.
DestinationUser: {
ProviderAttributeValue: existingUsername,
ProviderName: 'Cognito'
},
// An external identity provider account for a user who does not currently exist yet in the user pool.
SourceUser: {
ProviderAttributeName: 'Cognito_Subject',
ProviderAttributeValue: finalUserId,
ProviderName: providerName // Facebook, Google, Login with Amazon, Sign in with Apple
},
UserPoolId: userPoolId
});
await cognito.send(command);
Here is event data example :
{
"version": "1",
"region": "us-east-1",
"userPoolId": "us-east-1_d3sdfdsfD",
"userName": "linkedin_0labhk9l5z",
"callerContext": {
"awsSdkVersion": "aws-sdk-unknown-unknown",
"clientId": "dskjflkdsjflkdsflkdshkfdshlfk"
},
"triggerSource": "PreSignUp_ExternalProvider",
"request": {
"userAttributes": {
"email_verified": "false",
"cognito:email_alias": "",
"cognito:phone_number_alias": "",
"custom:sub": "0lAbhK9l5z",
"given_name": "Tom",
"family_name": "Jones",
"email": "tom@example.com"
},
"validationData": {}
},
"response": {
"autoConfirmUser": false,
"autoVerifyEmail": false,
"autoVerifyPhone": false
}
}
What I read online is - facebook and amazon have case-sensitive letters in sub as well. In contrast Google has numbers, and hence does not need this hack.
Hope this helps.
Max
Relevant content
- asked 2 years ago
- asked a year ago
- asked 5 months ago
- AWS OFFICIALUpdated 5 months ago
- AWS OFFICIALUpdated a year ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated 3 years ago
My response to you was too long to be a reply to your comment, so you will find it below. Sending this just to be sure you get a notification...since my solution just might work for you.