Integrating Facebook Login with Parse Swift 3 - swift

In my Xcode Project I already have a sign in feature that uses a user's username and password they created. Now I want to integrate a Facebook login in the project, but I am not completely sure how to do this. When someone makes an account through they way I have it now, they make and save a username and a password which can then be used in with PFUser.logIn(withUsername: ..., password: ...) for whenever they want to sign in again.
But with Facebook, I do not know what unique identifier I am suppose to save their account with. I know there is a Facebook id that I can extract, but how do I login the user in after I get this? Like I said before I currently use PFUser.logIn(withUsername: ..., password: ...) to log the users' in then I just use PFUser.current()?.username to get all data related to that user. I heard that I am suppose to use PFFacebookUtils.logInInBackground for this, but I already tried implementing it but when I press the "Continue with Facebook button", the app crashes (I screenshot error and placed it at bottom). I have copied my code of what I have so far. How do I integrate a signup with Facebook feature that will allow me to save a users Facebook id and what method do I use to sign the user in (i.e. PFFacebookUtils.logInInBackground)? Here's my code so far:
#IBOutlet var facebookSignUpButton: FBSDKLoginButton!
var fullnameFB = String()
var idFB = String()
var emailFB = String()
var isFBSignUp = Bool()
override func viewDidLoad() {
super.viewDidLoad()
signUpWithFacebook()
}
func signUpWithFacebook() {
facebookSignUpButton.readPermissions = ["email", "public_profile"]
facebookSignUpButton.delegate = self
self.view.addSubview(facebookSignUpButton)
}
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
if error != nil { //if theres an error
print(error)
} else if result.isCancelled { // if user cancels the sign up request
print("user cancelled login")
} else {
PFFacebookUtils.logInInBackground(with: result!.token!) { (user, error) in
if error == nil {
if let user = user {
if user.isNew {
print("User signed up and logged in through Facebook!")
} else {
print("User logged in through Facebook!")
}
if result.grantedPermissions.contains("email") {
if let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "email, name"]) {
graphRequest.start(completionHandler: { (connection, result, error) in
if error != nil {
print(error?.localizedDescription ?? String())
} else {
if let userDetails = result as? [String: String]{
print(userDetails)
self.fullnameFB = userDetails["name"]!
self.idFB = userDetails["id"]!
self.emailFB = userDetails["email"]!
self.isFBSignUp = true
}
}
})
}
} else {
print("didnt get email")
self.createAlert(title: "Facebook Sign Up", message: "To signup with Facebook, we need your email address")
}
} else {
print("Error while trying to login using Facebook: \(error?.localizedDescription ?? "---")")
}
} else {
print(error?.localizedDescription ?? String())
}
}
}
}
Console output:
2017-08-12 14:14:33.223472-0700 Project[2423:1001235] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'You must initialize PFFacebookUtils with a call to +initializeFacebookWithApplicationLaunchOptions'
*** First throw call stack:
(0x188042fe0 0x186aa4538 0x188042f28 0x100b8f934 0x100b90020 0x100b9032c 0x10019eee8 0x1001a0a64 0x100867598 0x10086e998 0x10086e4f0 0x100871a94 0x18b3610d4 0x101521a10 0x101526b78 0x187ff10c8 0x187feece4 0x187f1eda4 0x189989074 0x18e1dd364 0x1001ec288 0x186f2d59c)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

As stated in the docs, you need to initialize PFFacebookUtils before using it, like so:
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
// CODE...
PFFacebookUtils.initializeFacebook(applicationLaunchOptions: launchOptions)
}
Important: Must be done after Parse setup (Parse.initialize...).

Related

Google Classroom API integration with swift

