aws / aws-sdk-js

AWS SDK for JavaScript in the browser and Node.js
https://aws.amazon.com/developer/language/javascript/
Apache License 2.0
7.57k stars 1.55k forks source link

Error on InitiateAuthCommand with good cred >> NotAuthorizedException: Incorrect username or password >> But cr #4642

Open smichel-amiltone opened 3 weeks ago

smichel-amiltone commented 3 weeks ago

Describe the bug

Login fail with correct credential who are set in cognito user

Expected Behavior

Should succes with TOTO123456+ Azlsd45$q#s and have AuthenticationResult in result

If i set TOTO123456 + Azlsd45$ this is working fine...

Current Behavior

Result -> NotAuthorizedException: Incorrect username or password.

Reproduction Steps

Package

"@aws-sdk/client-cognito-identity-provider": "^3.245.0",

Step one set a password with spécial like $ or # in the middle on some cognito user

aws cognito-idp admin-set-user-password \
--user-pool-id XXXXXXXXX \
--username TOTO123456\
--password Azlsd45$q#s \
--permanent \
--profil XXXXXXX  \
--region eu-central-1

JS LAMBDA SAMPLE

import { CognitoIdentityProviderClient, InitiateAuthCommand } from '@aws-sdk/client-cognito-identity-provider';
import { APIGatewayEvent, Context, APIGatewayProxyResult, Handler } from 'aws-lambda';
import { COGNITO_APP_CLIENT_ID } from 'src/shared/process-env-var';

export const login: Handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => {
  try {

    const eventBody = parseBody(event);
    DEBUG && console.debug('>> body >>', eventBody);
    const { email: USERNAME, password: PASSWORD } = eventBody;

    const client = new CognitoIdentityProviderClient({});
    const AuthParameters = {
      USERNAME,
      PASSWORD,
    };
    const input = {
      ClientId: COGNITO_APP_CLIENT_ID,
      AuthFlow: 'USER_PASSWORD_AUTH',
      AuthParameters,
    };
    const command = new InitiateAuthCommand(input);

    const result = await client.send(command);

    return handleResponse({ result });
  } catch (error) {
    return handleError(error, context);
  }
};

LOG -> DEBUG >> body >> { email: 'TOTO123456', password: 'Azlsd45$q#s' }

Possible Solution

No response

Additional Information/Context

No response

SDK version used

"@aws-sdk/client-cognito-identity-provider": "^3.245.0"

Environment details (OS name and version, etc.)

AWS Serverless lambda

aBurmeseDev commented 3 weeks ago

Hi @smichel-amiltone - thanks for reaching out.

This error is thrown when a user isn't authorized according to service API docs. Can you verify that your user is authorized and credentials are correct? You can also check by running InitiateAuth command:

aws cognito-idp initiate-auth --client-id 12ab34cd56ef78gh91ij23kl45md --auth-flow USER_PASSWORD_AUTH --auth-parameters USERNAME="myuser",PASSWORD="password"
smichel-amiltone commented 3 weeks ago

Hi @smichel-amiltone - thanks for reaching out.

This error is thrown when a user isn't authorized according to service API docs. Can you verify that your user is authorized and credentials are correct? You can also check by running InitiateAuth command:

aws cognito-idp initiate-auth --client-id 12ab34cd56ef78gh91ij23kl45md --auth-flow USER_PASSWORD_AUTH --auth-parameters USERNAME="myuser",PASSWORD="password"

Allowed Authentication flows in APP Client

ALLOW_ADMIN_USER_PASSWORD_AUTH ALLOW_CUSTOM_AUTH ALLOW_REFRESH_TOKEN_AUTH ALLOW_USER_PASSWORD_AUTH ALLOW_USER_SRP_AUTH

The CMD aws cognito-idp admin-set-user-password accept both password

But on the same user the JS InitiateAuthCommand command work when i have set Azlsd45$ in password and not with Azlsd45$q#s.

