facebookLogin.logInWithReadPermissions with Firebase issues - swift

I am able to successfully authenticate login with facebook using basic SDK procedures, but am having some confusion when I am trying to authenticate with Firebase. I have read through the documentation and copied and pasted the code but I am still getting a warning that reads
'logInWithReadPermissions(_:handler:)' is deprecated: use logInWithReadPermissions:fromViewController:handler: instead facebookLogin.logInWithReadPermissions(["email"], handler: instead.
1) What does this warning mean and how do I fix it?
2) With emails and password sign in you see the registered users created, but how do I know and see if users were registered with facebook authentication in the Firebase DB?
Thanks for any help or direction!
import UIKit
import Firebase
import FBSDKCoreKit
import FBSDKLoginKit
class ViewController: UIViewController, FBSDKLoginButtonDelegate {
let loginButton: FBSDKLoginButton = {
let button = FBSDKLoginButton()
button.readPermissions = ["email"]
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(loginButton)
loginButton.center = view.center
loginButton.delegate = self
let ref = Firebase(url: "https://my-app.firebaseio.com")
let facebookLogin = FBSDKLoginManager()
facebookLogin.logInWithReadPermissions(["email"], handler: {
(facebookResult, facebookError) -> Void in
if facebookError != nil {
print("Facebook login failed. Error \(facebookError)")
} else if facebookResult.isCancelled {
print("Facebook login was cancelled.")
} else {
let accessToken = FBSDKAccessToken.currentAccessToken().tokenString
ref.authWithOAuthProvider("facebook", token: accessToken,
withCompletionBlock: { error, authData in
if error != nil {
print("Login failed. \(error)")
} else {
print("Logged in! \(authData)")
}
})
}
})
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
if error == nil {
print("completed login")
self.performSegueWithIdentifier("showNew", sender: self)
}
else {
print(error.localizedDescription)
}
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
print("user logged out")
}
func loginButtonWillLogin(loginButton: FBSDKLoginButton!) -> Bool {
return true
}
}

Try something like (compiles without warnings to me):
let currentToken = FBSDKAccessToken.currentAccessToken()
// Show login only if we had not logged in before
if (currentToken == nil || !currentToken.hasGranted("email")) {
let ref = Firebase(url: "https://my-app.firebaseio.com")
let facebookLogin = FBSDKLoginManager()
facebookLogin.logInWithReadPermissions(["email"], fromViewController: self, handler: {
(facebookResult, facebookError) -> Void in
if facebookError != nil {
log.error("Facebook login failed. Error \(facebookError)")
.
.
.

Related

AWS Cognito GetDetails() Method not calling

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
})
}

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.

EXC_BREAKPOINT (code=1, subcode=0x1051fbb50) console prints this: fatal error: Index out of range

I am new to swift development and I apologize if this question has already been answered, but I have no Idea why I am getting this error. it will build successfully, but when the buttonTapped gets tapped I get this error and the app crashes.
here is my code:
import UIKit
import Firebase
import FBSDKLoginKit
import FirebaseAuth
import FBSDKCoreKit
class QuotesViewController: UIViewController {
#IBOutlet weak var quoteLabel: UILabel!
var quotes : [Quote] = []
override func viewDidLoad() {
super.viewDidLoad()
Database.database().reference().child("quotes").observe(DataEventType.childAdded, with: {(snapshot) in
print(snapshot)
let quote = Quote()
quote.quote = (snapshot.value! as! NSDictionary)["quote"] as! String
self.quotes.append(quote)
})
}
#IBAction func buttonTapped(_ sender: Any) {
newQuote()
}
#IBAction func didTappedLogout(_ sender: Any) {
// sign user out of firebase
let firebaseAuth = Auth.auth()
do {
try firebaseAuth.signOut()
} catch let signOutError as NSError {
print ("Error signing out: %#", signOutError)
}
// sign user out of Facebook
FBSDKAccessToken.setCurrent(nil)
let mainStoryboard: UIStoryboard = UIStoryboard(name:"Main", bundle:nil)
let SignInViewController: UIViewController = mainStoryboard.instantiateViewController(withIdentifier: "LoginView")
self.present(SignInViewController, animated: true, completion: nil)
}
func newQuote(){ **this is where I get the error**
let myQuote = quotes[Int(arc4random_uniform(UInt32(quotes.count) ))]
quoteLabel.text = myQuote.quote
// print(myQuote.quoteID)
}
override func motionEnded(_ motion: UIEventSubtype, with event: UIEvent?) {
newQuote()
}
}
I'm gonna guess that your app is crashing because you're trying to access an item in the quotes array before Firebase gets the data to put in it. Thus, when you try to get something from it, there's nothing in it, so every index (even 0) is out of bounds. You should check to make sure that there's something in quotes first, like this:
func newQuote(){
guard !quotes.isEmpty else{
// Tell the user there are no quotes yet
return
}
let myQuote = quotes[Int(arc4random_uniform(UInt32(quotes.count) ))]
quoteLabel.text = myQuote.quote
}
the issue was that the signInSegue was out side the credential function like this:
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
if error != nil {
print(error)
return
}
print("Successfully logged in with Facebook...")
let credential = FacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString)
Auth.auth().signIn(with: credential) { (user, error) in
print("User logged in...")
}
self.performSegue(withIdentifier: "signInSegue", sender: nil)
}
it should be like this:
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
if error != nil {
print(error)
return
}
print("Successfully logged in with Facebook...")
let credential = FacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString)
Auth.auth().signIn(with: credential) { (user, error) in
print("User logged in...")
self.performSegue(withIdentifier: "signInSegue", sender: nil)
}
}