I want to link my iOS app with Google Classroom on swift. My current goal is to be able to get a list of all the courses I am enrolled in.
Here is the code I am currently using
func googleClassroomList() {
//let sharedInstance = GIDSignIn.sharedInstance()
//let handler = sharedInstance
googleClassroomService.apiKey = "AIzaSyBOGamjhRuu45T2jT7Qa3LmtntSwgIxeqo"
let query = GTLRClassroomQuery_CoursesList.query()
query.pageSize = 1000
let classQuery = googleClassroomService.executeQuery(query, completionHandler: { ticket , fileList, error in
if error != nil {
let message = "Error: \(error?.localizedDescription ?? "")"
print(message)
} else {
if let list = fileList as? GTLRClassroomQuery_CoursesList {
self.fileList = list
print("List: \(list)")
}
else {
print("Error: response is not a file list")
}
}
}
)
}
Here is the error message:
Error: Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.
I don't understand where I attach the OAuth access token, I tried putting it under apiKey but I don't really understand what I am supposed to do. For reference, I am using this auth scope. "https://www.googleapis.com/auth/classroom.courses"
First you have to sign-in using Google, and Google will manage the OAuth 2.0 token for you.
Here you have the instructions:
https://developers.google.com/identity/sign-in/ios/sign-in?ver=swift
Also make sure to set the service.authorizer property when you are actually signed in:
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!,
withError error: Error!) {
guard let user = user else {
return
}
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.setLoggedOut(loggedOut: false)
self.myClassroom.service.authorizer = user.authentication.fetcherAuthorizer()
self.showClassroomClasses()
}

Firebase Login Persistence Swift

I'm using Firebase to handle my user register and login for my app. But if I log in, and then close my app entirely - the user is forced to re-log in. I'd like to keep the user logged in unless they click "Log out"
My login code is this:
Auth.auth().signIn(withEmail: email, password: password, completion: {(user, error) in
if let firebaseError = error {
print(firebaseError.localizedDescription)
return
}
self.presentTabBar()
})
}
}
How do I keep this user logged in unless specifically told to logout?
Here's a handy full example for 2020:
Anywhere in your iOS+Firebase app, you can simply say:
guard let uid = Auth.auth().currentUser?.uid else {
return print("no current user!")
}
Thus, on the launch screen of your app, simply:
import UIKit
import Firebase
import FirebaseUI
class ViewController: UIViewController, FUIAuthDelegate {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
guard let uid = Auth.auth().currentUser?.uid else {
return print("no current user, hence AuthUI flow...")
basicAuthUIFlow()
}
print("User .. \(Auth.auth().currentUser?.displayName)")
continueWhenUserPresent()
}
It's that easy. So then as usual ...
private func basicAuthUIFlow() {
let authUI = FUIAuth.defaultAuthUI()
authUI?.delegate = self
let pp: [FUIAuthProvider] = [ FUIGoogleAuth() ]
authUI?.providers = pp
if let authVC = authUI?.authViewController() {
present(authVC, animated: true)
}
}
func authUI(_ authUI: FUIAuth,
didSignInWith authDataResult: AuthDataResult?,url: URL?, error: Error?) {
let u = authDataResult?.user
print("Successful login via authUI \(String(describing: u?.displayName))")
continueWhenUserPresent()
}
private func continueWhenUserPresent() {
.. pushViewController .. your first screen
}
Check if the user is logged in or not:
if Auth.auth().currentUser != nil {
// User is signed in.
// ...
} else {
// No user is signed in.
// ...
}
if the user is logged in, then go the Home ViewController. This way when he opens the app again he will go to the Home ViewController unless he sign outsFIRAuth.auth().signOut()
For more info check this: https://firebase.google.com/docs/auth/ios/manage-users
For keep user login you need to check currentUser Auth session, If it's not nil then you can redirect user to Home screen.
Call "setRootViewController" method from didFinishLaunchingWithOptions, just after FirebaseApp.configure() code
Swift 4
func setRootViewController() {
if Auth.auth().currentUser != nil {
// Set Your home view controller Here as root View Controller
self.presentTabBar()
} else {
// Set you login view controller here as root view controller
}
}

sign out for Facebook and Google

