I'm currently running into this error when implementing the AWSMobileClient signUp function. I haven't really altered the code sample from the AWS page describing how to implement it, other than changing the attributes to fit my user pool attribute requirements.
First in viewDidLoad, I initialize the mobile client like so:
AWSMobileClient.sharedInstance().initialize { (userState, error) in
if let userState = userState {
print("UserState: \(userState.rawValue)")
} else if let error = error {
print("error: \(error.localizedDescription)")
}
}
Then I have the function for signing up. This is what the code looks like (I encapsulate this in a function called signUpUser):
AWSMobileClient.sharedInstance().signUp(username: userEmail,
password: userPass,
userAttributes: ["email":userEmail, "given_name":userFirstName, "family_name": userLastName, "custom:school":userSchool]) { (signUpResult, error) in
if let signUpResult = signUpResult {
switch(signUpResult.signUpConfirmationState) {
case .confirmed:
print("User is signed up and confirmed.")
case .unconfirmed:
print("User is not confirmed and needs verification via \(signUpResult.codeDeliveryDetails!.deliveryMedium) sent at \(signUpResult.codeDeliveryDetails!.destination!)")
case .unknown:
print("Unexpected case")
}
} else if let error = error {
if let error = error as? AWSMobileClientError {
switch(error) {
case .usernameExists(let message):
print(message)
default:
break
}
}
print("\(error.localizedDescription)")
}
When I run the app on my iPhone, I call this function when the "Sign Up Button" is clicked. In the debug window, I get the following error:
The operation couldn’t be completed. (AWSMobileClient.AWSMobileClientError error 20.)
That's the only info that appears in the Xcode console. Does anyone know how to go about debugging or fixing this?
EDIT: I'm not sure what the issue was that caused this error. I started a fresh project, set up a new cognito pool and backend services, and ported over the code from this project, which resulted in everything working perfectly. The error may have been from incorrectly setting up the user pool, or perhaps not allowing unauthorized access to the sign up function (not sure if I had that set to "No").
If you exhaust the rest of the switch case there, you will be able to see what exactly is the error coming back from the service.
reference: https://stackoverflow.com/a/59521025/2464632
Related
I'm using MongoDB's Atlas Device Sync (until recently it was called Realm Sync) to handle login for my iOS app, coded in Swift.
I am UK based, and the app works fine for users in the UK. However, I recently sent the app to contacts in Eastern Europe (Poland, Belarus, potentially other countries as well. One person also tried logging in using a French VPN apparently) and they've all received the same error when creating an account or logging in with an already created account.
The localised description of this error is "cannot parse response".
Unfortunately I am based in the UK so I can't replicate it on my own device. However, I know that the error when creating an account is being thrown from the below code:
app.emailPasswordAuth.registerUser(email: email!, password: password!, completion: { [weak self] (error) in
DispatchQueue.main.async {
guard error == nil else {
self!.signUpFailed(with: error!)
return
}
self!.signIn(with: self!.email!, and: self!.password!)
}
})
And I know that the error when logging in to an already created account is being thrown from the below code:
app.login(credentials: Credentials.emailPassword(email: email, password: password)) { [weak self] (result) in
DispatchQueue.main.async {
switch result {
case .failure(let error):
self!.signInFailed(with: error)
return
case .success(let user):
self!.continueLoggingIn()
}
}
}
I'm at a bit of a loss here. I have no idea why the response can be parsed in the UK but not other countries. I assume it's an issue with Mongo/Realm but I could be wrong. If anyone can shed any light it would be greatly appreciated.
I am attempting to implement amplify auth on iOS, and what I would like to be able to do is customize the error message that is displayed to a user when authentication fails, as the default error messages are not end-user friendly, but I have no idea how to do this.
For instance, my signIn method is as follows:
func signIn(username: String) {
Amplify.Auth.signIn(username: username, password: "bla") { [weak self] result in
switch result {
case .success (let result):
if case .confirmSignInWithCustomChallenge(_) = result.nextStep {
DispatchQueue.main.async {
self?.showConfirmationSignInView()
}
} else {
print("Sign in succeeded")
}
case .failure(let error):
print (error)
}
}
}
Now in the .failure case, instead of printing the error, I would ideally like to determine if the error is a userNotFound error, or something else. I can't find any info in the docs on this. Any help would be appreciated.
You can do it by checking the error.code. for example, for a user who did not confirm the email if he tries to login then error.code will have UserNotConfirmedException string value. Amplify auth returns different exception codes for different types of errors. You can see all the exceptions from this link. Although it is for flutter, the exception code is identical for any framework. I have used these exception codes in react.
I want to give info to the user about the error that occurred while sending a request to the server. I use Alamofire.
The code is like below:
Alamofire.request(url, method: methodUsed, parameters: parameters).responseData { (response) in
switch response.result {
case .failure(let error) :
// I want to the describe the error in here
case .success(let value) :
let json = JSON(value)
completion(.success(json))
}
}
I have tried but I can't switch the error. I want something similar to this to be placed in the code above:
switch error {
case .NoSignal : // give alert to the user about the signal
case .ServerError : // give alert to the user about server error
}
For some case I want to inform the user to take some action on the alert but I don't know what the available cases are and I don't know the syntax that has to be used.
As per Jayesh Thanki says you can identify the server error using status code and for internet connectivity you can use NetworkReachabilityManager of Alamofire. Write following code in viewDidLoad():
var networkManager: NetworkReachabilityManager = NetworkReachabilityManager()!
networkManager.startListening()
networkManager.listener = { (status) -> Void in
if status == NetworkReachabilityManager.NetworkReachabilityStatus.notReachable {
print("No internet available")
}else{
print("Internet available")
}
You can identify error using status code. response.response.statusCode.
There is lots of HTTP status code and using them you can inform end user with alert.
Here is wikipedia link for list of status code.
For example is status code is 200 OK then its successful HTTP request
and status code is 500 Internal Server Error then its server related error.
You can also provide error description using response.result.error.localizedDescription if error is available.
Not sure if this a bug or an intended feature.
To create a user with an email and password in Firebase, I've been using the following code:
FIRAuth.auth()?.signIn(withEmail: email, password: password) { (user, error) in
if let error = error {
guard let error = error as? FIRAuthErrorCode else { return } // ALWAYS FAILS
...code...
}
...code...
}
The error parameter in the completion handler for the method cannot be cast as FIRAuthErrorCode; it always fails. Is that a bug, or is that the expected behaviour?
Edit: I am aware that error codes can be used to distinguish between the different types of FIRAuthErrorCode errors. It's just not readable, and it doesn't make much sense for the error parameter in the completion handler to be not of be of type FIRAuthErrorCode. The cases and error codes of FIRAuthErrorCode can be found here.
Have you tried using guard let error = error as! FIRAuthErrorCode else { return } to force the casting and check whether the return is nil or not?
After contacting Firebase support about the issue, they've said that the errors that are passed back in completion handlers are just Error objects. They weren't FIRAuthErrorCode objects. To test for the various FIRAuthErrorCode cases, one would have to do something like this:
FIRAuth.auth()?.signIn(withEmail: email, password: password) { (user, error) in
if let error = error {
guard let error = FIRAuthErrorCode(rawValue: error._code) else {
fatalError("This should never be executed")
}
switch error {
case .errorCodeInvalidEmail: ...
case .errorCodeWrongPassword: ...
default: ...
}
...code...
}
...code...
}
^ This preserves readability and makes error handling more intuitive. And, there is no need for error casting!
You should check the documentation of signIn method in firebase in order to check the all possible type of error this method can send and then check those type of errors in guard block in your code.
Try this, it's how I do my login and it seems to work great.
FIRAuth.auth()?.signIn(withEmail: EmailField.text!, password: PasswordField.text!, completion: { user, error in
if error == nil {
print("Successfully Logged IN \(user!)")
self.performSegue(withIdentifier: "Login", sender: self)
}
})
I just check that there's not an error with the signin process, then perform my segue.
My anonymous login for Firebase was working for months; however, when Xcode forced me to install some updates, it couldn't find some pods. After deleting those pods after running pod update, the project will now build; however, while attempting the anonymous login, I get this error:
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
If I wait long enough, I get error messages like this:
[Client] Discarding message for event <private> because of too many unprocessed messages
Here is my login method:
func login(onCompletion: #escaping (NSError?) -> Void) {
print("authenticating user")
FIRAuth.auth()?.signInAnonymously(completion: { result, error in
guard error == nil else {
print("error while authenticating user")
onCompletion(loginError)
return
}
if let user = result {
self.defaults.set(user.uid, forKey: "uid")
onCompletion(nil)
} else {
onCompletion(loginError)
}
})
}
which is called in the root view controller's viewDidLoad.
I still don't know what the issue was, but it was specific to the project. I created a new project and pulled the code from github and now it works like normal.