- Newest
- Most votes
- Most comments
Found one way. Link the cognito user to external provider using https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminLinkProviderForUser.html
Make sure to map attributes for external provider - email and username for the first time login, connect a pre signup trigger where you do the linking using API_AdminLinkProviderForUser, this will create a identities attribute that will have the linking. for subsequent logins it will direct go for login code and not signup.
to unlink the https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminDisableProviderForUser.html
some useful links https://stackoverflow.com/questions/66447439/prevent-users-from-signing-up-on-their-own-with-federated-identity-providers-fi
answered 2 years ago
Greeting
Hi Minaxi,
Thank you for sharing your experience and the challenges you're facing with SSO integration using SAML and Cognito. It's clear that you're encountering an issue where SSO attempts are creating duplicate user entries instead of recognizing existing ones. Let's work through this together to resolve the problem so that your users can log in seamlessly with their existing credentials. 😊
Clarifying the Issue
From what you've described, your Cognito user pool already contains users with valid email addresses. However, when a user logs in through SSO (via SAML and Azure AD), Cognito creates a new user entry instead of matching the existing user. This happens because Cognito treats SAML logins as external identities unless configured to map them to existing user pool attributes. As a result, the system creates duplicate user entries with an EXTERNAL_PROVIDER confirmation status.
This can be frustrating, especially when you need consistent user management and expect SSO logins to link to existing user accounts based on attributes like email. By adjusting the attribute mapping and validating the SAML assertions, we can ensure Cognito matches these users correctly, avoiding duplication and providing a seamless user experience.
Why This Matters
This issue is more than an inconvenience. Duplicate user entries can fragment data and disrupt workflows in your application, complicating analytics and user management. Resolving this ensures a consistent and professional user experience while maintaining operational efficiency.
Additionally, fixing this issue has broader implications for security. Properly validating SAML attributes reduces the risk of spoofing or unauthorized access. It also simplifies scalability as your user base grows, ensuring seamless user management without needing extensive manual intervention.
Key Terms
- Cognito User Pool: A user directory service in AWS that manages authentication and authorization.
- SAML: Security Assertion Markup Language, used for single sign-on between identity providers and service providers.
- IdP (Identity Provider): Azure AD, in this case, which authenticates users and sends their attributes to AWS.
- Attribute Mapping: A Cognito feature to map attributes (like email) from the IdP to user pool attributes.
- External Provider: Status assigned to users created by external SAML or OIDC identity providers.
The Solution (Our Recipe)
Steps at a Glance:
- Enable attribute mapping in your Cognito user pool.
- Configure the SAML assertion from Azure AD to include email and necessary attributes.
- Enable email matching in Cognito for user identification.
- Test and verify the integration.
Step-by-Step Guide:
- Enable Attribute Mapping in Cognito
- Log in to the AWS Management Console and navigate to your Cognito user pool.
- Go to the "Federation" section and click on "Identity providers".
- Select your SAML provider (Azure AD in this case).
- Map the
emailattribute from the SAML assertion to theemailattribute in your user pool.
Example mapping in JSON:{ "Attributes": [ { "Name": "email", "MappedAttribute": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" } ] }
- Configure SAML Assertion in Azure AD
- In Azure AD, ensure your SAML setup includes the
emailattribute in its assertion. - Go to Azure Active Directory > Enterprise Applications > Select your application.
- Under Single Sign-On, edit the SAML configuration to pass the
emailclaim:<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"> <Value>user_at_domain.com</Value> </Attribute>
- In Azure AD, ensure your SAML setup includes the
- Enable Email Matching in Cognito
- In the Cognito user pool, enable matching by email for SSO logins.
- Use a Lambda trigger for Pre Sign-Up to check if a user with the same email already exists:
import boto3 def lambda_handler(event, context): client = boto3.client('cognito-idp') # Extract email from the SAML assertion passed in the event email = event['request']['userAttributes']['email'] # Search for an existing Cognito user with the same email response = client.list_users( UserPoolId='your_user_pool_id', # Replace with your user pool ID Filter=f'email = "{email}"' ) # If a user is found, automatically confirm and verify the new SAML login if response['Users']: event['response']['autoConfirmUser'] = True event['response']['autoVerifyEmail'] = True return event
- Test and Verify the Integration
- Have an existing user log in through SSO.
- Verify that the login does not create a duplicate user and that the existing user receives the correct access tokens.
- Use AWS CloudTrail to monitor the SSO login process and verify SAML attributes received by Cognito.
- Check SAML logs in Azure AD for attribute configuration issues or mismatches.
- After implementing the Lambda trigger, confirm its behavior by checking CloudWatch logs for the Lambda execution. Ensure the logs reflect:
- A successful match to an existing user.
- Automatic confirmation and verification of the user.
Closing Thoughts
By implementing attribute mapping, ensuring proper SAML assertions, and using a Lambda trigger to verify existing users, you can prevent duplicate entries and streamline the login process. This approach maintains your user pool's integrity while enhancing the user experience.
For further reading and detailed steps, you can check the following documentation:
- AWS Cognito User Pool Attribute Mapping
- AWS Pre Sign-Up Lambda Trigger
- Azure AD SAML Claims Configuration
Farewell
I hope this enhanced explanation helps you tackle the issue, Minaxi! If you have further questions or run into any issues while testing, feel free to ask. Good luck with your setup! 🚀😊
Cheers,
Aaron 😊
answered 2 years ago
Hi Minaxi,
Thanks for the follow-up and for clarifying the issue. You're absolutely correct—the sub attribute in Cognito is a unique, immutable identifier, which can lead to the creation of new users even when the email attribute matches. To address this, you’ll need to ensure proper user linking and attribute mapping to prevent duplication.
Resolving the Issue
- Link Users with
AdminLinkProviderForUserAPI:
This API allows you to connect a Cognito user with an external identity provider, ensuring the samesubidentifier is used. For first-time logins, you can link the SSO user with the existing Cognito user programmatically.
- Map Attributes Correctly:
Make sure all critical attributes, includingemailandusername, are mapped between the SAML response and Cognito user pool. This reduces potential mismatches. Check your SAML configuration in Azure AD to ensure attributes are formatted correctly.
-
Use Pre Sign-Up Trigger for Dynamic Linking:
Implement a Lambda function in the Pre Sign-Up trigger to automatically link users during the sign-up process. Here’s a sample code snippet:import boto3 def lambda_handler(event, context): client = boto3.client('cognito-idp') email = event['request']['userAttributes']['email'] # Search for an existing user by email response = client.list_users( UserPoolId='your_user_pool_id', # Replace with your user pool ID Filter=f'email = "{email}"' ) if response['Users']: existing_user = response['Users'][0] client.admin_link_provider_for_user( UserPoolId='your_user_pool_id', DestinationUser={ 'ProviderName': 'Cognito', 'ProviderAttributeName': 'sub', 'ProviderAttributeValue': existing_user['Attributes'][0]['Value'], }, SourceUser={ 'ProviderName': 'SAML', 'ProviderAttributeName': 'Cognito_Sub', 'ProviderAttributeValue': event['request']['userAttributes']['sub'], } ) event['response']['autoConfirmUser'] = True event['response']['autoVerifyEmail'] = True return event
- Test and Validate:
Test the entire flow to ensure no duplicate users are created and that existing users can log in seamlessly with their SSO credentials. Check CloudWatch logs to confirm that the Lambda trigger works as intended.
Why This Matters
The sub attribute is fundamental for uniquely identifying users in Cognito. By linking users and ensuring proper attribute mapping, you maintain the integrity of your user pool, simplify user management, and improve the overall login experience.
Let me know if this resolves your issue or if further clarification is needed. You’re making excellent progress on this! 🚀😊
Cheers,
Aaron 😊
answered 2 years ago

Hi Aaron, thanks for responding. I have mapped the email field but cognito is still creating new user I think based on sub user attribute. email and sub are required attributes, even though email is same and mapped its still creating new user with different sub field. sub Index and search your users based on the sub attribute. The sub attribute is a unique user identifier within each user pool. Users can change attributes like phone_number and email. The sub attribute has a fixed value. For more information about finding users, see Managing and searching for user accounts. https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html