AWS Cognito GetDetails() Method not calling - swift

I'm using AWS Cognito for my app Sign In and Sign up. In my app first the user register with email and phone number. After that, I'm redirecting to Verification Screen(Here OTP is sending by Cognito) After Verifying the OTP user will create some stores and then enter into the Dashboard. In this flow, I want to get the User details Attribute from Cognito in Verification code success. I've implemented the getDetails() method to get the userAttributes in Verification code success but it is not calling. I need the userAttributes when the time of store creation. Any help appreciated.
Here is my code:
#IBAction func submitButtonAction(_ sender: GradientButton) {
let code = firstChar+secondChar+thirdChar+fourthChar+fifthChar+sixthChar
guard code.count == 6 else{
self.showAlert(message: ErrorMessages.kEnterValidOTP)
return
}
let currentUser = self.userPool?.getUser("xxxx#gmail.com")
currentUser?.confirmSignUp(code, forceAliasCreation: true).continueWith(block: { [weak self] (task) -> Any? in
guard let strongSelf = self else { return nil }
DispatchQueue.main.async {
if let error = task.error as NSError? {
if let message = error.userInfo["message"] as? String{
self?.showAlert(message: message, onOkAction: {
strongSelf.clearTextFieldData()
})
}else{
self?.showAlert(message: error.localizedDescription, onOkAction: {
strongSelf.clearTextFieldData()
})
}
}else{
print(task.result)
strongSelf.clearTextFieldData()
print(AWSUserDetails.shared.userPool.currentUser()?.username)
let user = AWSUserDetails.shared.userPool.currentUser()
//I've tried the above `user` and `currentUser`. But not working.
user?.getDetails().continueOnSuccessWith(block: { (task) -> Any? in
DispatchQueue.main.async {
if task.error == nil{
print(task.error)
}else{
print(task.result)
}
}
})
// strongSelf.performSegue(withIdentifier: SegueIdentifiers.createStoreSegue, sender: self)
}
}
return nil
})
}

Related

How to get the user id from the firebase authentication

i am using phone number authenticator for verify my user. i have verify them using following code.
PhoneAuthProvider.provider().verifyPhoneNumber(mobileNo!, uiDelegate: nil) { (verificationID, error) in
if error != nil {
self.errorLabel.text = error?.localizedDescription
}else{
log.success("\(mobileNo!)")/
// add authentication code to the defaults
let defaults = UserDefaults.standard
defaults.set(verificationID, forKey: "authVID")
self.performSegue(withIdentifier: "sendCode", sender: Any?.self)
}
}
verify the code using following code
func verifyCode(){
let defaults = UserDefaults.standard
let credential: PhoneAuthCredential = PhoneAuthProvider.provider().credential(withVerificationID: defaults.string(forKey: "authVID")!, verificationCode: verficationCodeTextField.text!)
Auth.auth().signIn(with: credential) { (user, error) in
if error != nil {
self.errorLabel.text = error?.localizedDescription
self.errorLabel.alpha = 1
}else{
self.transitionToRegistration()
}
}
}
now i need to get the userid from the authentication ?
this can be done by using following code line.
guard let userID = Auth.auth().currentUser?.uid else { return }

How to change email address in Firebase?

I have some problems with changing email address in firebase authentication.
My code looks like this now:
func changeEmail(withEmail email: String, completion: #escaping ((Bool) -> Void)) {
guard let currentUser = Auth.auth().currentUser, let email = mail else { return }
currentUser.updateEmail(to: email) { [weak self]
error in
guard let self = self else { return }
let title: String
let message: String
if let error = error {
title = "alert.error.title".localized()
message = error.localizedDescription
} else {
title = email
message = "auth.confirm.email.popup".localized()
currentUser.sendEmailVerification()
}
self.navigator.showAlert(title: title,
message: message,
bottomLeftTitle: "general.got.it".localized(),
bottomLeftHandler: { completion(error == nil)
})
}
}
So it is okey, and working, and user can actually change email.
But problem occurs when user stayed too long and needs to re-login. Everyone knows that it is disturbing user experience in app.
Auth.auth().reload() //not working in this situation.
So how to change email, without asking user to logout and login again?
There is a reauthenticate method exactly for this purpose.
https://firebase.google.com/docs/auth/ios/manage-users#re-authenticate_a_user
What you need to do is ask the user for its login credentials again. No logout - login needed.
Possible code for that:
if (self.newPassword == self.newPasswordConfirm) && (!(self.newPassword.isEmpty) || !(self.newUserName.isEmpty)) {
reauthenticate(email: self.accountEmail, password: self.oldPassword) { isSucceeded in
//Successfully authenticated
if isSucceeded == true {
if !self.newUserName.isEmpty {
// update username
}
Auth.auth().currentUser?.updatePassword(to: self.newPassword) { (error) in
// Alert user that it didn't work
}
self.editProfile.toggle()
}
// Failed to reauthenticate
else if isSucceeded == false {
// Alert User
}
}
}

