How to disable AWS Cognito User Pool account created via Identity Provider? - amazon-cognito

Any Cognito User Pool gurus out there? I've been using Cognito for a while now but this one has me a bit stumped.
We allow users to sign up and sign in using social accounts like Facebook which are set up as Identity Providers in the User Pool.
Users need to complete a custom registration form before they can use the main app - we don't use the hosted UI for login or signup
One step of the custom registration process allows the user to indicate which social provider then want to use
This allows us to pull back the users email, first and last names from the social provider which is great - we use a cognito client and callback to do this currently
But in doing so, this provisions a user within the Userpool before the registration process is complete - in fact this makes sense- in order for Cognito to provide us the user info it needs to have called into the social providers /userinfo endpoint to populate the user data
So, the issue we now have is that whilst the user is half way through the registration process I have a confirmed user account - eg. before the user has completed the registration process
This is an issue because a user could sign into the the app using their social login without ever have completed the registration process
So as I see it I have two options:
PostConfirmation Lambda trigger which uses the cognito-idp SDK to disable the user just after it was confirmed
Don't use Cognito to obtain the user info like firstname, lastname, email, picture etc - however this would require us to write a solution for every current and future social provider which isn't something I'm keen on
Am I missing something obvious?
Thanks in advance!

I would say PostConfirmation Lambda trigger is a good approach - however instead use adminDisableProviderForUser to disable the user from signing in with the specified external (SAML or social) identity provider
adminDisableProviderForUser
You can later call adminLinkProviderForUser to link the existing user account in the user pool to the external identity provider.
adminLinkProviderForUser
An alternative solution is to prevent the user from signing in if they have not fully completed the registration process via a Pre Authentication Lambda Trigger checking for a unique identifier with respect to your completed registration process

The simplest solution in the end for us was a Pre Token Generation Trigger in Cognito like this:
exports.handler = async (event) => {
if(event.triggerSource==="TokenGeneration_HostedAuth") {
//check db/api etc to see if we have a valid registration stored for user
if(!hasCompletedRegistration) {
//throw auth exception which we can catch on the frontend to inform user
throw new Error("REGISTRATION_NOT_COMPLETE")
}
}
return event
};
For username/password sign ins the TriggerSource will be TokenGeneration_Authentication
For federated/social sign ins the TriggerSource will be TokenGeneration_HostedAuth

Related

same gmail account has the same user ID in Auth0 even after deletion

I am implementing a functionality of removing a user account (the user will have the possibility to delete its account).
I am using Auth0 as authentication provider. If I log in the app using a Gmail account, Auth0 will create the account with user ID value of XXXXX. After I delete the user (through API or from users management section), if I try to access the app again with the same Gmail account then the user ID will still be XXXXX.
This is a problem in my case because I need to anonynimize the data and the other details should never be visible.
I can solve the problem by changing the the ID in my database but for the moment I would like to keep it.
Is this the normal behavior of auth0?
Good morning tzortzik! I work with the Auth0 Community team and after confirming with one of our senior engineer, some connections the user ID is built based on details originating from the external IDP (Google in this case). That being said, if you remove a user in Auth0 for this instance, the very next time the user logs in/signs up they will receive the same ID that originated from the external IDP. I hope this helps clear some things up. Thanks!

Merge two accounts in Cognito created with same email (email and social)

In my app, I have Amazon Cognito Hosted UI configured to handle Authentication by email and social (facebook and google).
The problem:
When a user create an account by email (ex: gmail) and later sign up by social (ex: same gmail), I have two accounts created in Cognito.
Question:
How merge these two accounts created with the same email?
Thanks for your help.
Edit
For those interested, I created an issue on aws amplify:
https://github.com/aws-amplify/amplify-js/issues/2754
You cannot link them however you can decide the behavior by setting the forceAliasCreation parameter in ConfirmSignUp API. If you set it as false it will throw an error if a user has already registered with same email/phone number. If you set it as true, the old account will be deactivated and the new one will be the only one he can use. You can read more about this behavior here

New sign-ups to Congito User pool default to disabled

