aws-amplify / amplify-swift

A declarative library for application development using cloud services.
Apache License 2.0
442 stars 192 forks source link

Amplify password less authentication. Error received as AuthError: Incorrect username or password #2028

Closed SwapnilDhotre closed 1 year ago

SwapnilDhotre commented 2 years ago

Describe the bug

I have configured the iOS app using amplify documentation. Not used Amplify CLI, but used Cognito User Pool and Identity Pool in amplifyconfiguration.json file. Installed latest library using pod as(version 1.27.0) pod 'Amplify' pod 'AmplifyPlugins/AWSCognitoAuthPlugin' Pod lock file: Screen Shot 2022-07-21 at 8 15 18 PM

Used only sign in method as Screen Shot 2022-07-21 at 8 26 25 PM

I have amplifyconfiguration.json same as in android and credential used for this API is also the same so there is no issues in that. But in the iOS application received error as `▿ AuthError: Incorrect username or password. Recovery suggestion: Check whether the given values are correct and the user is authorized to perform the operation. ▿ notAuthorized : 3 elements

In appdelegate added
try Amplify.add(plugin: AWSCognitoAuthPlugin()) try Amplify.configure() After running app, I received log as Amplify configured with auth plugin

Added configuration sample just masked some ids with xxx Screen Shot 2022-07-21 at 7 22 37 PM

Steps To Reproduce

Steps to reproduce the behavior:
1. Just follow amplify doc as in https://docs.amplify.aws/lib/auth/existing-resources/q/platform/ios/
2. Install latest amplify lib using pod
3. Add manually configured amplifyconfiguration.json in project
4. Hit sign-in method with password i.e. pass nil or "" string with only username in it.

Expected behavior

As all steps mentioned above is working in Android application then same should work in iOS as well.

Amplify Framework Version

1.27.0

Amplify Categories

Auth

Dependency manager

Cocoapods

Swift version

5.0

CLI version

Not used cli version

Xcode version

Xcode 13.1 (13A1030d)

Relevant log output

<details>
<summary>Log Messages</summary>

INSERT LOG MESSAGES HERE



### Is this a regression?

No

### Regression additional context

_No response_

### Device

On All device 

### iOS Version

Tried in iOS 12 and and 15

### Specific to simulators

_No response_

### Additional context

_No response_
royjit commented 2 years ago

Not that the Amplify-iOS library starts the custom auth flow with SRP. Please check here if you need to skip the SRP step as shown. - https://docs.amplify.aws/lib/auth/signin_with_custom_flow/q/platform/ios/#lambda-trigger-setup

Can you provide your define auth challenge lambda trigger ?

SwapnilDhotre commented 2 years ago

Thank you for your response. I debugged this issue with web team and they found that even if I am sending "authenticationFlowType": "CUSTOM_AUTH", they are receiving SRP_A from iOS device only. So aws is expecting for password and I am passing it as nil, so aws is giving response as Incorrect username or password.

Auth challange Lamda trigger used as:

exports.handler= async event => {    
    if (event.request.session &&
        event.request.session.find(attempt => attempt.challengeName !== 'CUSTOM_CHALLENGE')) {
        event.response.issueTokens = false;
        event.response.failAuthentication = true;
    } else if (event.request.session &&
        event.request.session.length > 2 &&
        event.request.session.slice(-1)[0].challengeResult === false) {
        // The user provided a wrong answer 3 times; fail auth
        event.response.issueTokens = false;
        event.response.failAuthentication = true;
    } else if (event.request.session &&
        event.request.session.length &&
        event.request.session.slice(-1)[0].challengeName === 'CUSTOM_CHALLENGE' && 
        event.request.session.slice(-1)[0].challengeResult === true) {
        // The user provided the right answer; succeed auth
        event.response.issueTokens = true;
        event.response.failAuthentication = false;
        console.log("Success OTP");
    } else {
        // The user did not provide a correct answer yet; present challenge
        event.response.issueTokens = false;
        event.response.failAuthentication = false;
        event.response.challengeName = 'CUSTOM_CHALLENGE';
    }

    return event;
};
royjit commented 2 years ago

iOS SDK currently starts the custom auth flow with SRP and the link I mentioned in my previous comment addresses that. We would need to bypass the SRP challenge something on the lines:

 if (event.request.session && 
    event.request.session.find(attempt => attempt.challengeName == 'SRP_A')) {
    event.response.issueTokens = false;
    event.response.failAuthentication = false;
    event.response.challengeName = 'CUSTOM_CHALLENGE'; // by pass to custom challenge
  } 
SwapnilDhotre commented 1 year ago

With above changes it is working fine. Thanks.

jav8r1at commented 12 months ago

Hi , Im am integrating Amplify on iOS

using do { let signInResult = try await Amplify.Auth.signIn(username: userId, password: password) switch signInResult.nextStep { case .confirmSignInWithSMSMFACode(let deliveryDetails, let info): print("SMS code send to (deliveryDetails.destination)") print("Additional info (String(describing: info))")

                // Prompt the user to enter the SMSMFA code they received
                // Then invoke `confirmSignIn` api with the code

            case .confirmSignInWithCustomChallenge(let info):
                print("Custom challenge, additional info \(String(describing: info))")

                // Prompt the user to enter custom challenge answer
                // Then invoke `confirmSignIn` api with the answer

            case .confirmSignInWithNewPassword(let info):
                print("New password additional info \(String(describing: info))")
                DispatchQueue.main.async {
                    NotificationCenter.default.post(name: NSNotification.showResetPasswordViewForFirstLogin,
                                                    object: nil, userInfo: [:])
                }

                // Prompt the user to enter a new password
                // Then invoke `confirmSignIn` api with new password

            case .resetPassword(let info):
                print("Reset password additional info \(String(describing: info))")

                // User needs to reset their password.
                // Invoke `resetPassword` api to start the reset password
                // flow, and once reset password flow completes, invoke
                // `signIn` api to trigger signin flow again.

            case .confirmSignUp(let info):
                print("Confirm signup additional info \(String(describing: info))")

                // User was not confirmed during the signup process.
                // Invoke `confirmSignUp` api to confirm the user if
                // they have the confirmation code. If they do not have the
                // confirmation code, invoke `resendSignUpCode` to send the
                // code again.
                // After the user is confirmed, invoke the `signIn` api again.
            case .done:
                do {
                    let session = try await Amplify.Auth.fetchAuthSession()

} catch let error as AuthError { print("Fetch auth session failed with error - (error)") } } catch let error as AuthError{ print ("Sign in failed (error)") completion(false, error.errorDescription, error) } catch { print("Unexpected error: (error)") } Im getting error as follows when i deliberately enter an incorrect password.. AuthError: Incorrect username or password. Recovery suggestion: Check whether the given values are correct and the user is authorized to perform the operation. ▿ notAuthorized : 3 elements - .0 : "Incorrect username or password." - .1 : "Check whether the given values are correct and the user is authorized to perform the operation." - .2 : nil

 My question here is how can i extract the error message form here. as i want to have redable userexperinece  .
 Another question , why is it throwing error in that last catch Block and not the error in AuthError block