iOS Facebook Login in swift - ios

I am trying to implement the exact same code mentioned in the docs, so when I get the granted permissions from the user in the below way
let loginManager = LoginManager()
loginManager.logIn(
permissions: [.email , .publicProfile],
viewController: self
) { result in
self.loginManagerDidComplete(result)
}
how can I decode the publicProfile to get all the inside information..
I know that there are other ways to get these details, but can I get a solution only with this code.
Can we get the details from the below code
switch result {
case .cancelled:
print("User cancelled login.")
case .failed(let error):
print("Login failed with error \(error)")
case .success(let grantedPermissions, _, _):
print("Login succeeded with granted permissions: \(grantedPermissions)")
print(grantedPermissions.map { $0.name },"test")
for perm in grantedPermissions {
print(perm.name,perm.hashValue)
}
}

In your completion handler for your login permissions, make a graph request to obtain the profile information. Your login function only asks for permissions and the subsequent call will return the information you require.
switch result {
case .failed(let error):
print(error)
case .cancelled:
print("Cancelled")
case .success(_,_,_):
let params = ["fields" : "id, email, first_name, last_name"]
let graphRequest = GraphRequest(graphPath: "/me", parameters: params)
graphRequest.start(completionHandler: { ( connection, result, error) in
if let error = error as Error? {
print(error.localizedDescription)
}
if let result = result as? [String: String],
let id = result["id"],
let firstName = result["first_name"],
let lastName = result["last_name"],
let email = result["email"]
})
}

Related

Swift - AWS Cognito using Amplify - How to get tokens after log in in swift?

Im struggling getting user token after successfully logging in.
The only thing I got is the current userId and username, but I cant get in any point the user tokens.
func login(userData: RegistrationFields) {
_ = Amplify.Auth.signIn(username: userData.email.data, password: userData.password.data) {
[weak self] result in
switch result {
case .success(let signInResult):
if signInResult.isSignedIn {
self?.getCurrentUser()
debugPrint("Sign in succeeded")
}
case .failure(let error):
debugPrint("Sign in failed \(error)")
self?.authStateDelegate?.authState(state: .error(error: error))
}
}
}
func getCurrentUser() {
guard let user = Amplify.Auth.getCurrentUser() else {return}
self.authStateDelegate?.authState(state: .session(user: user))
}
In success callback of your sign in you can do next:
Amplify.Auth.fetchAuthSession { result in
switch result {
case .success(let session):
if session.isSignedIn {
do {
if let cognitoTokenProvider = session as? AuthCognitoTokensProvider {
let tokens = try cognitoTokenProvider.getCognitoTokens().get()
//tokens.idToken - is ID token. Access and refresh tokens also can be found here
}
} catch {
//error
}
} else {
//Not Logged in
}
case .failure(let error):
print("Fetch session failed with error \(error)")
}
}
This is what worked for me:
First, import AmplifyPlugins
import AmplifyPlugins
And
_ = Amplify.Auth.fetchAuthSession { result in
switch result {
case .success(let session):
if(session.isSignedIn) {
if let sess = session as? AWSAuthCognitoSession {
let result = sess.getCognitoTokens()
switch result {
case .success(let tokens):
let accessToken = tokens.accessToken
let idToken = tokens.idToken
let refreshToken = tokens.refreshToken
case .failure(let error):
print("Fetch user tokens failed with error \(error)")
}
}
}
case .failure(let error):
print("Fetch session failed with error \(error)")
}
}

Swift - Getting error from facebook login