I am using Cognito User pools and the hosted Cognito UI. I want new users to be disabled when they first sign-up.
I am trying to use a Cognito Trigger to disable the user.
The "Pre sign-up" trigger is to soon, the user has not been created yet. I have successfully used the "Post confirmation" to disable the user, however this is causing a side effect. After the user enters the confirmation code which is emailed to them, they see this message in the hosted UI "User is disabled".
Does anyone have a suggested solution on how to make the new users disabled by default?
We had a similar Business Requirement. For us we made use of a User Pool Group. This allowed the sign up and validation process to work as normal. We had the Post Confirmation trigger send our product team an email with details about the new confirmed user. We had a simple UI for the product team to add the group to a user if they should have access.
To Deny/Grant Access to the app: Our app checked the ID Token, once a user successfully authenticated, for the group (the ID Token has a 'cognito:groups' key which contains a list of all the groups the user is in). If the group was not present we displayed a page showing the user a customized access denied message

How to associate data with a user that has been authenticated with Google oauth?

So I am having some trouble figuring out how to implement a sign-in for my app using google oauth. Every example I see shows how to authentication the user, get their permissions and then start using the Google APIs.
I do not care about permission or using Google APIs. All I want to do is have the user sign-in to my app using google oauth instead of having to implement my own authentication system with user and passwords in the database.
After the user authenticates with their google account, then they can change settings associated with their account for my app. What is the flow i need to implement to achieve this?
How would I associated a google user with certain data defined in my own app's database? I have successfully implemented the authentication part but then what would I need to store in my DB to associate them with their actions and data. Would I need to use sessions? and then retrieve their Google+ ID, save it in the database and then use that to identify them in the database for later when they log in again?
any help is appreciated
Once the the server validates the access token, a user account can be created in the database, saving the Google ID along other user details (ID, email, name etc).
If your application also supports normal registration, and an account is already present for that user (matching email), then you can just fill in the (nullable) Google ID column in order to link the account(s).

How to link different authentication providers in azure mobile services

What is the best practice in azure mobile services to use different authentication providers (Facebook, Google, Windows e.t.c.) and understand that this three logins belong to the same user.
Out of the box if a user1 choose to use Facebook for authentication on his mobile phone and add some information to the app, and later he (user1) try to login with Google on his tablet, he will not see his information. Because they are two different users with different tokens. And I want to take some additional information from authentication providers (email) and has my own user table which contains email and other profile info shared for user no matter what provider he uses. How could I achieve it?
P.S. I use .NET as a backend and Windows Phone as a client
There isn't an out-of-the-box solution here. You would probably be best served by using a lookup table which maps a static user ID that you define to different identity provider IDs. Then, everywhere that you take a dependency on the user ID, you would do a lookup to match the current user identity to your static identifier. Your user ID is what gets stored everywhere else in the database.
The important detail here is that a Mobile Services token maps to a single provider identity. If you look at the user ID, it is actually provider:providerID. So we need to obtain two tokens and validate both together in order to associate two IDs.
On the client, you would have to manually prompt the user to link accounts. You would stash the current token in memory during this process, log in with the new provider, then call and API on the backend which does the association.
string existingToken = App.MobileService.CurrentUser.MobileServiceAuthenticationToken;
App.MobileService.Logout(); // allows login with new provider
await App.MobileService.LoginAsync("google");
await App.MobileService.InvokeApiAsync("associateToken", existingToken);
On the server, you need to be able to validate existingToken (the new one being implicitly validated by restricting the API to AuthorizationLevel.User)
Within that API, you can validate the token using:
IServiceTokenHandler handler = this.Request.GetConfiguration().DependencyResolver.GetServiceTokenHandler()
ClaimsPrincipal claimsPrincipal;
bool didValidate = handler.TryValidateLoginToken(existingToken, ConfigurationManager.AppSettings["MS_MasterKey"], claimsPrincipal);
You should probably also look up the user ID in your lookup table to avoid conflicts.
So overall that's a rough sketch of a possible solution. Unfortunately there isn't anything more turnkey.