how do I perform segue after log in with facebook account?

Currently I am attempting to perform a segue to a second view controller after a user logs in with Facebook using firebase
I was able to sort of get this to work. My problem is I have to actually log-in twice before the Segue is activated. Any suggestions?
see my CODE below
private var fbLoginSuccess = false //This is gobal
override func viewDidAppear(_ animated: Bool) {
if (FBSDKAccessToken.current() != nil && fbLoginSuccess == true)
{
performSegue(withIdentifier: "Home", sender: self)
}
}
#IBAction func facebookLogin(sender: UIButton) {
let facebookLogin = FBSDKLoginManager()
facebookLogin.logIn(withReadPermissions: ["public_profile", "email"], from: self, handler: {
(facebookResult, facebookError) -> Void in
if facebookError != nil {
print("Facebook login failed. Error \(String(describing: facebookError))")
} else if (facebookResult?.isCancelled)! {
print("Facebook login was cancelled.")
} else {
let credential = FacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString)
Auth.auth().signIn(with: credential) { (user, error) in
if error != nil {
print("Login failed. \(String(describing: error))")
} else {
fbLoginSuccess = true
print("Logged in!")
if (facebookResult?.grantedPermissions.contains("email"))! {
}
}
}
}
})
}
It appears that you're only calling performSegue(withIdentifier:) in viewDidAppear. If you want the segue to occur after signing in, then you need to include it there.
let facebookLogin = FBSDKLoginManager()
facebookLogin.logIn(withReadPermissions: ["public_profile", "email"], from: self, handler: {
(facebookResult, facebookError) -> Void in
if facebookError != nil {
print("Facebook login failed. Error \(String(describing: facebookError))")
} else if (facebookResult?.isCancelled)! {
print("Facebook login was cancelled.")
} else {
let credential = FacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString)
Auth.auth().signIn(with: credential) { (user, error) in
if error != nil {
print("Login failed. \(String(describing: error))")
} else {
fbLoginSuccess = true
print("Logged in!")
if (facebookResult?.grantedPermissions.contains("email"))! {
}
performSegue(withIdentifier: "Home", sender: self)
}
}
}
})

Swift Firebase Facebook login dialog box pop up 2 times

I have a facebook login which using firebase to authenticate the process.
However, after I input my login detail and press confirm. It will back to the login page and pop up the facebook login page again. Then I press confirm again. It will display "User Cancel Login".
I am not sure why does it happen 2 times also when i click the confirm button it will display "User Cancel Login"
func loginButton(FbLoginBtn: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
let FbloginManager = FBSDKLoginManager()
FbloginManager.logInWithReadPermissions(["email","public_profile", "user_location", "user_hometown","user_friends"],fromViewController: self, handler: { (result, error) in
if let error = error {
print(error.localizedDescription)
return
}else if(result.isCancelled) {
print("User Cancel Login")
}else{
let credential = FIRFacebookAuthProvider.credentialWithAccessToken(FBSDKAccessToken.currentAccessToken().tokenString)
print("User\(self.user?.displayName) login successful")
AppState.instance.signedIn = true
if AppState.instance.signedIn == false{
self.firebaseLogin(credential)
//self.createFirebaseUser()
self.performSegueWithIdentifier(SEGUE_LOGIN, sender: nil)
}
}
})
}
For me this code work :
#IBAction func btnFBLoginPressed(sender: AnyObject) {
self.comeFromFB = true
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
var id:String = ""
var urlPhoto:String = ""
fbLoginManager.logInWithReadPermissions(["email"], fromViewController: self){ (result, error) -> Void in
if let error = error
{
print(error)
return
}
else
{
let fbloginresult : FBSDKLoginManagerLoginResult = result
if (!result.isCancelled)
{
if(fbloginresult.grantedPermissions.contains("email"))
{
if((FBSDKAccessToken.currentAccessToken()) != nil){
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).startWithCompletionHandler({ (connection, result, error) -> Void in
let bUserFacebookDict = result as! NSDictionary
id = bUserFacebookDict["id"]! as! String
urlPhoto = "https://graph.facebook.com/"+id+"/picture?width=500&height=500"
let credential = FIRFacebookAuthProvider.credentialWithAccessToken(FBSDKAccessToken.currentAccessToken().tokenString)
FIRAuth.auth()?.signInWithCredential(credential) { (user, error) in
self.currentUser.setCurrentUserState(user!.uid, _firstName: bUserFacebookDict["first_name"]! as! String, _name: bUserFacebookDict["last_name"]! as! String, _urlPhoto: urlPhoto, _email:bUserFacebookDict["email"]! as! String, _connected:true)
}
})
}
}
}
}
}
}
Then I add a listener in the ViewDidAppear method with perform segue after "connected" state.