Hi,
I would like to have a new feature for amazon cognito.
Here is my use case
When a user is created (via an cognito api - AdminCreateUser), he receives a temporary password.
His account is in FORCE_CHANGE_PASSWORD.
When temporary password expires, the user cannot use it. Logically, he asks a new one (I have made a form for users that have forgotten their password)
In this case it fails due to the status of the account (still FORCE_CHANGE_PASSWORD)
I would like to send a RESEND message action but I cannot guess with the sdk when a user is in this situation.
Ideally, when a user is in FORCE_CHANGE_PASSWORD state and try to use an expired temporary password, the api/sdk should return that temporary password is expired in order to be able to have a dedicated error message and a proper way to handle it
@mlecoq this is not possible to do it from the library, is a admin user problem. According to Cognito docs.
The temporary password can only be used until the user account expiration limit that you specified when you created the user pool. To reset the account after that time limit, you must call AdminCreateUser again, specifying "RESEND" for the MessageAction parameter.
This admin user task can be implemented behind a lambda function. There is an open RFC here where can you add this proposal for future releases on amplify-cli
Thanks for your feedback
@elorzafe thanks for your return
Yes I understand that resend can only be done on server side. My concern is about the feedback on client side, there is no way to indicate that temporary password is expired so asking a new one is useless.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This issue has been automatically closed because of inactivity. Please open a new issue if are still encountering problems.
Was anything ever done about this? I also want to know, via the api, when the TemporaryPassword has expired.
Currently the user state is FORCE_CHANGE_PASSWORD
. But that doesn't indicate that the password has expired. Or does it change to RESET_REQUIRED
after it expired?
Also would like to know. Quite an essential thing to tell a new user that the temp password has expired as that is why it is not working.
@elorzafe I got your point. But the issue is, I took information from the user add the time of signup, but now I only have his email ID. How can I send the email again using MessageAction: 'RESEND'
when I only have the email of that user?
Any update on this? We're in the same boat -- it's an issue on the client side...understanding the reason why the user is hitting an unsuccessful login. If we can determine the difference between an expired first-time-login-temp-password and a bad-username-password-combo we can trigger the appropriate workflow.
I realize many people are still having this issue, and it hasn't been resolved yet. I want to share my solution with you.
Basically, I got around the problem by emailing the user a new temporary password, every time the user attempted to login to our application.
I accomplish this by having a multi part login flow.
The most important part of this code, is the backend code that handles the resetting of the temporary password. This is accomplished by calling CognitoISP.adminCreateUser a second time with the same cognitoUser details.
Here is what it looks like:
import AWS from 'aws-sdk';
import crypto from 'crypto';
const USERPOOL_ID = '';
const MESSAGE_ACTION_RESEND = 'RESEND';
const CognitoISP = new AWS.CognitoIdentityServiceProvider();
export async function resetTemporaryPasswordByEmail(email) {
const cognitoUser = await getAccountByEmail(email);
const password = crypto.randomBytes(16).toString('hex'); // 32 hex chars
await CognitoISP.adminCreateUser({
UserPoolId: USERPOOL_ID,
Username: cognitoUser.Username,
MessageAction: MESSAGE_ACTION_RESEND,
TemporaryPassword: password,
}).promise();
return true;
}
async function getAccountByEmail(email) {
let paginationToken;
do {
let params = {
UserPoolId: USERPOOL_ID,
Filter: `email="${email}"`,
Limit: 1,
PaginationToken: paginationToken,
};
let result = await CognitoISP.listUsers(params).promise();
paginationToken = result.PaginationToken;
if (result.Users.length < 1) {
continue;
}
return result.Users[0];
} while (paginationToken !== undefined);
throw new Error('Account not found');
}
The email is sent by a Cognito customMessage handler. The handler simply checks if event.triggerSource === 'CustomMessage_AdminCreateUser' and then build and sends a custom email.
I hope that helps!
Edit: I just realized a bug in getAccountByEmail. It needs to handle a paginationToken.
Edit2: Fixed that.
Most helpful comment
Any update on this? We're in the same boat -- it's an issue on the client side...understanding the reason why the user is hitting an unsuccessful login. If we can determine the difference between an expired first-time-login-temp-password and a bad-username-password-combo we can trigger the appropriate workflow.