How exactly are popular games doing server-side Login via OAuth? - facebook

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)

Related

DropBox IOS SDk retrieving access token and secret is invalid once user is Authenticated

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

Google+ integration in iPhone [duplicate]

I have been searching for tutorials on google for posting some text on google plus. But it seems like there are none.
I have also tried to go through the docs provided by google for developers of mac and iPhone but can't find anything that will solve my problem. Also there are little information on how to get the user login to there google plus account.
I am not sure what to do for the user login, do I have to use some GTLObject or use UIWebView like foursquare for user login.
Here is a list of docs that I had went through.
http://code.google.com/p/google-api-objectivec-client/wiki/Introduction
http://code.google.com/p/google-api-objectivec-client/wiki/BuildingTheLibrary
http://code.google.com/p/gtm-oauth2/
As it turns out there are only a limited number of api's available for google + developers and that also only as GET calls according to the developer of google + page my question will not get any definite answers as google is in the process of creating new api's for accessing user information on google plus.
https://developers.google.com/+/api/
Also you can use the google client sdk provided by google but it is much easier to show a webview for user login. I managed to get the people list from google plus.
The steps are same as for getting the access token as in foursquare. Just with some small changes.
in viewdidload method.
NSString *authStr = #"https://accounts.google.com/o/oauth2/auth?client_id=client_id&redirect_uri=http://somevalidurl.com&scope=https://www.googleapis.com/auth/plus.me&response_type=token";
as a url for loading request in webview. People should note one thing here that you need to create a client id in api console for your app that is web based and not as installed for this purpose as you wont we getting any option to enter any website url for callback which is very important in this case.
and in webview delegate method webViewDidFinishLoad:
NSString *urlStr = [[webView.request URL] absoluteString];
NSArray *array = [urlStr componentsSeparatedByString:#"access_token="];
if(array.count > 1)
{
NSString *oauth_token = [[[array objectAtIndex:1] componentsSeparatedByString:#"&"] objectAtIndex:0];
//do something with the oauth token after this.
}
I wrote a code snippet to signin and post simple text to Google Plus with URL and thumb Image URL.
Try it
Take a look here:
http://code.google.com/p/google-api-objectivec-client/source/browse/#svn%2Ftrunk%2FExamples%2FBooksSample
http://code.google.com/p/google-api-objectivec-client/

401 error code when using Soundcloud API OAuth2

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.

Using retweeted_by API with MGTwitterEngine - keeps on returning error 404

I'm trying to add a method to MGTwitterEngine to use twitter's retweeted_by API ( http://dev.twitter.com/doc/get/statuses/:id/retweeted_by ).
Here is what I've added to MGTwitterEngine.m (all the OAuth stuff is done, the other methods inside the engine work fine)
-(NSString *)getUsersWhoRetweetedTweetWithID:(unsigned long)ID {
NSString *path = [NSString stringWithFormat:#"statuses/70482402362933249/retweeted_by.xml"];
return [self _sendRequestWithMethod:nil path:path queryParameters:nil body:nil
requestType:MGTwitterUsers
responseType:MGTwitterUsers];
}
Note: I've already included the .xml format and a status ID - just to ensure there's nothing wrong with the data I'm passing on. When I call [_engine getUsersWhoRetweetedTweetWithID:0]; from my app controller, error 404 is returned "The operation couldn't be completed. (HTTP error 404.)".
I've tried it with a parameters NSDictionary & tried changing the request & response types.
Currently, I don't make use of MGTwitterEngine to check who RTd a tweet, I just use a non OAuth'd method - however this will not return protected users who RTd a tweet.
Can anyone give me a point in the right direction - it's being driving me crazy for the past few days! I really appreciate any input :)
Take a look here.....
How to do a RETWEET on an iPhone twitter app (MGTwitterEngine)
MGTwitterEngine does not support re-tweet method yet .. you have to manually add the parse to MGTwitterEngine .h and .m then the call out would be [_engine sendRetweet:(unsigned Long)];
Now I am in the process of trying to determine how you call out the unsigned long...if any one else has an answer to that I would be happy to hear it myself.

Facebook API: FB.Connect.requireSession issues

I have a Facebook app that is built as an iFrame. I am using the JavaScript client API loaded via:
http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php
In my initialization code, I use the requireLogin method to ensure that the user has authorized the app. I have found this to be necessary to be able to gather the user's name, avatar, etc. for the scoreboard. Here's a representative code snippet:
FB_RequireFeatures(["Connect","Api"], function() {
FB.Facebook.init("...API_KEY_HERE...", "xd_receiver.htm");
var api = FB.Facebook.apiClient;
api.requireLogin(function() {
api.users_getInfo(
FB.Connect.get_loggedInUser(),
["name", "pic_square", "profile_url"],
function(users, ex) {
/* use the data here */
});
});
});
This causes the iframe to redirect causing the Facebook authorization screen to load within my app's iFrame. This looks junky and is somewhat confusing to the user, e.g. there are two Facebook bars, etc.
Question 1: is there anything I can do to clean this up while still implementing as an iFrame, and still using the JavaScript APIs?
According to the FB API documentation:
FB.ApiClient.requireLogin
This method is deprecated - use
FB.Connect.requireSession instead.
My experience though when I replace api.requireLogin with FB.Connect.requireSession it never gets invoked. I'd prefer the recommended way of doing it but I struggled and was not able to find a way to get it to work. I tried adding various arguments for the other two parameters as well with seemingly no effect. My expectation is that this method will load in a dialog box inside my app iFrame with a similar authorization message.
Question 2: what am I missing with getting FB.Connect.requireSession to properly prompt the user for authorization?
Finally, at the end of the game, the app prompts the user for the ability to publish their score to their stream via FB.Connect.streamPublish. Which leads me to...
Question 3: am I loading the correct features? Do I need both "Api" and "Connect"? Am I missing any others?
Here is a summary of the changes I needed to make to clean up the authorization process. It appears that iFrames must fully redirect to properly authorize. I tried using the FBConnect authorization but it was a strange experience of popup windows and FBConnect buttons.
Ultimately this game me the expected experience that I've seen with other FB apps:
FB_RequireFeatures(["Connect","Api"], function() {
var apiKey = "...",
canvasUrl = "http://apps.facebook.com/...";
function authRedirect() {
// need to break out of iFrame
window.top.location.href = "http://www.facebook.com/login.php?v=1.0&api_key="+encodeURIComponent(apiKey)+"&next="+encodeURIComponent(canvasUrl)+"&canvas=";
}
FB.Facebook.init(apiKey, "xd_receiver.htm");
FB.ensureInit(function() {
FB.Connect.ifUserConnected(
function() {
var uid = FB.Connect.get_loggedInUser();
if (!uid) {
authRedirect();
return;
}
FB.Facebook.apiClient.users_getInfo(
uid,
["name", "pic_square", "profile_url"],
function(users, ex) {
/* user the data here */
});
},
authRedirect);
});
For iFrames, the solution was ultimately to redirect to the login URL which becomes the authorization URL if they are not already logged in.
I think that FB.requireSession only works from a FB connect site outside of
Facebook. If you're using an app hosted on apps.facebook.com use the php api
call instead,
$facebook = new Facebook($appapikey, $appsecret);
$facebook->require_login();
or link to the login page.
Of these methods to login
* Using the PHP client library
* Directing users to login.php
* Including the requirelogin attribute in a link or form
* Using FBML
only the first 2 are available to iframe apps hosted on apps.facebook.com
I think requirelogin and fbml only work with fbml canvas apps.
see
http://wiki.developers.facebook.com/index.php/Authorization_and_Authentication_for_Canvas_Page_Applications_on_Facebook
Question 1: is there anything I can do
to clean this up while still
implementing as an iFrame, and still
using the JavaScript APIs?
Question 2: what am I missing with
getting FB.Connect.requireSession to
properly prompt the user for
authorization?
Please have a look at this. This article discusses correct use of require session and provides links on how to implement that. And yes, you are right, the requireLogin has been deprecated and won't help any more.
Question 3: am I loading the correct
features? Do I need both "Api" and
"Connect"? Am I missing any others?
As far as I know, you can use both API and Connect together, basically you access Facebook's API with the help of JavaScript.
For iframe apps however, there is no great help and minimum support of API with some handful functionality available. See this for more info.
This causes the iframe to redirect
causing the Facebook authorization
screen to load within my app's iFrame.
This looks junky and is somewhat
confusing to the user, e.g. there are
two Facebook bars, etc.
Finally and personally I have not seen any iframe app requiring user to add the app first. This will create the problem of two bars you mentioned as quoted above.
The link I posted at the beginning of my answer has some useful links to get you started and decide the next-steps or possibly making changes to your apps.