just to start off with I have looked at many examples but can't seem to find a solution. Well I thought I did but it doesn't seem to work.
What I'm trying to do is use the Firebase auth login method for facebook, which works by the way. My issue is I want to link the password auth credentials and facebook auth credentials when the facebook method throws the error that the email/credentials already exist. I read here that I could use error.email but it doesn't give me the option to access the email.error. I might be missing something and I have spent a lot of time trying to figure it out.
Here is my code:
func signInFacebookUser() {
let fbLoginManager = FBSDKLoginManager()
fbLoginManager.logIn(withReadPermissions: ["public_profile", "email"], from: self) { (result, error) in
if let error = error {
self.errorMessagePopUp(title: "Failed to login", message: error)
return
}
guard let accessToken = FBSDKAccessToken.current() else {
print("Failed to get access token")
return
}
let credential = FacebookAuthProvider.credential(withAccessToken: accessToken.tokenString)
Auth.auth().signIn(with: credential, completion: { (user, error) in
if let error = error {
let errCode = AuthErrorCode(rawValue: error._code)!
switch errCode {
case .accountExistsWithDifferentCredential:
// somehow obtain email right here.
self.showSigninForm(attributes: self.attributes(), style: .light)
return
default:
return
}
}
self.performSegue(withIdentifier: "signInBtnPressed", sender: nil)
})
}
}
This Works for me Swift4
#objc func loginButtonClicked() {
var alertController = UIAlertController()
let loginManager = LoginManager()
loginManager.logIn(readPermissions: [ReadPermission.email], >viewController: self, completion: {loginResult in
switch loginResult {
case .failed(let error):
print(error)
case .cancelled:
print("User cancelled login.")
case .success(_, _, let accessToken):
print(accessToken)
}
})
}
func getDataUser() {
let request = GraphRequest(graphPath: "me?fields=first_name,last_name,email",
parameters:[:],
httpMethod: .GET)
request.start { httpResponse, result in
switch result {
case .success(let response): do {
print("Graph Request Succeeded: \(response)")
let dicval = response.dictionaryValue
let email = dicval?.keys
print("Graph Request Succeeded: \(String(describing: email))")
}
case .failed(let error):
print("Graph Request Failed: \(error)")
}
}
}
}
Try this code
#IBAction func facebookLoginButtonTapped(_ sender: UIButton) {
if Utility.checkInternet(){
let fbLoginManager: FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.logIn(withReadPermissions: ["email", "public_profile"], from: self) { (result, error) in
if (error == nil){
let fbLoginResult: FBSDKLoginManagerLoginResult = result!
if fbLoginResult.grantedPermissions != nil {
if(fbLoginResult.grantedPermissions.contains("email")){
self.facebookLogin()
}
}
}
}
}
else{
Utility.showAlert("Connection Error!", message: "Please check internet connection and retry.", viewController: (self.window?.rootViewController)!)
}
}
func facebookLogin() {
Utility.showProgress("")
if((FBSDKAccessToken.current()) != nil) {
FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"id, name, first_name, last_name, picture.type(large), email "]).start(completionHandler: { (connection, result, error) in
if result == nil {
}
else{
self.userResults = result as! [String : AnyObject]
self.email = (self.userResults["email"] as? String) ?? ""
if (self.email != "") {
}
else{
Utility.showAlert("Login Faild", message: error?.localizedDescription, viewController: self)
}
}
})
}
}

Posting as a Facebook Page using Swift

I would like my app to post to my Facebook business page. I've can get it to post to my person Facebook feed, and I've also gotten it to post to my business page, posting as my personal user account. However, I'd like it to post to the main business page feed, as the business account.
As shown here in Facebook's documentation:
https://developers.facebook.com/docs/pages/publishing
Here's is what I've tried. The following code posts to the page using my personal user account.
I was trying to replace the accessToken parameter in the POST GraphRequest with the pageAccessToken... but couldn't get it to work.
var pageAccessToken : GraphResponse?
func getPageAccessToken() {
let connection = GraphRequestConnection()
connection.add(GraphRequest(graphPath: "/\(pageID)?fields=access_token")) { httpResponse, result in
switch result {
case .success(let response):
print("Graph Request Success: \(response)")
self.pageAccessToken = response
case .failed(let error):
print("Graph Request Fail: \(error)")
}
}
connection.start()
}
func requestPublishPermissions() {
let loginManager = LoginManager()
loginManager.logIn(publishPermissions: [ .managePages, .publishPages], 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("grantedPermissions = \(grantedPermissions) \n" +
"declinedPermissions = \(declinedPermissions) \n" +
"accessToken = \(accessToken)")
}
}
}
func postMessage() {
let requestPage : GraphRequest = GraphRequest(graphPath: "\(pageID)/feed", parameters: ["message" : "Hello Page!"], accessToken: AccessToken.current, httpMethod: .POST, apiVersion: .defaultVersion)
requestPage.start({ (connection, result) -> Void in
print("RESULT = \(result)")
})
}
Thank you for any advice tips you can give!
swift 5 update
let pageID = "yourFBPage"
var pageAccessToken : String?
func getPageAccessToken() {
let connection = GraphRequestConnection()
connection.add(GraphRequest(graphPath: "\(pageID)", parameters: ["fields": "access_token"])) { httpResponse, result,error in
if let error = error {
print(error.localizedDescription)
} else {
let info = result as! [String : AnyObject]
if info["access_token"] as? String != nil {
self.pageAccessToken = info["access_token"] as? String
}
//print(result)
self.postMessage()
}
}
connection.start()
}
func postMessage() {
let requestPage : GraphRequest = GraphRequest(graphPath: "\(pageID)/feed", parameters: ["message" : "Hello Page!"], tokenString: self.pageAccessToken, version: nil , httpMethod: .post )
requestPage.start(completionHandler: { (connection, result, error) -> Void in
if let error = error {
print(error.localizedDescription)
} else {
//print("RESULT = \(result)")
}
})
}
I eventually got it working on my own. I'll share the answer, for those trying to do the same thing.
To post a simple text message to a page on Facebook:
let pageID = {Get Your Page ID On Facebook}
var pageAccessToken : AccessToken?
func requestPublishPermissions() {
let loginManager = LoginManager()
loginManager.logIn(publishPermissions: [ .managePages, .publishPages], 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("grantedPermissions = \(grantedPermissions) \n" +
"declinedPermissions = \(declinedPermissions) \n" +
"accessToken = \(accessToken)")
}
}
}
func getPageAccessToken() {
let connection = GraphRequestConnection()
connection.add(GraphRequest(graphPath: "/\(pageID)?fields=access_token")) { httpResponse, result in
switch result {
case .success(let response):
print("Graph Request Success: \(response)")
self.pageAccessToken = AccessToken.init(authenticationToken: response.dictionaryValue?["access_token"] as! String)
case .failed(let error):
print("Graph Request Fail: \(error)")
}
}
connection.start()
}
func postMessage() {
let requestPage : GraphRequest = GraphRequest(graphPath: "\(pageID)/feed", parameters: ["message" : "Hello Page!"], accessToken: self.pageAccessToken, httpMethod: .POST, apiVersion: .defaultVersion)
requestPage.start({ (connection, result) -> Void in
print("RESULT = \(result)")
})
}

