I am creating an iPhone app using the TestApp application that came with the Soundcloud
Coca API wrapper download.
When I use the key and client id and call back URL there is no
problem. I can log into the app using my Soundcloud account and upload
the my tracks at the touch of a button.
When I switch the client id, key and callback URL to the one that I
have listed on my developer account the behavior changes. I can log in
and the app gets registered to my account, but before my username is
posted to the app I get a 401 at this level in the code:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
{
#if (NXOAuth2ConnectionDebug)
NSLog(#"%.0fms (SUCC) - %#", -[startDate
timeIntervalSinceNow]*1000.0, [self descriptionForRequest:request]);
#endif
printf("connectionDidFinishLoading\n");
if (sendConnectionDidEndNotification) [[NSNotificationCenter
defaultCenter] postNotificationName:NXOAuth2DidEndConnection
object:self];
sendConnectionDidEndNotification = NO;
printf("connectDidFinishLoading.1\n");
printf("self.statusCode: %d \n", self.statusCode);
Since my app works perfectly fine with the key, id and callback URL
given in the TestApp it is strange to me that when I switch these
values I get the 401.
Just to clarify further:
It is an iOS app and I have definitely placed the correct key and id
in the correct spot. The client ID and Secret from souncloud.com (not
sandbox-soundcloud) are plugged into the values directly under
#ifdef kUseProduction
This seems to me the correct thing to do. Also, in my info.plist file
I have the URL identifier
com.imc
and the URL scheme
http://imc
which matches exactly the redirect URI have filed with Soundcloud.
Likewise I have defined my kCallbackURL as
http://imc
Any other thoughts?
I finally got the answer from the lovely people at SoundCloud.
Related
SimCity BuildIt, HayDay, and Paradise Bay (near as I can tell) are all doing FB login via server based authentication. (FB API versions 2.2, 2.2, and 2.6 respectively)
They all use "response_type=token,signed_request" and they all use some variant of "redirect_uri=fbXXXXXXXXXXXXXXX://authorize" where the XXX's are the FB App ID. This is very confusing because I have no idea how to actually get the token if the redirect is going back to Facebook.
It would make sense if there were an "authorize callback URI" but FB only provides a "de-authorize callback URI".
I'm not looking to use a different token type, or a different redirect strategy. This is for a mobile game and I imagine there's a good reason why all the major games do auth this way. I also can't use the Facebook SDK due to the extra amount it adds to the over-the-air binary size; Apple still limits OTA to 100MB.
Figured this out finally. So the fbXXXXXXXXXXXXXXX://authorize redirect is meant to be used in combination with an iOS URL Scheme where you register the scheme using your APP ID prepended with "fb". Then Facebook will append a bit of data to the end of the redirect URL. So your final result looks something like fbXXXXXXXXXXXXXXX://authorize/#signed_request=<user_token>&expires_in=1234567 where the <user_token> is a long SHA256 encoded value (using your app secret).
This means that URL should end up getting passed as arguments to your app where you can decode and unpack the args as needed and then use the token for your subsequent requests such as https://graph.facebook.com/v2.8/me/friends?access_token=<user_token>. Since we are using Unity 5 this meant adding a small bit of code in a custom UnityAppController subclass.
Although it's somewhat outside of the scope of this question, to maybe save other Unity devs some headache, the code for the UnityAppController subclass would need to be something like...
#import "UnityAppController.h"
#interface MyAppController: UnityAppController {}
#end
#implementation MyAppController
- (BOOL)application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation
{
const char *URLString = [[url absoluteString] UTF8String];
UnitySendMessage("_MyUnityObject", "MyMethod", URLString);
return [super application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
}
#end
IMPL_APP_CONTROLLER_SUBCLASS(MyAppController)
I use this code on my app to start facebook login :
[FBSession openActiveSessionWithReadPermissions:nil allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
NSLog(#"#####################");
// session might now be open.
[self sessionStateChanged:session state:status error:error];
}];
Safari start, but i got :
I read that this error is related to the URL key in the plist file, everything looks OK
Here are some settings of the facebook app :
This is very strange. Of course, i double check the fb ID and bundle identifier ...
Any idea ?
Thanks
UPDATE
I got this error message only on the simulator. On real device, i got another one :
You can see that i changed the app id from last time. I just create another facebook app (and i changed the bundle id as well)
Of course i double check that app id and bundle Id are same from my ios app and in the facebook app settings ... so why does it say that the app id is invalid ?
Attached my Facebook app settings for reference!
The Secure Canvas URL - Should have a valid link starting with https://
Canvas URL - Should have a valid link starting with http://
I don't think the issue is about the URL Scheme into the plist file.
In this related post, you can see the redirect_uri has to be set to a full URL when it's provided to redirect the user to after the login process is done.
But I Think the redirect_uri has not to be set logging in by Facebook from an iOS app.
From my point of view, there are two ways to explore resolving this issue:
Disable the FB option: embedded browser OAuth option
Your plist file seems not to provide the FacebookDisplayName key which is now required. See the Facebook iOS SDK Getting Started page for this.
If you are using Facebook SDK, you don't need to bother yourself to enter
anything for redirect URI on the app management page of facebook. Just setup a
URL scheme for your iOS app.
The URL scheme of your app should be a value "fbxxxxxxxxxxx" where xxxxxxxxxxx is
your app id as identified on facebook.
To setup URL scheme for your iOS app, go to info tab of your app settings
and add URL Type.
Cross authentication of a dropbox user using Access token and secret not happening.
Elaborating my Question:
authenticate the user in my IOS app
In Ios app , I retrieve access token and secret from MPOAuthCredentialConcreteStore *credentials.
get the access token from credentials->acccessToken and similarly the secret.
Now if I feed these values into another app outside IOS which uses python sdk for dropbox. I get a error message "Invalid token".
But, interestingly the reverse process from step 1 to 4 works. i.e get access token and secret from python SDK and feed it to my IOS app by using
[dbSession updateAccessToken:#"xxxxxxxxx" accessTokenSecret:#"YYYYYYYYYYY" forUserId:#"12345678"];
and now i can assess user's dropbox account. Any idea as to whats going wrong? Is there a difference between MPoauth and Oauth? I believe MPoauth is just a wrapper right?
is there any other way to get the access token and secret?
Thanks for the help.
I found a fix for this. It was a simple error. Basically the editor I was using was adding a new line char at the end. For some one stuck at the same problem make sure you dont have a new line char at the end.
You can get your Access token by using this delegate
(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *) url {
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
// At this point you can start making API calls
NSLog(#"App linked successfully!");
}
// Add whatever other url handling code your app requires here
}
return NO;
}
Given url has Access token, secret token and user id
I have seen a lot of questions here regarding the Facebook Graph API but I still haven't find a solution for simple 'login'/'logout' operations using it. Looks like the Single Sign-On style is causing more confusion than benefits.
I'd like to know if it is possible have the following situation:
Enter in the app (no accessToken/expirationDate created).
Perform a login using SSO by calling authorize:delegate: method (application goes background and the login is made in the 'global' scope (Facebook App/Mobile Safari), asking for the user credentials.
Enter back in the app (now logged in, both accessToken and expirationDate are saved to NSUserDefaults).
Perform a logout by calling the logout: method (now logged out, both accessToken and expirationDate are removed from NSUserDefaults)
Attempt to perform a login again, with exactly the same steps done in 2.
I realize that when I call logout:, I do really log out from Facebook (accessToken is invalidated) from my App scope, not from the global scope (Facebook App/Mobile Safari). In 5.) when I try to log in again, the application goes to background and the login attempt is made again in Facebook App/Mobile Safari as usual, however I'm getting a screen saying that I'm already logged in:
You have already authorized .... Press "Okay" to continue.
Logged in as ... (Not You?).
It's a strange behavior for the user that has just logged out in my App.
My question is:
"Can I really log out from facebook (I mean 'global' scope) from inside my App? This would affect other apps using the facebook credentials too. However, if I can't to do this, how can I avoid the 'strange behavior' describe above?
Thanks
Eduardo,
I feel your pain! I spent the better part of a day working on this issue. I have discovered that when you use SSO and the call:
Called from your code:
[facebook logout:self];
Facebook API method:
- (void)logout:(id<FBSessionDelegate>)delegate {
self.sessionDelegate = delegate;
[_accessToken release];
_accessToken = nil;
[_expirationDate release];
_expirationDate = nil;
NSHTTPCookieStorage* cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSArray* facebookCookies = [cookies cookiesForURL:[NSURL URLWithString:#"http://login.facebook.com"]];
for (NSHTTPCookie* cookie in facebookCookies) {
[cookies deleteCookie:cookie];
}
if ([self.sessionDelegate respondsToSelector:#selector(fbDidLogout)]) {
[_sessionDelegate fbDidLogout];
}
}
The facebook API does invalidate the access token and expirationdate variables and attempts to delete the mobile Safari cookies, but for some reason, probably Apple's fault the cookies are not really deleted. So when you attempt to login in the next time your mobile Safari will see the cookie and it says:
"You have already authorized .... Press "Okay" to continue. Logged in as ... (Not You?)."
Until either Facebook finds a fix or Apple fixes their broken API we must bypass SSO through Safari. Below are the changes I made to Facebook.m in order to force the old login dialog. If you used these changes they may not work forever but it is my guess that they will work for a very long time. Also to be sure this worked with the most recent facebook API I updated to the latest as of this post (Nov 2011 build).
Called from your code:
[facebook authorize:permissions];
Facebook API method:
- (void)authorize:(NSArray *)permissions {
self.permissions = permissions;
// [self authorizeWithFBAppAuth:YES safariAuth:YES];
[self authorizeWithFBAppAuth:NO safariAuth:NO];
}
If this helps you please up rate this thread and my post to help others find it.
gadildafissh
I'm afraid the answer is no, you can't do this.
Your application is in a sandbox, and can't write outside, where global cookies are (for mobile safari) and Facebook app settings (in Facebook app preferences/cookies I think)
You can only warn your user to logout outside of your app...
...Or you can just not use facebook api SSO, but in app login webform, like I do for other reasons.
If you choose that option this pull request might save you some time ;)
Hii ,
its not possible , the reason is for Single Sign On (SSO) is not to make user login everytime, he logouts , instead if the user logs in anyone of FB enabled apps - it will use that to login again - This is because the device is mostly used by single person in this case only one user can login in Facebook.
you can't control any app outside of your app - for Example - if u login with Gmail & when you open google.com you can see your username there is currently logged In which has SSO,
In new SDK of Facebook, you can set login button loginBehaviour property
Below code in swift ...
let fbButton = FBSDKLoginButton()
fbButton.loginBehavior = .Web
Answer already done, but I just want to clarify it. May be it saved somebody's time.
Go to Facebook.m and change line
[self authorizeWithFBAppAuth:YES safariAuth:YES];
to
[self authorizeWithFBAppAuth:YES safariAuth:NO];
It will cause login window appear inside the app. Logout will work perfect. In other words, it will work as it used to in older versions of OS.
in addition to kishnan94 answer. the objective c version is ;
if you want a modal to open up and ask for facebook credentials seperately from Safari or Facebook app, just use the latest facebook sdk and set the login behaviour
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login setLoginBehavior:FBSDKLoginBehaviorWeb];
this will make the logout process more convenient and less confusing for users without using safari or facebook app accounts.
It seems that this is a bug of Facebook SDK. In a case of the Facebook app is installed on device, access_token is renewed. In other hand, access_token and expirationDate could not be changed. :((
I'm learning how to integrate facebook api in iphone app.
First I visited facebook website, went to applications->developer and created an app. Noted down private key and secret key.
Now, I'm using FBConnect sample code. I am using my keys in FBConnect app. And I set session proxy as
static NSString* kGetSessionProxy = #"SessionViewController"; // #"<YOUR SESSION CALLBACK)>";
I'm able to run the app and when I click "Connect to Facebook", its asking me for credentials as well. But afte providing credentials, its failing. The following delegate method is being called:
- (void)sessionDidNotLogin:(FBSession*)session { _label.text = #"Canceled login"; }
I'm not understanding why I'm ending up in above delegate.
What are all options that I've to select in facebook website when creating new application?
Please help me.
When I made kGetSessionProxy to nil, it worked without any problem. But I didn't understand why it didn't when i gave some value.