self.userUid = user.user.uid method still not working in Swift

Ok so in my code I get this error:'Value of type 'AuthDataResult' has no member 'uid''. Even after trying to use the authDataResult or the self.userUid = user.user.uid, I'm still getting the error. Here's my code if anyone wants to help me
#IBAction func SignIn (_ sender: AnyObject) {
if let email = emailField.text, let password = passwordField.text {
Auth.auth().signIn(withEmail: email, password: password, completion: { (user, error) in
if error == nil {
self.userUid = user.user.uid
KeychainWrapper.standard.set(self.userUid, forKey: "uid")
self.performSegue(withIdentifier: "toMessages", sender: nil)
} else {
self.performSegue(withIdentifier: "toSignUp", sender: nil)
}
})
}
}
Thanks if you can help me!
Inside if error == nil { do the following :
let user = Auth.auth().currentUser
if let user = user {
// The user's ID, unique to the Firebase project.
// Do NOT use this value to authenticate with your backend server,
// if you have one. Use getTokenWithCompletion:completion: instead.
let uid = user.uid
let email = user.email
}
You can find more information here:
https://firebase.google.com/docs/auth/ios/manage-users

What is the correct way to log in with facebook on firebase? swift

When I log in with a facebook account in a view, I pass it a second view, in the second view I want a fetch query but in the view log I get permission denied and I dont see the info.
I have a normal firebase account, application test facebook.
this is the code view log in
#IBAction func InicioSesionFacebook(_ sender: Any)
{
esperaSesion.isHidden = false
esperaSesion.startAnimating()
let fbLoginManager = FBSDKLoginManager()
fbLoginManager.logIn(withReadPermissions: ["public_profile", "email"], from: self) { (result, error) in
if let error = error {
print("Failed to login: \(error.localizedDescription)")
self.esperaSesion.stopAnimating()
return
}
guard let accessToken = FBSDKAccessToken.current() else {
print("Failed to get access token")
self.esperaSesion.stopAnimating()
return
}
let credential = FacebookAuthProvider.credential(withAccessToken: accessToken.tokenString)
// Perform login by calling Firebase APIs
Auth.auth().signIn(with: credential, completion: { (user, error) in
if let error = error
{
self.esperaSesion.stopAnimating()
print("Login error: \(error.localizedDescription)")
let alertController = UIAlertController(title: "Login Error", message: error.localizedDescription, preferredStyle: .alert)
let okayAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(okayAction)
self.present(alertController, animated: true, completion: nil)
return
}
else
{
let fbloginresult : FBSDKLoginManagerLoginResult = result!
if (result?.isCancelled)!
{
return
}
else
{
// Present the main view
self.esperaSesion.stopAnimating()
if let viewController = self.storyboard?.instantiateViewController(withIdentifier: "NavigationMasterController")
{
UIApplication.shared.keyWindow?.rootViewController = viewController
self.dismiss(animated: true, completion: nil)
}
}
}
})
}
}
this is the code in the second view, a query
import FirebaseAuth
import FirebaseDatabase
import FBSDKLoginKit
var refDB: DatabaseReference!
override func viewDidLoad()
{
super.viewDidLoad()
refDB = Database.database().reference()
CerrarSesion.layer.cornerRadius = 8
imagenPerfil.layer.cornerRadius = imagenPerfil.frame.height/2
imagenPerfil.clipsToBounds = true
verDatos()
// Do any additional setup after loading the view.
}
func verDatos()
{
let userID = Auth.auth().currentUser?.uid
refDB.child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
let nombre = value?["nombre"] as? String ?? ""
let apellido = value?["apellido"] as? String ?? ""
self.nombreUsuario.text = nombre
self.apellidoUsuario.text = apellido
// ...
}) { (error) in
print(error.localizedDescription)
}
}
and the button log out
#IBAction func CerrarSesion(_ sender: Any)
{
do
{
try Auth.auth().signOut()
self.view.window?.rootViewController?.dismiss(animated: true, completion: borrarUserDefaults)
}
catch let error as NSError
{
print (error.localizedDescription)
}
}
how is the correct form for log out when I logged in with facebook account?
You can check out my YouTube Tutorial on this exact topic !
https://www.youtube.com/watch?v=BfwNf-W-R4U
The version of the Facebook API that you are using is dated. The Login function should look something like this
let loginManager = LoginManager()
loginManager.logIn(readPermissions: [.publicProfile], viewController: self) {loginResult in
switch loginResult {
case .failed(let error):
print("error: \(error)")
case .cancelled:
print("User cancelled login.")
case .success(let grantedPermissions, let declinedPermissions, let accessToken):
print(grantedPermissions)
print(declinedPermissions)
fbAccessToken = accessToken
let credential = FacebookAuthProvider.credential(withAccessToken: (fbAccessToken?.authenticationToken)!)
Auth.auth().signIn(with: credential) { (user, error) in
if let error = error {
print(error)
return
}
currentUser = Auth.auth().currentUser
moveToHomeScreen()
print("Logged in!")
}
}
}
I think that you are getting a permissions error because the parameter name from the AccessToken changed and you are passing the wrong value. (Sorry I cant recall what the change was).
If you are following the Facebook API instructions on the facebook developer portal they are horrendously out of date iOS 9 I think.