me/albums return data nil facebook swift

i develop an app which take users albums and photos from facebook and show them in app.
I use custom button:
#objc func loginButtonClicked() {
let loginManager = LoginManager()
loginManager.logIn([ .publicProfile ], 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.getFBUserData()
}
}
}
if login success i call another method which request albums
func getFBUserData(){
if((FBSDKAccessToken.current()) != nil) {
FBSDKGraphRequest(graphPath: "/me/albums", parameters: nil).start(completionHandler: { (connection, result, error) -> Void in
if (error == nil) {
print("result = \(result)")
let responseDictionary = JSON(result)
if let data = responseDictionary["data"].array {
print("data result = \(data)")
print("----------")
for i in 0..<data.count {
print(data[i])
}
}
}
})
}
}
the printed result is
result = Optional({
data = (
);
})
if i will change request from "me/albums" to "me" i will take some info that won't be nil. Have anybody any ideas?

Facebook Graph Request is returning name but not email

I'm using the graph api to return my name and email from a Facebook login. This is the code I use - name comes back fine, but email is nil:
func getUserInfo() {
let params = ["fields" : "email, name"]
let graphRequest = GraphRequest(graphPath: "me", parameters: params)
graphRequest.start {
(urlResponse, requestResult) in
switch requestResult {
case .failed(let error):
print("error in graph request:", error)
break
case .success(let graphResponse):
if let responseDictionary = graphResponse.dictionaryValue {
print(responseDictionary)
if let name = responseDictionary["name"] {
self.nameLabel.text = "Logged in as: \n\(name)"
}
if let email = responseDictionary["email"] {
self.emailLabel.text = "Your email is: \n\(email)"
} else {
self.emailLabel.text = "Your email is: "
}
print(responseDictionary["name"])
print(responseDictionary["email"])
}
}
}
}
This is what prints to my console:
["id": 1653899307960705, "name": *my name removed for privacy*]
Optional(*my name removed for privacy*)
nil
I'm not sure if my code is wrong or it's just a bug - I specify both email and name as my parameters, but as you can see only the name comes back. Anyone know why this is happening?
Your code is absolutely correct, there few possibilities that facebook graph API not providing email:
Registered user has submitted its email but not validated
User has set email (visibility) as private/limited access to friends only (not public)
Check account setting of an/your account (email is valid & validated as well as it is public)
I thing you forgot to take email permission, so here I am sharing you code to take permission.
func fbLoginInitiate()
{
let loginManager = FBSDKLoginManager()
loginManager.logInWithReadPermissions(["public_profile", "email","user_friends"], handler: {(result:FBSDKLoginManagerLoginResult!, error:NSError!) -> Void in
if (error != nil) {
// Process error
self.removeFbData()
} else if result.isCancelled {
// User Cancellation
self.removeFbData()
} else {
//Success
if result.grantedPermissions.contains("email") && result.grantedPermissions.contains("public_profile") && result.grantedPermissions.contains("user_friends"){
//Here you need to call your function for graphRequest
self.getUserInfo()
} else {
//Handle error
}
}
})
}
func removeFbData()
{
//Remove FB Data
let fbManager = FBSDKLoginManager()
fbManager.logOut()
FBSDKAccessToken.setCurrentAccessToken(nil)
}

Resources