I'm trying to get post permissions from a user using the Facebook SDK on iOS.
I'm calling the code below in a method that is called if the app does not have the required publishing permissions to post to the users facebook wall.
// No permissions found in session, ask for it
[FBSession.activeSession requestNewPublishPermissions: [NSArray arrayWithObject:#"publish_actions"]
defaultAudience: FBSessionDefaultAudienceEveryone
completionHandler: ^(FBSession *session, NSError *error)
{
if( !error )
{
// Do something
}
}];
The first time I call this code it takes the user to the permissions page, and before it even switches to safari on the device the block gets called and this error message is returned
Error Domain=com.facebook.sdk Code=2 "The operation couldn’t be completed. (com.facebook.sdk error 2.)" UserInfo=0xc426410 {com.facebook.sdk:ErrorLoginFailedReason=com.facebook.sdk:ErrorReauthorizeFailedReasonUserCancelled,
The app then continues on to show the permissions page in safari where the user selects ok. Then it returns to the app. Permissions have not been set at this point even tho the user was presented with the permissions page and accepted.
When trying to post a second time it takes the user to the permissions page in safari and the requestNewPublishPermissions method doesn't fail instantly. The user selects ok and then everything works as expected.
So it is only on the very first time calling requestNewPublishPermissions that it fails instantly returning the error ErrorReauthorizeFailedReasonUserCancelled.
This happens in the simulator and on the device.
Any idea what might be causing this?
I found the solution to this problem on the answer to this question Facebook iOS 3.1 sdk login with publish permission callbacks
dispatch_async(dispatch_get_current_queue(), ^{
[self openSessionForPublishPermissions];
});
Where opensessionforpublishpermissions is the method that contains the requestNewPublishPermissions method.
"The reason is that the call to reauthorize.. needs to be after the event loop of which openActiveSession.. is called."
I assume this is a bug in the Facebook SDK, it doesn't make sense for this to be normal behaviour and I haven't seen any of the Facebook docs comment on this being the expected behaviour.
I had the similar issue, and the answer, provided by Tiddly worked for me. For some time.
Later I ran across the same issue. I don't know why, may be it was concerned with SDK or iOS updates, may be run loop of the app became more complicated. So I inspected FB SDK source and figured out that this issue occurs when you ask publish permissions just after read permissions, like this:
// Open with read permissions
[FBSession openActiveSessionWithReadPermissions: readPermissions
allowLoginUI: YES
completionHandler: ^
(FBSession *session, FBSessionState status, NSError *error)
{
// Ask for publish permissions (This is incorrect!)
[FBSession.activeSession requestNewPublishPermissions:publishPermissions
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:
^(FBSession *session, NSError *error)
{
// ...
}];
}];
When your app switches to Safari or FacebookApp and back,
-application: openURL: sourceApplication: annotation:
is called. CompletionHandler of
+openActiveSessionWithReadPermissions:
called immediately after this, before
applicationDidBecomeActive:. And after you start reauthorisation
applicationDidBecomeActive: is finally called. So, FB SDK think that user has returned back to the app, without giving permissions and reauthorisation fails with that "com.facebook.sdk error 2." error.
Sometimes dispatch_async() works well. But the robust solution, is to wait for active session to handle App Did Become Active event. And then request additional publish permissions. Here is an example of how to achieve this:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[FBAppCall handleDidBecomeActive];
if (self.shouldReauthorise) {
[self requestPublishPermissions];
self.shouldReauthorise = NO;
}
}
Related
I just started using facebook sdk and slightly confused with it documentation. It's well written, but very often does not correspond to current SDK version. So i'm not found what to do with this situation:
I request publish permissions when firstly require them, with the next code:
[[FBSession activeSession] requestNewPublishPermissions:permissions
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
if (error) {
NSLog(#"Permissions request error: %#", error.description);
}
completion(error == nil);
}];
I need only one publish permission - 'publish_actions', when i request it sdk redirects me to facebook app and immediately returns back to the my app without asking whether i'm agree to give this permission.
There are no errors in completionHandler, but through debug i found that this permission was saved in the variable _requestedReauthPermissions:
So, finally, permission i requested not granted to me.
How properly request publish permission? What could I miss? May it occur due to setup of facebook app?
My app needs to send a private message to the user's Facebook friend. The user needs to grant the XMPP permission before my app can do this.
[[FBSession activeSession]
requestNewPublishPermissions:[NSArray arrayWithObjects:
#"publish_stream",
#"xmpp_login",
nil
]
defaultAudience:FBSessionDefaultAudienceEveryone
completionHandler:^(FBSession *session, NSError *error) {
}
];
The above code will pop up this alert view as expected:
However, even before tapping any button, this warning is printed out in the debug log:
FBSDKLog: FBSession: a permission request for publish or manage
permissions contains unexpected read permissions
Surely enough, after tapping the "OK" button, the completion handler comes back with an error, containing the same warning. I understand that the Facebook API requires asking for read and write permissions separately, but the xmpp_login permission seems to need both read and write at the same time. I'm at a dead end here.
iOS 7.1
Facebook SDK 3.12.0
Xcode 5.1
See the section Extended Permissions in this link.
According to this, xmpp_login is the read permission, not the write/publish permission. So you should add that the readPermission
every time you tap the facebook login button you are asked to accept the read permissions regardless of whether you just accepted them on your previous login attempt. you can accept the read permissions and land back in the app, only to logout, login, and be presented with the read permissions to accept yet again.
this issue did not exist prior to 3.5, 3.5.1, or the new 3.5.2. Due to this issue my application is stuck on the latest version of the pre v3.5 version of the sdk (3.2.1).
to me, this sounds like a bug in the facebook sdk/app but when i submitted this bug report it was marked as "triaged/low priority" and had the following note attached: "Thanks for the report. We are prioritizing other reports at the moment. You may want to check out http://facebook.stackoverflow.com/" so here i am.
my logic behind the assertion of it being a facebook server side thing is that we are making an auth request to facebook. it is within the facebook realm that they decide what permissions you have and have not accepted. how can it be a fault on my side? it is not the developer's job to tell facebook what their own user has accepted or not.
heres the code that i have behind the "Login with Facebook" button touch up event:
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
if (appDelegate.session.state != FBSessionStateCreated) {
appDelegate.session = [[FBSession alloc] initWithPermissions:permissions];
}
[appDelegate.session openWithCompletionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if([appDelegate.session isOpen]) {
//login ui flow finished here
}
}];
anybody have any thoughts?
I've been trying to integrate Facebook and came across some issues and questions.
1.
I have implemented the following method in viewDidLoad:
[FBSession openActiveSessionWithReadPermissions:nil allowLoginUI:NO completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
[self sessionStateChanged:session state:status error:error];
}];
When there's a token cached, the block is executed as expected.
But, when there isn't a token cached, the block isn't executed at all.
Is this a normal behaviour? If so, when is the block executed?
2.
I've been said that access tokens are expired at some point.
Should I be worried about what to do when a token is expired, or Facebook handles it automatically?
3.
What FBSession actually means?
As I understand - the FBSession manages the token and the user authentication,
Yet, I don't understand what does it mean to "open a session" or what the FBSessionStates represent.
When is the FBSession created? Right when the app loads?
4.
I've found that graph that should explain the FBSessionsStates:
After reading the graph, I still don't understand the flow - when are FBSessionStateCreated & FBSessionStateCreatedTokenLoaded the current state of the session?
As you can see, I have many questions about the whole process.
I've tried to organize the questions in a way that other people seeing this in the future, won't be having the struggles I'm having.
Thank you.
my app can only send app request during the first run that the user logins into facebook. Once the app is restarted, the app request gets stopped because FBSession.activeSession.isOpen gives false.
Although, FBSession.activeSession.isOpen gives false still the app can perform other operations such as posting to the wall, getting friend list etc. Only it cannot send app requests. And still it has a valid access token too.
Any ideas?
You say "FBSession.activeSession.isOpen gives false", but, just to be sure : when do you run this test? When your call to the login request returns, or inside the asynchronous request's callback ?
If it's done outside the request's callback, it may say that the session is not opened yet. Then, the request returns properly, which means that any further call to another FB request succeeds.
Does that help?
If it does not, maybe an overview of your code could.
Ok, next to your comment from the previous answer :
yes, that's what you said already. but WHERE in your code do you check isOpen? To expect a proper value, it should be something like this :
FBSession openActiveSessionWithReadPermissions:_readPerms allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
// here is the proper place to check the isOpen boolean, and to go on with your program, including the app request
}];
// not the proper place to check isOpen.
Does that help?