Function will not call Swift 3

#IBAction func signup(_ sender: Any) {
print("began signup process")
guard let fullname = fullnameField.text, fullname != "" else {
print("FULLNAME field is empty")
return
}
guard let username = usernameField.text, username != "" else {
print("USERNAME field is empty")
return
}
guard let email = emailField.text, email != "" else {
print("EMAIL field is empty")
return
}
guard let password = passwordField.text, password != "" else {
print("PASSWORD field is empty")
return
}
print("all fields good")
mainActivityIndicator.startAnimating()
self.checkUsernameAvailability(username: username, completion: {
result in
print("starting check")
...
})
print("finished the function")
}
The issue is basically that nothing inside of the checkUsernameAvailability function will call.
The console looks like this:
began signup process
all fields good
finished the function
it does not print 'starting check' or run any code at all inside of the function.
This is probably a rookie error and I am sorry if it is a stupid question.
Future thanks.
P.S I checked the entire console and there is no error relating to this.
EDIT: Here is the code inside the function
func checkUsernameAvailability(username: String, completion: #escaping (Bool) -> Void) {
_ = Database.database().reference().child("usernames").observe(.childAdded, with: {
snapshot in
print("checking username availability")
print(snapshot)
completion(true)
let dict = snapshot.value as? [String: AnyObject]
for handled in (dict?.values)! {
print("stumbled")
print(handled)
if username.lowercased() == handled.lowercased {
completion(false)
}
}
})
}
And...
self.checkUsernameAvailability(username: username, completion: {
result in
print("starting check")
if result == false {
print("username is taken")
self.mainActivityIndicator.stopAnimating()
return
} else {
Auth.auth().createUser(withEmail: email, password: password, completion: {
(user, error) in
if error != nil {
print(error ?? "ERROR OCCURED")
self.mainActivityIndicator.stopAnimating()
return
}
let ref = Database.database().reference()
ref.child("~/users/\(user?.uid ?? "0")/username").setValue(username.lowercased())
ref.child("~/users/\(user?.uid ?? "0")/fullname").setValue(fullname)
ref.child("usernames/\(user?.uid ?? "0")").setValue(username.lowercased())
self.mainActivityIndicator.stopAnimating()
})
}
})
The Database.database().reference().child("usernames").observe call simply never calls the with block. I would assume that block is called when the event .childAdded is observed, but I see no code that would add a child. To me this looks like you are setting up an asynchronous observer, so this code will not run when you make the call, it will run when the monitored event takes place.