"Forgot username" flow for AWS Cognito? - amazon-cognito

I'm using ASW Cognito for authenticating users. Cognito has a well-documented flow to handle users who have forgotten their passwords.
How do I handle users who have forgotten their usernames? Is there a built-in flow that lets the user enter their email or phone number, and then receive an email or text with their associated username? I found the ListUser API, which returns all the users in a userpool. I could write a Lambda function that filters through all my users, looking for a match on email or phone number. But this seems like overkill.

Unfortunately, there is no default out of the box workflow of "Forgot Username".
I am implementing similar workflow. We ask user for their registered phone number/email, and we retrieve username based on that number and send it to email/phone according to configuration. If user is configured to use email and phone both, we send SMS to phone if user forget username (which is email id they used during sign up).
One major drawback of this approach is that, we need to provide ListUsers API call access to anonymous user which is a potential security issue but can't seem to find any other way by which we inform user about their login details.

For those, who are looking for the solution, don't give the anonymous user access to ListUser API as suggested in the accepted answer.
There are two ways to implement 'Forgot username flow'.
Enable email as an alias for your Cognito User Pool:
Calling this API causes a message to be sent to the end user with a
confirmation code that is required to change the user's password. For
the Username parameter, you can use the username or user alias. The
method used to send the confirmation code is sent according to the
specified AccountRecoverySetting.
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html
The user will be able to reset the password with their email and code delivered to provided email address. If you still want to remind the username, you can use Lambda trigger to generate the password reset email with both username and verification code.
Use the backend (web server or lambda) which will receive the email address as an input to the 'Forgot username flow'. The backend will have permissions to invoke List Users API (https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUsers.html) and will perform user lookup using the email. You now can go into Forgot Password flow using the retrieved username. Lambda trigger will be used to generate password reset email with username and verification code.
You can protect this API from abuse using WAF and/or captcha.

Related

Passwordless Authentication with Cognito - How to determine if a user signed up with email or phone number

We have implemented the Custom Auth Triggers as described link here. We have the user pool set up to let users log in with either phone number or email.
The provided case is - the user has email & phone both verified in their Cognito account
The problem I am having is determining what medium (email or phone number) the user signed in
When observing the event passed into the define / create/verify auth triggers, it seems like doesn't pass through what the username was used to initiate the authentication flow.. only the user attributes which in my case there could be both email or phone. I need to know which one it is so I know if I need to send the code through SMS or Email.
I also read about ClientMetadata this key we can pass from in InitiateAuthCommandInput but it will provide a client metadata key only below these triggers
Pre signup
Pre-authentication
User migration
but it will not provide ClientMetadata in these triggers
Post authentication
Custom message
Pre token generation
Create auth challenge
Define auth challenge
Verify auth challenge
After googling it too much, I found an article which had a tricky solution:
here is the link
I am not able to implement the provided solution.
I found a similar question in stack overflow too Link but there is also no answer, Can anyone please help me with this.
This is a workaround by adding a custom attribute during passwordless login
Actually, the authenticationUser function needs to identify whether the user is adding email or phone during login
Step 1: during login process, before calling initiateAuthCommand, First set a custom attribute in Cognito user object - logged_in_by - email or phone
Step 2: once you add a key after that InitiateAuthCommand will be started and call the triggers
Step 3:
When createAuthChallenge runs at the time we will have userAttributes.logged_in_by.
If this attribute contains email this indicates that the user is trying to login with the email and we need to send OTP over email.
If this attribute contains phone this indicates that the user is trying to log in with the phone and we need to send OTP over the phone number.

How to require a verification code before changing attribute in AWS cognito

We are using amazon-cognito-identity-js to manage users in a javascript application.
Currently, once authenticated, a user can change their email address or phone number with cognitoUser.updateAttributes(). If that attribute is marked as verified, it will then be unverified, and we can trigger verification through cognitoUser.getAttributeVerificationCode() and it will send a confirmation code to the users phone.
Ideally, we would like to require a code BEFORE changing the attribute, much like the change password flow works. Is such an approach possible?

