aws-amplify / amplify-ui-swift-authenticator

The Amplify UI Authenticator is a component that supports several authentiation flows using Amplify Authentication.
https://ui.docs.amplify.aws/swift/connected-components/authenticator
Apache License 2.0
15 stars 9 forks source link

If the user is automatically confirmed after Sign In, the Authenticator fails to Sign In and shows error #71

Closed lawmicha closed 5 months ago

lawmicha commented 6 months ago

I have the following backend CDK

amplify/auth/resource.ts

import { defineAuth, defineFunction } from '@aws-amplify/backend';

/**
 * Define and configure your auth resource
 * @see https://docs.amplify.aws/gen2/build-a-backend/auth
 */
export const auth = defineAuth({
  loginWith: {
    email: true
  },
  triggers: {
    // configure a trigger to point to a function definition
    preSignUp: defineFunction({
      entry: './pre-sign-up-handler.ts'
    })
  }
});

amplify/auth/pre-sign-up-handler.ts

import type { PreSignUpTriggerHandler } from 'aws-lambda';

export const handler: PreSignUpTriggerHandler = async (event) => {
  // your code here
  event.response.autoConfirmUser = true
  return event;
};

When I use Authenticator to sign up with email, the user gets auto confirmed by the lambda, and Authenticator attempts to sign in the user.

The sign in fails

Attempting to Sign Up
Starting execution for Auth.signUpAPI
Starting execution
AWSCognitoAuthPlugin/LoadCredentialStore.swift Starting execution
Credential Store state change:

{
    "CredentialStoreState.loadingStoredCredentials" =     {
    };
}
AWSCognitoAuthPlugin/LoadCredentialStore.swift Retreiving credential deviceMetadata(username: "mdlaw+test2@amazon.com")
AWSCognitoAuthPlugin/LoadCredentialStore.swift Sending event CredentialStoreEvent.throwError
AWSCognitoAuthPlugin/IdleCredentialStore.swift Starting execution
AWSCognitoAuthPlugin/IdleCredentialStore.swift Sending event CredentialStoreEvent.moveToIdleState
AWSCognitoAuthPlugin/LoadCredentialStore.swift Starting execution
AWSCognitoAuthPlugin/LoadCredentialStore.swift Retreiving credential asfDeviceId(username: "mdlaw+test2@amazon.com")
Credential Store state change:

{
    "CredentialStoreState.error" =     {
        errorType = "KeychainStoreError: Unable to find the keychain item";
    };
}
Credential Store state change:

{
    "CredentialStoreState.idle" =     {
    };
}
Credential Store state change:

{
    "CredentialStoreState.loadingStoredCredentials" =     {
    };
}
AWSCognitoAuthPlugin/LoadCredentialStore.swift Sending event CredentialStoreEvent.throwError
AWSCognitoAuthPlugin/IdleCredentialStore.swift Starting execution
AWSCognitoAuthPlugin/IdleCredentialStore.swift Sending event CredentialStoreEvent.moveToIdleState
Credential Store state change:

{
    "CredentialStoreState.error" =     {
        errorType = "KeychainStoreError: Unable to find the keychain item";
    };
}
AWSCognitoAuthPlugin/StoreCredentials.swift Starting execution
Credential Store state change:

{
    "CredentialStoreState.idle" =     {
    };
}
AWSCognitoAuthPlugin/StoreCredentials.swift Sending event CredentialStoreEvent.completedOperation
Credential Store state change:

{
    "CredentialStoreState.storingCredentials" =     {
    };
}
AWSCognitoAuthPlugin/IdleCredentialStore.swift Starting execution
AWSCognitoAuthPlugin/IdleCredentialStore.swift Sending event CredentialStoreEvent.moveToIdleState
Credential Store state change:

{
    "CredentialStoreState.success" =     {
        savedData = "AWSCognitoAuthPlugin.CredentialStoreData.asfDeviceId(\"64464796-E53C-4A76-8FA8-DC936BD56DA5\", \"mdlaw+test2@amazon.com\")";
    };
}
Credential Store state change:

{
    "CredentialStoreState.idle" =     {
    };
}
2024-04-30T14:01:49-0400 info CognitoIdentityProviderClient : [Logging] Request: POST https:443 
 Path: / 
 User-Agent: aws-sdk-swift/1.0 ua/2.0 api/cognito_identity_provider#1.0 os/ios#17.2.0 lang/swift#5.9 cfg/retry-mode#legacy, 
Content-Type: application/x-amz-json-1.1, 
Content-Length: 6423, 
X-Amz-Target: AWSCognitoIdentityProviderService.SignUp, 
Host: cognito-idp.us-east-1.amazonaws.com 
 nil
124163          HALC_ProxyIOContext.cpp:1328  HALC_ProxyIOContext::IOWorkLoop: skipping cycle due to overload
2024-04-30T14:01:50-0400 info URLSessionHTTPClient : [Logging] urlSession(_:dataTask:didReceive:) called
2024-04-30T14:01:50-0400 info URLSessionHTTPClient : [Logging] urlSession(_:dataTask:didReceive:) called with 71 bytes
2024-04-30T14:01:50-0400 info URLSessionHTTPClient : [Logging] urlSession(_:task:didCompleteWithError:) called. Success
Received result
Successfully completed execution for Auth.signUpAPI with result:
AuthSignUpResult(nextStep: Amplify.AuthSignUpStep.done, userID: Optional("e4489468-9041-704c-0be7-a541f8c192fe"))
Sign Up next step is done
Starting execution for Auth.signInAPI
Starting execution
Check if authstate configured
Auth state configured
Validating current state
Signing with userSRP
Sending signIn event
Waiting for signin to complete
AWSCognitoAuthPlugin/IntializeSignInFlow.swift Starting execution
AWSCognitoAuthPlugin/LoadCredentialStore.swift Starting execution
Credential Store state change:

{
    "CredentialStoreState.loadingStoredCredentials" =     {
    };
}
AWSCognitoAuthPlugin/LoadCredentialStore.swift Retreiving credential deviceMetadata(username: "")
Auth state change:

{
    "AuthState.configured" =     {
        "AuthenticationState.signingIn" =         {
            "SignInState.notStarted" =             {
            };
        };
        "AuthorizationState.sessionEstablished" = identityPoolOnly;
    };
}
Checking next step for: notStarted
AWSCognitoAuthPlugin/LoadCredentialStore.swift Sending event CredentialStoreEvent.throwError
AWSCognitoAuthPlugin/IdleCredentialStore.swift Starting execution
AWSCognitoAuthPlugin/IdleCredentialStore.swift Sending event CredentialStoreEvent.moveToIdleState
Credential Store state change:

{
    "CredentialStoreState.error" =     {
        errorType = "KeychainStoreError: Unable to find the keychain item";
    };
}
Credential Store state change:

{
    "CredentialStoreState.idle" =     {
    };
}
No existing device metadata found. AuthEnvironment(configuration: AWSCognitoAuthPlugin.AuthConfiguration.userPoolsAndIdentityPools(["verificationMechanisms": "[AWSCognitoAuthPlugin.UserPoolConfigurationData.VerificationMechanism.email]", "poolId": "us-e****XQHX", "endpoint": "N/A", "pinpointAppId": "(nil)", "usernameAttributes": "[AWSCognitoAuthPlugin.UserPoolConfigurationData.UsernameAttribute.email]", "signUpAttributes": "[AWSCognitoAuthPlugin.UserPoolConfigurationData.SignUpAttributeType.email]", "clientSecret": "(nil)", "region": "<REDACTED>", "clientId": "7531****8ajk", "hostedUI": "N/A", "passwordProtectionSettings": "Optional(AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordProtectionSettings(minLength: 8, characterPolicy: [AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.lowercase, AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.uppercase, AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.numbers, AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.symbols]))"], ["poolId": "us-e****2a05", "region": "<REDACTED>"]), userPoolConfigData: Optional(["verificationMechanisms": "[AWSCognitoAuthPlugin.UserPoolConfigurationData.VerificationMechanism.email]", "poolId": "us-e****XQHX", "endpoint": "N/A", "pinpointAppId": "(nil)", "usernameAttributes": "[AWSCognitoAuthPlugin.UserPoolConfigurationData.UsernameAttribute.email]", "signUpAttributes": "[AWSCognitoAuthPlugin.UserPoolConfigurationData.SignUpAttributeType.email]", "clientSecret": "(nil)", "region": "<REDACTED>", "clientId": "7531****8ajk", "hostedUI": "N/A", "passwordProtectionSettings": "Optional(AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordProtectionSettings(minLength: 8, characterPolicy: [AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.lowercase, AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.uppercase, AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.numbers, AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.symbols]))"]), identityPoolConfigData: Optional(["poolId": "us-e****2a05", "region": "<REDACTED>"]), authenticationEnvironment: Optional(AWSCognitoAuthPlugin.BasicAuthenticationEnvironment(srpSignInEnvironment: AWSCognitoAuthPlugin.BasicSRPSignInEnvironment(srpAuthEnvironment: AWSCognitoAuthPlugin.BasicSRPAuthEnvironment(userPoolConfiguration: ["verificationMechanisms": "[AWSCognitoAuthPlugin.UserPoolConfigurationData.VerificationMechanism.email]", "poolId": "us-e****XQHX", "endpoint": "N/A", "pinpointAppId": "(nil)", "usernameAttributes": "[AWSCognitoAuthPlugin.UserPoolConfigurationData.UsernameAttribute.email]", "signUpAttributes": "[AWSCognitoAuthPlugin.UserPoolConfigurationData.SignUpAttributeType.email]", "clientSecret": "(nil)", "region": "<REDACTED>", "clientId": "7531****8ajk", "hostedUI": "N/A", "passwordProtectionSettings": "Optional(AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordProtectionSettings(minLength: 8, characterPolicy: [AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.lowercase, AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.uppercase, AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.numbers, AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.symbols]))"], cognitoUserPoolFactory: (Function), eventIDFactory: (Function), srpClientFactory: (Function), srpConfiguration: (nHexValue: "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF", gHexValue: "2"))), userPoolEnvironment: AWSCognitoAuthPlugin.BasicUserPoolEnvironment(userPoolConfiguration: ["pinpointAppId": "(nil)", "clientId": "7531****8ajk", "signUpAttributes": "[AWSCognitoAuthPlugin.UserPoolConfigurationData.SignUpAttributeType.email]", "passwordProtectionSettings": "Optional(AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordProtectionSettings(minLength: 8, characterPolicy: [AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.lowercase, AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.uppercase, AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.numbers, AWSCognitoAuthPlugin.UserPoolConfigurationData.PasswordCharacterPolicy.symbols]))", "usernameAttributes": "[AWSCognitoAuthPlugin.UserPoolConfigurationData.UsernameAttribute.email]", "poolId": "us-e****XQHX", "verificationMechanisms": "[AWSCognitoAuthPlugin.UserPoolConfigurationData.VerificationMechanism.email]", "clientSecret": "(nil)", "region": "<REDACTED>", "endpoint": "N/A", "hostedUI": "N/A"], cognitoUserPoolFactory: (Function), cognitoUserPoolASFFactory: (Function), cognitoUserPoolAnalyticsHandlerFactory: (Function)), hostedUIEnvironment: nil)), authorizationEnvironment: Optional(AWSCognitoAuthPlugin.BasicAuthorizationEnvironment(identityPoolConfiguration: ["region": "<REDACTED>", "poolId": "us-e****2a05"], cognitoIdentityFactory: (Function), eventIDFactory: (Function))), credentialsClient: AWSCognitoAuthPlugin.CredentialStoreOperationClient, logger: Amplify.BroadcastLogger)
AWSCognitoAuthPlugin/IntializeSignInFlow.swift Sending event SignInEvent.initiateSignInWithSRP
AWSCognitoAuthPlugin/StartSRPFlow.swift Start execution
AWSCognitoAuthPlugin/StartSRPFlow.swift Sending event SignInEvent.initiateSignInWithSRP
Auth state change:

