Limit permissions when accessing Facebook using Accounts framework - ios

I need some help on this one ....
So the problem I am facing is that while fetching the Facebook account from ACAccount, the alert view informs too many permissions. I am getting an alert box when I use the ACAccount login for facebook.
It says APP_NAME would like to access your basic profile info and list of friends
This shows up even when my permissions set is an empty array.
NSArray * FB_PERMISSIONS = #[];
// or FB_PERMISSIONS = #[#"public_profile", #"likes", #"email"];
// It does not matter what the array is -> The alert has extra sentences.
ACAccountType *FBaccountType= [_accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSString *key = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"FacebookAppID"];;
NSDictionary *dictFB = [NSDictionary dictionaryWithObjectsAndKeys:key,ACFacebookAppIdKey,FB_PERMISSIONS,ACFacebookPermissionsKey, nil];
[_accountStore requestAccessToAccountsWithType:FBaccountType options:dictFB completion:
What am I trying to do here?
I am just needing the "public_profile", #"email" and "likes". The alert says APP_NAME would like to access your profile, and likes on your behalf. In addition, APP_NAME would like to access your basic profile info and list of friends
Why is that second sentence there? How do I get rid of it? I can see a number of apps where the second line that talks about basic profile and list of friends does not show up.
Expected result:
APP_NAME would like to access your profile and likes.
Update:
Check my answer for solution.

There is nothing in the FB SDK docs that explain any of this. They made this way so that users can use the Facebook pop UI and pick the permissions they want to authorize. I guess Facebook design's philosophy is to give as much control and transparency to the user. But with the OS pop-up it hides a lot of permissions underneath. I guess it's Apple's design philosophy to show minimal information. This works best for developers scenario, as users usually freak out when they see so many permissions being asked by the app.
Anyway, if you take a look at FBSDKLoginManager+Internal.h you can checkout the capabilities for System login. Further digging, I've discovered that FBSDKLoginButton is pointless. The best way to go about this is using your own instance of FBSDKLoginManager, and set the system account type to be native, and if you get the error code 306, fall back to default login mechanism.
Somehow ->> This way does not show additional permissions. I have no idea how. All I know is that everything falls into place now.
Further more, you will have to setup a separate listener for ACAccountStoreDidChangeNotification so that you can tie up some edge cases. But yes, \m/

The Fix
The fix to this problem involves adding code to the view header file as well as adding code to your view file. The code examples are listed below.
To the view header file add:
// ViewController.h
#import <FBSDKLoginKit/FBSDKLoginKit.h>
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet FBSDKLoginButton *loginButton;
#end
And to the view file add:
loginButton.readPermissions =
#[#"public_profile", #"email", #"likes"];
Note that the comment in the first example was just for reference.
Why did it happen?
The reason why your problem happened was because the Account Framework and Facebook API think by default that you mean every permission there is. It requires you to be more specific in the code. I am pretty sure that you for got to do the first example of code which was supposed to go in your view header file. I understand that the code above is not what you will put in the file you are working on, but it just gives you a rough idea on doing it.
Still Confused?
If you are still confused please comment below and I will try to update my answer. It would be really helpful if you could send the code you were doing with he arrays filled not blank. If I wasn't clear please tell me and I will do the best I can to help. Sorry if there is any inconvenience!
Sources
Mainly, I found the info on here: https://developers.facebook.com/docs/facebook-login/permissions/overview and over here: https://developers.facebook.com/docs/facebook-login/ios#permissions
Facebook is pretty trustworthy and creditable. I think...

Is there a reason you're not using the Facebook API instead? Requesting access via iOS APIs will require the user to be logged into Facebook via the iOS Settings. If you make the same request with Facebook's API, it can detect if the user is logged in via the settings, the FB app, or Safari. And if the user is not logged in, it'll prompt them to do so (as opposed to just erroring out and telling them to do so via settings)
Version 4.X:
https://developers.facebook.com/docs/facebook-login/ios/permissions
FBSDKLoginManager *loginManager = [[FBSDKLoginManager alloc] init];
[loginManager logInWithReadPermissions:#[#"public_profile", #"likes", #"email"]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
//TODO: process error or result
}];
Version 3.X
[FBSession openActiveSessionWithReadPermissions: #[#"public_profile", #"likes", #"email"]
allowLoginUI:YES
completionHandler:
^(FBSession *session, FBSessionState state, NSError *error) {
// Handle completion by calling AppDelegate
}];

