I have a custom button for users to register with Facebook. However when I test it is shows that I have authorized the app, but it stays on the safari page and does not return to my app. Here is what my code looks like so far.
#IBAction func facebookButtonWasHit(sender: AnyObject) {
let permissions = [ "public_profile", "email" ]
FBSDKLoginManager().logInWithReadPermissions(permissions, fromViewController: nil, handler: { (result, error) in
if error != nil {
self.presentViewController(UIAlertController(title: "Whoops!", message: error!.localizedDescription), animated: true, completion: nil)
}
else if result.isCancelled {
self.presentViewController(UIAlertController(title: "Whoops!", message: "We couldn't access facebook! Did you hit cancel?"), animated: true, completion: nil)
}
else {
if((FBSDKAccessToken.currentAccessToken()) == nil){
FBSDKGraphRequest(graphPath: "me", parameters:["fields":"email,name"]).startWithCompletionHandler({ (connection, result, error) in
if error != nil {
self.presentViewController(UIAlertController(title: "Whoops!", message: error!.localizedDescription), animated: true, completion: nil)
} else {
if let loginResult = result as? Dictionary<String,AnyObject> {
dispatch_async(dispatch_get_main_queue(), {
if let emailID = loginResult["email"] as? String{
self.emailTextField.text = emailID
}
self.nameTextField.text = loginResult["name"] as? String
let userID = loginResult["id"] as! String
let facebookProfileUrl = "http://graph.facebook.com/\(userID)/picture?type=large"
let url = NSURL(string:facebookProfileUrl)
self.picChanged = true
self.downloadImage(url!)
})
}
}
})
}
}
})
}
Related
Hi everyone I'm using DTSocialMediaLogin for the social media logins (Facebook, Google, Twitter) all of them works except Facebook. When ı try to Facebook login, it's not logged because "email" is not getting.
Here is the result of the coming data
There is no email on coming data as you can see on the image.
Here is the permission section:
func login(from viewController: UIViewController, done: #escaping(_ status: Bool, _ message: String, _ user: DTFacebookUser?) -> Void) {
let login = FBSDKLoginKit.LoginManager()
login.defaultAudience = .everyone
if scopes.count == 0 {
scopes = ["public_profile", "email"]
}
login.logIn(permissions: scopes, from: viewController) { (result, error) in
DispatchQueue.main.async {
if error != nil {
done(false, error!.localizedDescription, nil)
}
else if let result = result {
if result.isCancelled && result.declinedPermissions.count > 0 {
done(false, "facebook_cancel_declined", nil)
}
else {
//let userID = result.token?.userID
self.graph(str: "/me?fields=email,name", done: done)
}
}
}
}
}
Here is the login action:
#objc func actionFacebook() {
self.socialLogin.login(with: .Facebook, from: self) { (error, user) in
// user.name, user.email, user.id, user.profileImageURL
if user == nil {
return
}
var text = "FACEBOOK LOGIN\n"
text = "\(text)\nFull Name: \(user!.name)"
text = "\(text)\nEmail: \(user!.email)"
text = "\(text)\nUser ID: \(user!.id)"
text = "\(text)\nImage: \(user!.profileImageURL)"
print(text)
if user!.email == "" {
return
}
if user!.name == "" {
return
}
if self.passSignType == "Login"
{
ServiceManager.shared.Authenticate(Phone: "", MobilePin: "", Email: user!.email, Password: "", ProviderName: "Facebook", ProviderId: user!.id, ProviderToken: "", Name: user!.name, Username: user!.name, ActionType: "Login", callbackSuccess: { (response) in
HUD.flash(.label("hudAccountLogin".localized()), delay: 1.0) { _ in
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.dismiss(animated: true) {
}
NotificationCenter.default.post(name: Notification.Name(rawValue: "UserLogged"), object: nil)
}
}) { (response) in
HUD.flash(.label("hudFailed".localized()), delay: 1.0) { _ in
}
}
}
}
I cant solve the problem Email is not coming on Facebook...
post logIn(permission ..) API use GraphRequestConnection to get the user info.
func getFbUserProfileInfo() {
let connection = GraphRequestConnection()
connection.add(GraphRequest(graphPath: "/me",
parameters: ["fields" : "id,first_name,last_name,email,name"],
tokenString: AccessToken.current?.tokenString,
version: Settings.defaultGraphAPIVersion,
httpMethod: .get)) { (connection, values, error) in
if let res = values {
if let response = res as? [String: Any] {
let username = response["name"]
let email = response["email"]
}
}
}
connection.start()
}
I'm trying to log users into into my app using Facebook and then save the users into my Cloud Firestore. I'm just not too sure how to go about it. This is the code I have now
#IBAction func buttTapped(_ sender: Any) {
let fbLoginManager = LoginManager()
fbLoginManager.logIn(permissions: ["public_profile", "email"], from: self) { (result, error) in
if let error = error {
print("Failed to login: \(error.localizedDescription)")
return
}
guard let accessToken = AccessToken.current else {
print("Failed to get access token")
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 {
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
}
// Present the main view
self.dismiss(animated: true, completion: nil)
})
}
}//
What code do I have to add to grab certain values like email and name and save it to Cloud Firestore the image below is an example for what I have using email signup
You just done the Facebook authentication and get the access token. To get user public info you need a graph request. The full Facebook Authentication and Graph request code will be like
func facebookLogin(){
let loginManager = LoginManager()
loginManager.logIn(permissions: [.publicProfile, .email], viewController: self) { loginResult in
switch loginResult {
case .failed(let error):
print(error)
case .cancelled:
print("User cancelled login.")
case .success(let grantedPermissions, let declinedPermissions, let accessToken):
print("Logged in!")
self.fetchUserProfile()
}
}
}
func fetchUserProfile() {
let graphRequest : GraphRequest = GraphRequest(graphPath: "me", parameters: ["fields":"id, email, name, picture.width(480).height(480)"])
graphRequest.start(completionHandler: { (connection, result, error) -> Void in
if ((error) != nil)
{
print("Error took place: \(error ?? "" as! Error)")
}
else
{
let result = result as! Dictionary<String, Any>
let picture = result["picture"] as! Dictionary<String, Any>
let dataObj = picture["data"] as! Dictionary<String,Any>
var emailValue = result["email"] as! String?
if emailValue == nil {
emailValue = ""
}
let name = result["name"] as? String
let id = result["id"] as? String
let imageUrl = result["url"] as? String
// Update data to firestore
}
})
}
Hope you understand.
I am trying to setup a method to allow users to login to their Firebase accounts using Facebook. If it is a first time user creating an account everything works fine, but if a user made an account before and is trying to login in to their account is where the trouble begins. When the code
FIRAuth.auth()?.signIn(with: credential, completion: {(user, error)
runs I get the error saying that the email is already in use, even though it is the account in which they are trying to sign in for.
My entire code is here:
func handleCustomFBLogin() {
FBSDKLoginManager().logIn(withReadPermissions: ["email"], from: self) { (result, err) in
if err != nil {
print("Error loggin in is \(err)")
//self.facebookanimateIn()
} else if (result?.isCancelled)!{
print("The user cancelled loggin in ")
} else {
let credential = FIRFacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString)
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, email"])
graphRequest.start(completionHandler: { (connection, result, error) -> Void in
if ((error) != nil) {
print("Error: \(error)")
} else {
let data:[String:AnyObject] = result as! [String: AnyObject]
let facebookName:NSString = data["name"] as! NSString
let facebookEmail = data["email"] as Any
let userId = data["id"] as! NSString
let facebookProfileUrl = "http://graph.facebook.com/\(userId)/picture?type=large"
let facebookAge = data["age_range"] as Any
let password = "needToPutRandomizedPasswordInHere" as String
FIRAuth.auth()?.createUser(withEmail: facebookEmail as! String, password: password, completion: {result, error in
if error != nil{
//user has account, they just need to sign in
FIRAuth.auth()?.signIn(with: credential, completion: {(user, error) in
if error != nil{
print(error.debugDescription)
return
}
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let vc: UINavigationController = storyboard.instantiateViewController(withIdentifier: "checker") as! UINavigationController
self.present(vc, animated: true, completion: nil)
// ref.removeObserver(withHandle: handle)
})
} else {
//user does not have an account and they need to create one
guard let uid = result?.uid else{
return
}
print("user created as \(uid)")
let val = "0"
let number = (val as NSString).integerValue
let ref = FIRDatabase.database().reference()
let usersReference = ref.child("Users").child(uid)
let values = [""] as [String : Any];
usersReference.updateChildValues(values, withCompletionBlock: { (err,ref) in
if err != nil {
print(err.debugDescription)
return}})
print("Save the user successfully into Firebase database")
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let vc: UINavigationController = storyboard.instantiateViewController(withIdentifier: "checker") as! UINavigationController
self.present(vc, animated: true, completion: nil)
}
})
}
})
}
}
}
once you have created the user, all you need is the login step
FIRAuth.auth()?.signIn(withEmail: email, password: password, completion: { (user, error) in
if error != nil {
// handle errors
} else {
// continue with login process
}
})
I am having some trouble in my code. I gave the permission of "user_photos" in "loginwithreadpermission" but still not getting the users album. I also tried this "fbuserid/albums" but this is also not working for me. Please help me what I am doing wrong.
This is my Login Code:
#IBAction func facebookLogin(sender: AnyObject)
{
let facebookLogin = FBSDKLoginManager()
facebookLogin.logOut()
facebookLogin.logInWithReadPermissions(["email" , "user_photos"], fromViewController: nil) { (facebookResult, facebookError) in
if facebookError != nil {
print("Login Failed. Error: \(facebookError)")
}
else {
if !(facebookResult.isCancelled)
{
let accessToken = FBSDKAccessToken.currentAccessToken().tokenString
if accessToken != nil
{
token = accessToken
let credential = FIRFacebookAuthProvider.credentialWithAccessToken(accessToken)
print("1")
FIRAuth.auth()?.signInWithCredential(credential)
{
(user, error) in
if error != nil
{
print("Error Firebase: \(error)")
}
else
{
if self.userEmails.contains(user!.email!)
{
print("User Already Exist")
NSUserDefaults.standardUserDefaults().setValue(user?.uid, forKey: KEY_UID)
USER_UID = (user?.uid)!
print("id:\(USER_UID)")
LOGIN_FLAG = 1
FaceBookFlag = 1
self.performSegueWithIdentifier("fbLogin", sender: nil)
}
else if user!.email != nil
{
print("Creating a User Data in FB")
var request = FBSDKGraphRequest(graphPath:"me", parameters: ["fields":"email,first_name,age_range"]);
request.startWithCompletionHandler({ (connection, result, error) in
if error == nil
{
print("res: \(result)")
if let dob = result.valueForKey("age_range") as? [String: AnyObject]
{
print("dd: \(dob["min"]!)")
self.dateOfBirth = String(dob["min"]!)
print("dob: \(dob) , date: \(self.dateOfBirth)")
print(" date: \(self.dateOfBirth!)")
}
}
else
{
print("error:: \(error)")
}
let displayName = user?.displayName!.componentsSeparatedByString(" ")
let firstName = displayName![0]
let lastName = displayName![1]
print("url: \(user?.photoURL)")
let profilePicUrl = user?.photoURL
let picture = String(profilePicUrl!)
let userEmail = user!.email!
let _user = ["username": "\(firstName+lastName)","emailAddress": "\(userEmail)", "dateOfBirth": "\(self.dateOfBirth!)"]
ref.child("users").child(user!.uid).setValue(_user)
ref.child("users").child(user!.uid).child("images").setValue([picture])
NSUserDefaults.standardUserDefaults().setValue(user?.uid, forKey: KEY_UID)
USER_UID = (user?.uid)!
LOGIN_FLAG = 1
FaceBookFlag = 1
//Segue to reveal view controller
self.performSegueWithIdentifier("fbLogin", sender: nil)
})
}
}
}
}
}
}
}
}
And This is my Code where I am requesting to give me the albums of current user :
func getAlbums()
{
//for sake of running i hardcoded the FBuserId.
let fbid = "758111074330935"
//169682503464671/photos
let graphRequest = FBSDKGraphRequest(graphPath: "/\(fbid)/albums", parameters: ["fields":"photos,picture"] , HTTPMethod: "GET")
graphRequest.startWithCompletionHandler { (connection, result, error) in
if error != nil
{
print(error)
}
else
{
print("rr:\(result)")
let value = result.valueForKey("data")
print("value:\(value) ... \(result["data"])")
if let graphData = result.valueForKey("data") as? [AnyObject]
{
print("array of Any")
for obj in graphData
{
print("id: \(obj.valueForKey("id")!)")
let id = String(obj.valueForKey("id")!)
self.albumsId.append(id)
//Also save the album link here to.
}
}
}
You have a wrong set of fields for this type of request.
Check this doc to verify the fields that are available: https://developers.facebook.com/docs/graph-api/reference/v2.7/album
In particular, I'm getting the following error (which is self-explained):
{
"error": {
"message": "(#100) Unknown fields: email,first_name.",
"type": "OAuthException",
"code": 100,
"fbtrace_id": "G0POfi9dWkb"
}
}
I trying to capture the results of user Facebook details after they have login, instantiate a view controller and show the controller.
However the weird thing is that when I have that instantiateViewControllerWithIdentifier code inside my getFBUserData() method, it exits after FBSDKGraphRequest. When I remove that chunk of commented codes, it executes the storing of variables perfectly.
I've also tried placing the instantiateViewControllerWithIdentifier code after self.getFBUserData(), and it also doesn't store the variables again.
I need help with storing the variables, and then execute the instantiateViewControllerWithIdentifier displaying the stored variables.
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!){
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.loginBehavior = FBSDKLoginBehavior.Web
fbLoginManager.logInWithReadPermissions(["email"], fromViewController: self, handler: { (result, error) -> Void in
if (error == nil){
let fbloginresult : FBSDKLoginManagerLoginResult = result
if fbloginresult.grantedPermissions != nil {
if(fbloginresult.grantedPermissions.contains("email"))
{
self.getFBUserData()
}
}
return;
}
else {
let alertController = UIAlertController(title: "Limited Connectivity", message: "We're unable to log you in. Please check your network connectivity.", preferredStyle: .Alert)
let action1 = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default){
UIAlertAction in
}
alertController.addAction(action1)
self.presentViewController(alertController, animated: true, completion: nil)
fbLoginManager.logOut()
return;
}
})
}
func getFBUserData(){
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
if (error == nil){
self.strName = (result.objectForKey("name") as? String)!
self.strID = (result.objectForKey("id") as? String)!
self.strEmail = (result.objectForKey("email") as? String)!
let strPictureURL: String = (result.objectForKey("picture")?.objectForKey("data")?.objectForKey("url") as? String)!
self.fbProfileImage = UIImage(data: NSData(contentsOfURL: NSURL(string: strPictureURL)!)!)!
/*
let displayViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ChooseNameViewController") as! ChooseNameViewController
displayViewController.email = self.strEmail
displayViewController.id = self.strID
displayViewController.name = self.strName
displayViewController.profilePic = self.fbProfileImage
self.navigationController?.pushViewController(displayViewController, animated: true)
*/
}
else{
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.logOut()
return
}
})
}
}
1) As this method FBSDKGraphRequest make asych call on back ground thread.You need to do UI related work on main thread.
dispatch_async(dispatch_get_main_queue(), ^{
let displayViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ChooseNameViewController") as! ChooseNameViewController
displayViewController.email = self.strEmail
displayViewController.id = self.strID
displayViewController.name = self.strName
displayViewController.profilePic = self.fbProfileImage
self.navigationController?.pushViewController(displayViewController, animated: true)
});