Resume on the same working user !

User required attributes : User name -> CL00000005 email -> smichel@amiltone.com (Verified)


Set password Azlsd45$

aws cognito-idp admin-set-user-password \
--user-pool-id XXXXXXXXX \
--username CL00000005 \
--password Azlsd45$ \
--permanent \
--profil XXXXXXX  \
--region eu-central-1

Run Lambda code

LOG -> DEBUG >> body >> { email: 'smichel@amiltone.com', password: 'Azlsd45$' } Result InitiateAuthCommand -> Succes and result have authenticationResult with the token etc...


Set password Azlsd45$q#s

aws cognito-idp admin-set-user-password \
--user-pool-id XXXXXXXXX \
--username CL00000005 \
--password Azlsd45$q#s \
--permanent \
--profil XXXXXXX  \
--region eu-central-1

Run Lambda code

LOG -> DEBUG >> body >> { email: 'smichel@amiltone.com', password: 'Azlsd45$q#s' } Result InitiateAuthCommand -> NotAuthorizedException: Incorrect username or password.

The password Azlsd45$q#s set with the CMD isn't working, but if we set it with new AmazonCognitoIdentity.CognitoUser.changePassword it's ok !

aBurmeseDev commented 3 weeks ago

Thanks for the response, I'm going to reach out to service team to get their insight as this's related to service API rather than SDK. Will update once I hear back. (P133737497)

darwinagyei commented 2 weeks ago

Hi @aBurmeseDev - This bug is impacting my app as well. Any updates from the service team ?

aBurmeseDev commented 1 week ago

Service team mentioned that

In terminal, alphanumeric characters following a dollar sign (e.g. $abc123) are treated as a variable name in the terminal session. Terminal will try to resolve this to a value, even if it is in the middle of a string, like the customer's Azlsd45$q#s. Terminal is trying to substitute the $q in the middle of the string with the value that is assigned to q.

They suspect that this might be the case:

  1. Customer alls admin-set-user-password on CLI with a password of Azlsd45$q#s
  2. Terminal parses the command and finds $q and assumes this is a variable
  3. Terminal replaces $q with the value it was assigned in the terminal session 3a. This is likely to be nothing. $q would be replaced with an empty string. The resulting password is then Azlsd45#s
  4. Terminal sends the malformed password with the replaced "variable" to the AWS CLI
  5. Cognito updates the user with the malformed password
  6. Attempts to authenticate with any SDK and fails.

Solution is to wrap the password in the admin-set-user-password call in CLI with single quotes, like 'Azlsd45$q#s'. This ensures that the $q does not get replaced by Terminal.

Let me know if that helps!

smichel-amiltone commented 6 days ago

Service team mentioned that

In terminal, alphanumeric characters following a dollar sign (e.g. $abc123) are treated as a variable name in the terminal session. Terminal will try to resolve this to a value, even if it is in the middle of a string, like the customer's Azlsd45$q#s. Terminal is trying to substitute the $q in the middle of the string with the value that is assigned to q.

They suspect that this might be the case:

1. Customer alls `admin-set-user-password` on CLI with a password of `Azlsd45$q#s`

2. Terminal parses the command and finds $q and assumes this is a variable

3. Terminal replaces `$q` with the value it was assigned in the terminal session
   3a. This is likely to be nothing. `$q` would be replaced with an empty string. The resulting password is then `Azlsd45#s`

4. Terminal sends the malformed password with the replaced "variable" to the AWS CLI

5. Cognito updates the user with the malformed password

6. Attempts to authenticate with any SDK and fails.

Solution is to wrap the password in the admin-set-user-password call in CLI with single quotes, like 'Azlsd45$q#s'. This ensures that the $q does not get replaced by Terminal.

Let me know if that helps!

Thx for the answer, good to know

darwinagyei commented 6 days ago

I will implement the solution into my app. Thanks for the update!