aws-amplify / amplify-swift

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

Resending MFA code during sign in #3842

Closed Dave-London closed 2 months ago

Dave-London commented 2 months ago

Hi,

the sign in flow in our mobile apps requires MFA using amplify and cognito. the flow was implemented fully and works as expected. I'm trying to find a way to implement an option for the user to request a resend of the MFA code in case he didn't get the 1st code sent to him. from going over the documentation is seems that this is what Amplify.Auth.resendConfirmationCode(forUserAttributeKey: .email) is meant for (as written here). however it seems like it has been deprecated and the recommendation is to replace it with sendVerificationCode(forUserAttributeKey:options:).

I tried implementing using both options and in both cases got the same error: authError: No identity pool configuration found. suggestion: Make sure that the amplify configuration passed to Auth plugin is valid. this is a bit weird since our cognito setup does not use Identity pools but only user pools.

is this the approach you recommend for implementing MFA code resend functionality? if not, what do you suggest?

harsh62 commented 2 months ago

@Dave-London Would you be able to share the following 3 things for us to investigate further:

Dave-London commented 2 months ago
  1. I don't use a config file. here is the code I use to configure Amplify:
    
    func configureAmplify() {        
        let authConfig = AuthCategoryConfiguration(
            plugins: [
                "awsCognitoAuthPlugin": [
                    "UserAgent": "aws-amplify/ios",
                    "Version": "1.0",
                    "IdentityManager": [
                        "Default": [:]
                    ],
                    "CognitoUserPool": [
                        "Default": [
                            "PoolId": .string(cognitoPoolId),
                            "AppClientId": .string(cognitoClientId),
                            "Region": .string(cognitoRegion)
                        ]
                    ],
                    "Auth": [
                        "Default": [
                            "authenticationFlowType": "USER_SRP_AUTH"
                        ]
                    ]
                ]
            ]
        )        
        let configuration = AmplifyConfiguration(auth: authConfig)                
        do {
            try Amplify.add(plugin: AWSCognitoAuthPlugin())
            try Amplify.configure(configuration)
            logDebug("Amplify configured with auth plugin")
        } catch {
            logDebug("Failed to configure Amplify: \(error)")
        }
    }

2. verbose log files are attached.
[mfa resend logs.log](https://github.com/user-attachments/files/16843756/mfa.resend.logs.log)

3. here is the API usage code:
func request2FACodeResend(_ deliveryMethod: MFADeliveryMethod) -> AnyPublisher<Resource<Void>, Never> {
    logDebug("AmplifyServiceImpl.request2FACodeResend called with \(deliveryMethod)")
    return Future<Resource<Void>, Never> { promise in
        Task.init(operation: {
            do {
                if deliveryMethod == .email {
                //  let resendResult = try await Amplify.Auth.sendVerificationCode(forUserAttributeKey: .email)
                    let resendResult = try await Amplify.Auth.resendConfirmationCode(forUserAttributeKey: .email)
                    logDebug("MFA code resent. method: \(String(describing: resendResult.attributeKey)), destination: \(resendResult.destination)")
                } else {
                //  let resendResult = try await Amplify.Auth.sendVerificationCode(forUserAttributeKey: .phoneNumber)
                    let resendResult = try await Amplify.Auth.resendConfirmationCode(forUserAttributeKey: .phoneNumber)
                    logDebug("MFA code resent. method: \(String(describing: resendResult.attributeKey)), destination: \(resendResult.destination)")
                }
                promise(.success(Resource.success(Void())))
            } catch {
                logError("Error in AmplifyServiceImpl.request2FACodeResend: \(error)")

                if let authError = error as? AmplifyError {
                    logError("authError: \(authError.errorDescription). suggestion: \(authError.recoverySuggestion)")
                }
                promise(.success(Resource.failure(NovaError.signInGeneralFailure)))
            }
        })
    }
    .eraseToAnyPublisher()
}
harsh62 commented 2 months ago

Unfortunately the feature is not supported by AWS Cognito. The workaround seems to be caching the credentials and calling the sign in API again.

For the misleading error message, I'll work on fixing that.

github-actions[bot] commented 2 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.