如何从登录/注册 AWS Amplify 获取身份验证错误?

GBM*_*BMR 7 swift aws-amplify

我目前正在尝试了解当用户尝试登录/注册时抛出什么类型的错误,但我的 switch case 不起作用,因为我不知道我应该与什么枚举进行比较。一旦确定了错误,应用程序就会显示一个 UIAlertController 来解释该错误。如果我print(err.code)只是得到一个 Int 回来。有人能引导我走向正确的方向吗?我找不到任何有关如何处理它的文档。

func signIn(username: String, password: String) {
    Amplify.Auth.signIn(username: username, password: password) { result in
        switch result {
        case .success:
            print("Sign in succeeded")
            //Go to root vc
        case .failure(let error):
            print("Sign in failed \(error)")
     if let err = error as NSError?{
          switch err.code {
                
          case AWSCognitoIdentityProviderErrorType.unknown.rawValue:
                        self.presentAlert(errorTitle: "Unkown Error", errorMessage: "An unknown error has occured", buttonText: "Ok")
                        print("Unkown error")
          case AWSCognitoIdentityProviderErrorType.invalidPassword.rawValue:
                        self.presentAlert(errorTitle: "Invalid Password", errorMessage: "You have entered an invalid password", buttonText: "Try Again")
          case AWSCognitoIdentityProviderErrorType.tooManyFailedAttempts.rawValue:
                        self.presentAlert(errorTitle: "Excedded login trys", errorMessage: "You attempted to login too many times", buttonText: "Try Again Later")
          case AWSCognitoIdentityProviderErrorType.userNotFound.rawValue:
                        self.presentAlert(errorTitle: "Unknown Credentials", errorMessage: "No user exists with the credentials you entered.", buttonText: "Try Again")
                    default:
                        break
                    }
                }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

JJJ*_*idt 4

Amplify Authentication 库抛出的错误类型是AuthError类型,其中包含更有用的嵌入式AWSCognitoAuthError类型。AWS 文档令人困惑和误导,因为 AWS 目前提供了两个 SDK:AWS Mobile SDK和更新、更笨的Amplify Libraries

您似乎正在使用 Amplify 库。如果您在 .failure 情况下在 Xcode 调试器中中断代码,调试器变量显示将显示errorAmplify.AuthError,这需要 AWS 博士学位才​​能理解。但出于说明的目的,如果您将其放入 .failure 情况下

        case .failure(let error):
            if let actualError = error.underlyingError as NSError? {
                print("Cast to nserror:", actualError)
            }
Run Code Online (Sandbox Code Playgroud)

您将得到Cast to nserror: AWSCognitoAuthPlugin.AWSCognitoAuthError.xxxxxx 可能所在的位置usernameExists或其他一些有用的错误。事实证明,AWSCognitoAuthError是一个简单的枚举,您可以通过在源代码中的某个随机位置键入内容来仔细阅读它AWSCognitoAuthError,然后右键单击并在 Xcode 弹出菜单中选择“跳转到定义” 。

我更喜欢将所有 voodoo Amplify 知识隔离开来,因此我创建了一个 User 类来与 AWS Authentication 服务交互。我在这里包含了错误处理部分,希望它能减轻您的痛苦。

// At the top of the file, outside the class:
import Amplify
import AWSCognitoAuthPlugin
import AWSPluginsCore
import Foundation

// This typealias allows other modules to interpret error responses
// from the AWSCognitoAuthError enum, such as ".usernameExists" without
// needing to import Amplify everywhere.
typealias AWSError = AWSCognitoAuthError

// Amplify Auth methods return AuthError type errors, which are complex multilayer
// enums that require complex deciphering if you want to extract a simple error
// to guide the user.
//
// This custom Error type allows callers from other modules to receive a simple
// explanatory "message" string, which is pulled from the .errorDescription
// property of an Amplify AuthError.  The "error" optional is the returned
// .underlyingError property cast to an AWSCognitoAuthError type, which is an
// enum of all the possible problems interacting with Amplify Auth such as
// .usernameExists, .userNotConfirmed, .codeMismatch, or .codeExpired.
struct UserError: Error {
    let message: String
    let error: AWSError?
    init(message: String?, error: Error?) {
        self.message = message ?? "Unknown error"
        self.error = error as? AWSError
    }
}

// Example of usage, within the class.  In my case the class signIn()
// function includes an onCompletion callback parameter to allow the
// caller to inform the user and change the UI according to the results.
func signIn(username: String, password: String, 
            onCompletion: @escaping (Result<Bool, UserError>) -> Void) {

    _ = Amplify.Auth.signIn(username: username, password: password) { result in
        switch result {
            case .success(let signInResult):
                onCompletion(.success(signInResult.isSignedIn))

            case .failure(let authError):
                let awsError = authError.underlyingError as? AWSError ?? AWSError.userNotFound
                let userError = UserError(message: authError.errorDescription,
                                          error: awsError)
                onCompletion(.failure(userError))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的视图控制器中,您可以按照以下方式处理来自上面示例的 SignIn() User 类方法的响应:

// Inside e.g. an @IBAction function
User.sharedUser.signIn(email, password: password, onCompletion: { result in
    switch result {
        case .success:
            // Go to root View Controller
    
        case .failure(let userError):
            if let authError = userError.error {
                if (authError == .userNotConfirmed) {
                    DispatchQueue.main.async {
                        self.performSegue(withIdentifier: "ShowConfirm", sender: nil)
                    }
                    return
                }
            }
            let alert = UIAlertController(title: userError.message, message: nil, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            DispatchQueue.main.async {
                self.present(alert, animated: true, completion: nil)
            }
    }
})
Run Code Online (Sandbox Code Playgroud)