Login with phone number feature

Currently I am working on feature login with phone number, user will enter their phone number and server will send sms which contain OTP.
I have researched many days for the solution to integrate with Keycloak but still stuck on it. I saw that we need to use authenticator SPI, extend keycloak and implement code which we want.
I also have thought about using other third party to handle sms and otp stuff ( like Firebase) and then will use firebase token to exchange keycloak token but firebase is not supported provider in Keycloak therefore can't do this flow
I just want to ask is there any other ways to do this feature without extend Keycloak? or simply can we get keycloak token via API but without password
I can imagine small solutions around keycloak, which together can get what you want. Will try to explain :)
Imagine phone number is user login in keycloak.
Imagine password is system generated, like encoded phone number + salt; basically hash algorithm know what the password is, user don't.
You use third party library, which verify user mobile number and text message user enters, and it works.
You create system-user in keycloak, keep password encoded in application.properties, assign him some admin roles like create user, query user, something else you need to manage users.
And now, workflow is:
User enter mobile number 123, sms getting send
User verify sms,
you know user number 123, you generate password
hash1(hash2(123+salt)) (see point 2)
Using system-user you login to keycloak, get accessToken for system-user
using accessToken check if user exist, if not, create user 123 with password hash(..), assign default roles, groups
logout from system-user
login with user 123 and password hash(..), load user accessToken, build User Profile, put in to SecurityContextHolder.getContext()
If you make all small bits working, should work all together.
or just ignore me if I am wrong! Good luck !

Create Auth0 user

I'm using Management API V2 to create users and I'm setting their password in the creation process.
After that they're receiving an invitation email to confirm their email address because I'm setting the parameter "verify_email" to true.
What I need to do is:
Create User
Send the user an invitation email so they can confirm their email
address.
Giving them the option to set their own password, instead of me
setting it in the creation process "step 1"
I looked up in the community before asking, and I found that I can trigger password reset flow upon the creation, is there any different way to do it? because this doesn't look like the correct way to do it, there should be a way to do so.
Thanks
Triggering reset password email is the right approach. You can use authentication API to send the reset password email.
https://auth0.com/docs/api/authentication#change-password
More options are described here: https://auth0.com/docs/connections/database/password-change

Can/should IdentityServer4 be used to create a token for user-email verification

I have IdentityServer4 setup for API authentication although I have a use case where I want to verify that a guest (user) is essentially a valid user. A valid user in my case is anyone with a valid email address, so I want to do the following:
send the user an email with a verification token (preferably something which is a mash up of their email address, some salt and an expiry
the user can then enter this token into my app and they are "allowed" to go ahead
I was wondering if IdentityServer4 can/should be used to achieve the above?
Their tools show that you can generate a token although I am very new to this topic so was hoping for some guidance.
No, the tokens Identity Server deals with are access_tokens which are to do with claims-based authentication.
The tokens you need to use for email verification are commonly referred to as User Tokens, or one-time passwords (OTP). You can find a wealth of information on how to generate/consume these using those search terms but if you use the aspnet identity classes such as the UserManager you will find it has some in-built read to use. Or you can register your own UserTokenProvider with the UserManager.
In general you'd do something like this:
Use your UserTokenProvider to get a token (otp) for a specific user. The UserManager will use the security hash of that user and your own 'reason' (e.g. "EmailVerification") to generate the short OTP.
You could then wrap that OTP into an object that includes the email address, a userid maybe, and whatever you like. Safe Base64 encode it (there is a helper function within Identity Server that has this in fact, making sure it doesn't have the superfluous _ at the end which will mess with HTML links), put it in an email to the user
User clicks your link which takes them to your 'verify password' controller, with your mashed up token as payload. You decode it, work out which user it was for, get UserManager to verify the OTP part is still valid.
Job done.
If you want them to enter the OTP into your app directly, while logged in, then you could just skip the whole mash-up part of emailing a link, and email the short OTP directly.