Related

Multiple facebook app id for a single iOS application

Currently I am using FBSDKLoginManager with a Facebook app id to sign in via Facebook into my application. I have the required things in .plist file. Everything works fine.
But now I have to login in another section of my application with a different Facebook app id. How could I use different Facebook app id in a single application in various area.
Someone already asked this question previously. From the answer I found
FBSession *session = [[FBSession alloc] initWithAppID:#"AN_APP_ID"
permissions:nil
defaultAudience:FBSessionDefaultAudienceNone
urlSchemeSuffix:nil
tokenCacheStrategy:nil];
[session openWithCompletionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
// do stuff here
}];
But the answer does not work for me as FBSessionis not available. Any idea? Suggestion?
Refer to this tutorial that specifically addresses your problem in particular, and how to manage different environments in general: https://medium.com/slalom-engineering/ios-managing-multiple-environments-with-a-single-target-94cf823a6447
To go directly into what you want, search for "FacebookAppID" on that link.

Login through FB Giving Error iOS Objective-C [duplicate]

Something must have changed recently on Facebook's servers regarding how they process login requests because this used to be working perfectly and suddenly stopped.
(We are using FBSDKLoginManager.loginBehavior = FBSDKLoginBehaviorWeb because of how our app is replicated for multiple brands (one codebase, many apps) and issues we ran into using the native login.)
Anyhow, this is what we see now when we try to present a login webview to the user (before it even lets them attempt to login):
(Not Logged In: You are not logged in. Please login and try again.)
This is the code we are using to present the login view:
NSString *const publish_actions = #"publish_actions";
FBSDKLoginManager* login = [FBSDKLoginManager new];
login.loginBehavior = FBSDKLoginBehaviorWeb;
[login logInWithPublishPermissions:#[publish_actions] handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
[FBSDKAccessToken setCurrentAccessToken:result.token];
// ...
}];
Also note that this problem is not specific to iOS. Our Android app is seeing the same thing (and again it used to work fine until just recently).
I was having this same bug... seems as though the issue lies in your info.plist URL Scheme settings: Facebook SDK: app not registered as a URL Scheme
However, adding these leads to the app sending you off to the actual Facebook app for authentication, instead of showing the login modal in your own app.
** UPDATE **
Sorry, I spoke too soon... the above changes will help things out (or change the user flow in ways you don't want), but what really needed to happen (and this is the only thing), was just adding an "iOS Platform" (or other) to your app settings in the Facebook Developer portal. This is what did it for me anyways. :)

Apps will not shown in setting->facebook if the account is signed in after the app is installed

I found an weird problem of iOS account setting. When I working on ACAccount renew issue, I found that if users login facebook in device setting after my app in installed, my app will not be able to gain access to facebook account.
To be precise, my app will not be shown on the "ALLOW THESE APPS TO USE YOUR ACCOUNT". Therefore, I've done some tests about this issue:
(1). Facebook login after the app installed -> not shown
(1-1). Remove the app and reinstall -> not shown
(2). Facebook re-login after app installed -> not shown, and all apps which have been granted or not granted will not be shown, too.
(3). Facebook login before the app installed -> shown
And, once the problem encountered, it is not reversible, whether you re-login facebook, reinstall the apps or restart the device will not fix the problem. Only native iOS apps and Facebook app will remain on the list.
There was a old question about this, but the issue is not answered.
Anyone encountered the same problem?
Updated 2013.11.20 11:38 AM
I made two mistakes when using ACAccount, following is a sample code of gaining access to facebook account:
// Check if store exists
if(!_accountStore)
_accountStore = [[ACAccountStore alloc] init];
ACAccountType *facebookTypeAccount = [_accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
// Request access, note that one should not check if the account is available until the access right is granted
[_accountStore requestAccessToAccountsWithType:facebookTypeAccount
options:#{ACFacebookAppIdKey: #"FACEBOOK_API_KEY", ACFacebookPermissionsKey: #[#"read_stream"]}
completion:^(BOOL granted, NSError *error) {
if(granted){
NSArray *accounts = [_accountStore accountsWithAccountType:facebookTypeAccount];
_facebookAccount = [accounts lastObject];
NSLog(#"Success");
}else{
// ouch
_facebookAccount = nil;
NSLog(#"Failed, Error: %#", error);
dispatch_async(dispatch_get_main_queue(), ^{
NSString *message = [NSString stringWithFormat:#"No facebook account or access denied by user. Error:%#", error];
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"系統提示" message:message delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
});
}
}];
I check account count before I gain access to it.
I am not sure if this is a bug of APPLE SDK, if I request for access of "publish_stream", the request will fail.
Then, I saw discussions of errors about requestAccessToAccountsWithType here. It is said that we should request for permissions twice, one for read, and one for write.
Therefore, I change the access right from "publish_stream" to "read_stream", then, it works. My app is shown on the list again.
Although the request for write permission failed, but it does not affect the ability to post on the user's behave.
Updated 2014.8.12 12:31 AM
maml reported that the permission may still be denied after doing the steps above, but the app did show up in setting which makes it possible to toggle it on.
I had solved the issue in the update of my question. It may seems like a workaround, but currently it did solve the problem. If you want to know detail about the solution, see the edited question above.
To solve the problem, we have to:
Change permission access from "publish_stream" to "read_stream". Though you were request for read permission, you are still able to post to the user's time line.
No further steps.
I think this might be a bug of ACAccount framework. However, it did save our time to study Facebook API. So, if you use this method, remember to keep an eye on this issue, which might be fixed in the future.
Note. I answer my own problem to keep it from becoming Tumbleweed...

new facebook account in iOS 6 settings

I am using following code to access the facebook
[FBSession openActiveSessionWithAllowLoginUI:TRUE];
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"email",
nil];
[FBSession openActiveSessionWithReadPermissions:permissions allowLoginUI:true
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if (error) {
NSLog(#"Failure");
}
else
{
}];
It is working fine when user has enabled the facebook account in iOS setting and also when there is no account enabled in iOS settings then it goes to safari for facebook authentication. But suppose user has first enabled the account with abcd#gmail.com and then after some time he has added new account i.e. efgh#gmail.com. So how the app come to know that user has changed his/her account in iOS settings. How to check it by using facebook SDK. Anyone has idea?
Thanks to all.
The information (access token, etc) stored inside a FBSession is entirely independent of any other account authority (this includes iOS6, Safari, or the Facebook app). Those other authorities are only used to connect your app, once it's connected, your app operates independently. This means that even if the user logs out, and logs in again with a different id, it doesn't affect your app at all. The user of your app needs to proactively log out inside your app, and initiate another login in order to change accounts.
This is why it's vitally important that the user has a way of identifying themselves inside of your app (either through a profile picture, and/or their name displayed somewhere), so they know which account they're using.

Changing defaultAudience when sharing to a feed using Facebook IOS SDK

Using the IOS SDK for Facebook (3.1) , I find that once I set up my project, I am unable to change the default audience.
For instance, I set up my test project to publish to "Only Me". It works fine. I am working off of this example, making the change that I start out with audience "Only Me".
http://developers.facebook.com/docs/howtos/publish-to-feed-ios-sdk/
Then I arrange to call the following:
[FBSession.activeSession
reauthorizeWithPublishPermissions:
[NSArray arrayWithObject:#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
if (!error) {
// If permissions granted, publish the story
NSLog (#"Here goes nothing");
[self publishStory];
}
}];
which should publish the story to DefaultAudienceFriends. However, it continues to publish to Only Me.
Shouldn't this work? Am I missing something?
Ok, here is the answer I came up with, which addresses my particular need. I change the privacy settings for the app, in Facebook, here:
http://www.facebook.com/settings?tab=applications
And come to think of it, this makes sense. I, as a user of this app (which I happened to create, but that probably isn't relevant), am specifying the behavior it displays when it posts on my behalf.
So I'm happy, because now I can work on my app, freely test it, without disturbing anybody. And I can change it to post more widely, when I'm ready.
During the authorization flow you set the default audience, in your case "Only Me". Now that your app has permissions trying to reauthorize will likely do nothing, unless you probably logout and back in. What you can try doing instead is passing the audience you want as a part of the post parameter.
So, based on the sample, let's say you wanted "Only Me", you would add:
[self.postParams setObject:#"{'value':'SELF'}",
forKey:#"privacy"];
And if you wanted "Friends", you would use:
[self.postParams setObject:#"{'value':'ALL_FRIENDS'}",
forKey:#"privacy"];

Resources