I am trying to implement a sign out button that depending on the current user type (Facebook vs Google) it will sign out based on which type of current user is logged in. I am able to login with different accounts but want the sign out function to be conditional based on what type of account is logged in...thanks in advance!
// sign out functions
func handleSignOut() {
// facebook sign out
UserDefaults.standard.setIsLoggedIn(value: false)
FBSDKLoginManager().logOut()
print("did log out of facebook...")
// google signout
let firebaseAuth = FIRAuth.auth()
do {
try firebaseAuth?.signOut()
} catch let signOutError as NSError {
print ("Error signing out: %#", signOutError)
}
let loginController = LoginController()
present(loginController, animated: true, completion: nil)
}
func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) {
do {
try FIRAuth.auth()!.signOut()
} catch let logoutError {
print(logoutError)
}
}
Try storing in the UserDefaults which account your user is signed in as (e.g. store a "account" key with a string value "google" or "facebook").
Then, in your sign-out method, handleSignOut() {...}, test for that value, i.e.
let at = (UserDefaults.getAccountType())
if at == "google" {
handleGoogle()
} else if at == "facebook" {
handleFacebook()
}
*Implement your own accessor for UserDefaults.getAccountType

Unable to pass Facebook User properties to Firebase FIRAuth in Swift 3

I'm using the following function to login a User with a Facebook Token and the Firebase FIRAuth function. There is no error and no print of email property. As if the function wouldn't be called.
var login = FBSDKLoginManager()
#IBOutlet weak var fbBtnPressed: UIButton!
#IBAction func fbBtnPressed(_ sender: AnyObject) {
login.logIn(withReadPermissions: ["public_profile", "email", "user_friends"], from: self) { (FBSDKLoginManagerLoginResult, Error) in
if Error != nil {
print("The login with Facebook don't working. Erro: \(Error)")
} else {
let accessToken = FBSDKAccessToken.current().tokenString
print("Login with Facebook ok. \(accessToken)")
let credential = FIRFacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString)
FIRAuth.auth()?.signIn(with: credential) { (email, error) in
if (error != nil) {
print("The login in the Firebase broke \(error)")
} else {
print("Login in the Firebase ok \(email)")
}
}
}
}
}
After a lot of research, it seems to be a change in Swift3 in combination with the Keychain swap.
You have to enable the Keychange Sharing in your project under capabilities.

Swift 2.0 working Facebook custom login button

I beg all of thee. I searched everywhere but i can't find working swift 2.0 code for Facebook custom login button with returning Access Token. My code simply don't work. (token is not returning Facebook token)
Considering that you have done all the setup as described by the Facebook developer page, you need to do the following in your login view controller:
// Import the following on top below "import UIKit" in your login view controller
import FBSDKCoreKit
import FBSDKLoginKit
// This is your action code for your custom login button for login using facebook in Swift
#IBAction func fbLoginBtn(sender: AnyObject) {
let permisions = ["public_profile", "email"]
PFFacebookUtils.logInInBackgroundWithReadPermissions(permisions) {
(user: PFUser?, error: NSError?) -> Void in
if let error = error {
print(error)
} else {
if let user = user {
print(user)
// "yourSegue" below will be the segue identifier for your new view.
self.performSegueWithIdentifier("yourSegue", sender: self)
}
}
}
}
In case you have not setup your app at Facebook developer, please following the simple steps as mentioned in Facebook Developer Page.
1 - Add a normal button in your view then add the FB login class "FBSDKLoginButton"
2 - Declare your button in your ViewController
#IBOutlet weak var FBLoginButton: FBSDKLoginButton!
3 - Add in your ViewDidload methode
if (FBSDKAccessToken.currentAccessToken() != nil)
{
// User is already logged in, do work such as go to next view controller.
}
else
{
self.FBLoginButton.delegate = self
FBLoginButton.readPermissions = ["public_profile", "email", "user_friends"]
}
4-Add Delegate Login and logout button funcutions
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
loginButton.readPermissions = ["public_profile", "email", "user_friends"]
let fbAccessToken = FBSDKAccessToken.currentAccessToken().tokenString
FBSDKGraphRequest(graphPath: "me?fields=id,name,email,gender,first_name,last_name,middle_name,birthday&access_token=\(fbAccessToken)", parameters: nil).startWithCompletionHandler({ (connection, result, error) in
if ((error) != nil) {
// Process error
print("Error: \(error)")
} else {
print("fetched user: \(result)")
}
})
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
print("User Logged Out")
}