{
    "AuthState.configured" =     {
        "AuthenticationState.signingIn" =         {
            "SignInState.signingInWithSRP" =             {
                "SRPSignInState.notStarted" =                 {
                };
                clientMetadata =                 {
                };
                password = "<REDACTED>";
                signInMethod = "AWSCognitoAuthPlugin.SignInMethod.apiBased(AWSCognitoAuthPlugin.AuthFlowType.userSRP)";
                username = "";
            };
        };
        "AuthorizationState.sessionEstablished" = identityPoolOnly;
    };
}
Checking next step for: signingInWithSRP(AWSCognitoAuthPlugin.SRPSignInState.notStarted, ["username": "", "password": "<REDACTED>", "clientMetadata": [:], "signInMethod": AWSCognitoAuthPlugin.SignInMethod.apiBased(AWSCognitoAuthPlugin.AuthFlowType.userSRP)])
Checking next step for: signingInWithSRP(AWSCognitoAuthPlugin.SRPSignInState.error(AWSCognitoAuthPlugin.SignInError.inputValidation(field: "username")), ["username": "", "password": "<REDACTED>", "clientMetadata": [:], "signInMethod": AWSCognitoAuthPlugin.SignInMethod.apiBased(AWSCognitoAuthPlugin.AuthFlowType.userSRP)])
Auth state change:

{
    "AuthState.configured" =     {
        "AuthenticationState.signingIn" =         {
            "SignInState.signingInWithSRP" =             {
                "SRPSignInState.error" =                 {
                    Error = "AWSCognitoAuthPlugin.SignInError.inputValidation(field: \"username\")";
                };
                clientMetadata =                 {
                };
                password = "<REDACTED>";
                signInMethod = "AWSCognitoAuthPlugin.SignInMethod.apiBased(AWSCognitoAuthPlugin.AuthFlowType.userSRP)";
                username = "";
            };
        };
        "AuthorizationState.sessionEstablished" = identityPoolOnly;
    };
}
Wait for signIn to cancel
Auth state change:

{
    "AuthState.configured" =     {
        "AuthenticationState.signedOut" =         {
            lastKnownUserName = "(nil)";
        };
        "AuthorizationState.configured" =         {
        };
    };
}
Failed execution for Auth.signInAPI with error:
AuthError: Username is required to signIn
Recovery suggestion: Make sure that a valid username is passed during signIn
Unable to Sign In after sucessfull sign up
The operation couldn’t be completed. (Amplify.AuthError error 3.)
AuthError: Username is required to signIn
Recovery suggestion: Make sure that a valid username is passed during signIn
The operation couldn’t be completed. (Amplify.AuthError error 3.)
AuthError: Username is required to signIn
Recovery suggestion: Make sure that a valid username is passed during signIn
Creating an unknown AuthenticatorError
AuthError: Username is required to signIn
Recovery suggestion: Make sure that a valid username is passed during signIn
github-actions[bot] commented 6 months ago

This issue was opened by a maintainer of this repository; updates will be posted here. If you are also experiencing this issue, please comment here with any relevant information so that we're aware and can prioritize accordingly.

lawmicha commented 6 months ago

Confirmed that without the pre-sign up auto confirm user lambda, then the flow from sign up -> confirm -> sign in works as expected. We also confirmed that the state is being updated here, https://github.com/aws-amplify/amplify-ui-swift-authenticator/blob/main/Sources/Authenticator/States/SignUpState.swift#L57 credentials.username is being set to the email value. This does not appear to be a Gen2 related bug

ruisebas commented 6 months ago

Yes, this is an Authenticator bug when a new user is automatically confirmed, the component attempts to log in without the credentials and it causes the error. I will submit a fix.

ruisebas commented 5 months ago

This has been fixed in version 1.1.3

github-actions[bot] commented 5 months ago

This issue is now closed. Comments on closed issues are hard for our team to see. If you need more assistance, please open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.