Facebook SDK + iPhone SDK + SSO - iphone

I know that this question has been asked, but I have been reading through threads all day and have applied all of the fixes I could find and am still having an issue.
I am trying to implement Facebook SDK's new SSO feature to allow my app to authenticate with Facebook's app instead of a webView. When my app switches to Facebook's app, it says loading for a few seconds and switches back but the token is still null. I have a feeling it has to do with the URL scheme for my app but I have followed many tutorials and am fairly confident that my current plist values are correct:
Here is the code I have implemented in my appDelegate and viewController files:
appDelegate.h
Facebook *facebook;
appDelegate.m
// Pre 4.2 support
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [facebook handleOpenURL:url];
}
// For 4.2+ support
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [facebook handleOpenURL:url];
}
SecondViewController.m
-(IBAction) fbButton {
//FACEBOOK INTEGRATION
appDelegate.facebook = [[Facebook alloc] initWithAppId:#"222087841143437" andDelegate:appDelegate];
// Check and retrieve authorization information
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
appDelegate.facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
appDelegate.facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![appDelegate.facebook isSessionValid]) {
appDelegate.facebook.sessionDelegate = self;
[appDelegate.facebook authorize:permissions];
NSLog(#"Token: %#", [defaults objectForKey:#"FBAccessTokenKey"]);
} else {
NSLog(#"Already logged in!");
}
[appDelegate.facebook requestWithGraphPath:#"me" andDelegate:self];
}
- (void)request:(FBRequest *)request didLoad:(id)result {
NSString *nameID = [[NSString alloc] initWithFormat:#"%# (%#)", [result objectForKey:#"name"], [result objectForKey:#"id"]];
NSMutableArray *userData = [[NSMutableArray alloc] initWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:
[result objectForKey:#"id"], #"id",
nameID, #"name",
[result objectForKey:#"picture"], #"details",
nil], nil];
[userData release];
[nameID release];
NSLog(#"DATA RECEIVED: %#", result);
}
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response {
NSLog(#"request:didReceiveResponse:");
}
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error {
NSLog(#"%#", [error localizedDescription]);
NSLog(#"Err details: %#", [error description]);
};
- (void)fbDidLogin {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[[appDelegate facebook] accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[[appDelegate facebook] expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
NSLog(#"Facebook Logged in!");
[appDelegate.facebook requestWithGraphPath:#"me" andDelegate:self];
}
I know that I call [appDelegate.facebook requestWithGraphPath:#"me" andDelegate:self] twice, but I don't think that's the problem.
Here is a snippet from the console when I press the login button:
2011-10-18 15:37:33.287 Track[2235:707] Token: (null)
2011-10-18 15:37:36.578 Track[2235:707] request:didReceiveResponse:
2011-10-18 15:37:36.584 Track[2235:707] The operation couldn’t be completed. (facebookErrDomain error 10000.)
2011-10-18 15:37:36.586 Track[2235:707] Err details: Error Domain=facebookErrDomain Code=10000 "The operation couldn’t be completed. (facebookErrDomain error 10000.)" UserInfo=0x1ce480 {error=<CFBasicHash 0x1c9560 [0x3e368630]>{type = mutable dict, count = 2,
entries =>
2 : <CFString 0x19a830 [0x3e368630]>{contents = "type"} = <CFString 0x11d230 [0x3e368630]>{contents = "OAuthException"}
3 : <CFString 0x1f5b60 [0x3e368630]>{contents = "message"} = <CFString 0x1f8a70 [0x3e368630]>{contents = "An active access token must be used to query information about the current user."}
I appreciate the help and I really hope I didn't miss a discussion on here that solves this problem. Here are a few (of the many) that I have read through and had no success in finding a solution
How to implement Single Sign On (SSO) using facebook ios sdk for iphone
Facebook SSO and request iOS SDK
Facebook API for iPhone Error: An active access token must be used

Make sure that your Facebook application (the actual application that you created on Facebook) is not in sandbox mode and if it is make sure that the user your Facebook application (the iPhone Facebook client) is currently logged in with is a developer for that application.

Related

How to fetch instagram app logged in user details in ios device using our application?

This is the first time I am working on Instagram API. If the user is already having instagram app in his device, how can we fetch his user details from our application?
Right now my app is redirecting to safari and asking the instagram credentials there though I have instagram app in my iPhone where I loggedin.
Can any one please help me with this?
We need Instagram.h and Instagram.m file to fetch instagram user details.
You need a create an application in the Instagram developer site to get app id.
instagram = [[Instagram alloc] initWithClientId:APP_ID delegate:nil];
NSString *const instagramUrlScheme = #"---YourAppName---";
-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { //openo
if ([urlStr hasPrefix:instagramUrlScheme]) {
//[self showAlertWithTitle:THIS_METHOD message:url.description];
return [self.instagram handleOpenURL:url];
}
}
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
NSString *urlStr = url.description;
if ([urlStr hasPrefix:instagramUrlScheme]) {
return [self.instagram handleOpenURL:url];
}
return NO;
}
These are the instagram delegates you need to implement.
#pragma - IGSessionDelegate
-(void)igDidLogin
{
NSLog(#"Instagram did login");
//[[self appDelegate] showAlertWithTitle:#"igDidLogin" message:#""];
// here i can store accessToken
[[NSUserDefaults standardUserDefaults] setObject:[self appDelegate].instagram.accessToken forKey:#"accessToken"];
[[NSUserDefaults standardUserDefaults] synchronize];
//NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:#"users/self/followed-by", #"method", nil];
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:#"users/self", #"method", nil];
[[self appDelegate].instagram requestWithParams:params
delegate:self];
}
-(void)igDidNotLogin:(BOOL)cancelled
{
NSLog(#"Instagram did not login");
NSString* message = nil;
if (cancelled) {
message = #"Access cancelled!";
}
else {
message = #"Access denied!";
}
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:message
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
}
-(void)igDidLogout
{
NSLog(#"Instagram did logout");
// remove the accessToken
[[NSUserDefaults standardUserDefaults] setObject:nil forKey:#"accessToken"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
-(void)igSessionInvalidated
{
NSLog(#"Instagram session was invalidated");
}
You have to use these when you want to connect to instagram.
[self appDelegate].instagram.accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:#"accessToken"];
[self appDelegate].instagram.sessionDelegate = self;
[[self appDelegate].instagram logout];
[[self appDelegate].instagram authorize:[NSArray arrayWithObjects:#"comments", #"likes", nil]];
Hope this helps:
As far as my knowledge when we are redirecting from our app to other app we can't access the other app details (Login details).
As long as I also do know, this is not possible.
We can't get details of the other app from our app.
You can get more info for instagram by this instagram developer link.
Hope this helps you.

iPhone Facebook SDK Error

I'm trying to figure out what this error means...
I'm trying to get user information via Facebook sdk. All I need is their email and name
Error Domain=facebookErrDomain Code=10000 "The operation couldn’t be completed. (facebookErrDomain error 10000.)" UserInfo=0xde94ad0 {error=<CFBasicHash 0xde7d100 [0x3f616650]>{type = mutable dict, count = 3,
entries =>
2 : <CFString 0xde722a0 [0x3f616650]>{contents = "type"} = <CFString 0xdeba1a0 [0x3f616650]>{contents = "OAuthException"}
3 : <CFString 0xde6ba20 [0x3f616650]>{contents = "message"} = <CFString 0xdeb12a0 [0x3f616650]>{contents = "An active access token must be used to query information about the current user."}
6 : <CFString 0xde74c40 [0x3f616650]>{contents = "code"} = 2500
}
}
My basic code... (below in my viewDidLoad)
facebook = [[Facebook alloc] initWithAppId:#"random#123456" andDelegate:self];
[self login];
(below in my login method)
- (void) login {
NSArray *permissionsArray = [NSArray arrayWithObjects:#"email", nil];
[facebook authorize:permissionsArray];
}
(and my Facebook request methods...)
- (void)request:(FBRequest *)request didLoad:(id)result {
NSLog(#"Inside didLoad");
if ([result isKindOfClass:[NSArray class]]) {
result = [result objectAtIndex:0];
}
// When we ask for user infor this will happen.
if ([result isKindOfClass:[NSDictionary class]]){
//NSDictionary *hash = result;
NSLog(#"Name: %#", [result objectForKey:#"name"]);
}
if ([result isKindOfClass:[NSData class]])
{
NSLog(#"Profile Picture");
//[profilePicture release];
//profilePicture = [[UIImage alloc] initWithData: result];
}
NSLog(#"request returns %#",result);
//if ([result objectForKey:#"owner"]) {}
};
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error{
NSLog(#"%#",error);
}
I'm really confused to why I get an error and what I need to change or add in order to fix it...
Any ideas?
EDIT: My request code:::
- (IBAction)requestFBFriends:(id)sender {
NSLog(#"HERE");
[facebook requestWithGraphPath:#"me/friends" andDelegate:self];
}
Here's how you can get the name and email...
I didn't test it so if it doesn't work just tell and I'll find out the problem.
The method that sends the request needs to authenticate if you don't have a valid access token
-(void)getUserFBInfo
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"] && [defaults objectForKey:#"FBExpirationDateKey"]) {
self.facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
self.facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![self.facebook isSessionValid]) {
NSLog(#"auth");
[self.facebook authorize:[NSArray arrayWithObject:#"email"]];
} else {
[self apiFQLIMe];
}
}
#pragma mark -
#pragma mark FBSessionDelegate
/**
* Called when the user successfully logged in.
*/
- (void)fbDidLogin
{
[self reportAction:#"FB allowed"];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[self.facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[self.facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
[self apiFQLIMe];
}
/**
* Called when the user dismissed the dialog without logging in.
*/
- (void)fbDidNotLogin:(BOOL)cancelled
{
NSLog("did not login");
}
/**
* Called after the access token was extended. If your application has any
* references to the previous access token (for example, if your application
* stores the previous access token in persistent storage), your application
* should overwrite the old access token with the new one in this method.
* See extendAccessToken for more details.
*/
- (void)fbDidExtendToken:(NSString*)accessToken
expiresAt:(NSDate*)expiresAt
{
NSLog(#"token extended");
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:accessToken forKey:#"FBAccessTokenKey"];
[defaults setObject:expiresAt forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
/**
* Called when the user logged out.
*/
- (void)fbDidLogout
{
NSLog("did logout")
}
/**
* Called when the current session has expired. This might happen when:
* - the access token expired
* - the app has been disabled
* - the user revoked the app's permissions
* - the user changed his or her password
*/
- (void)fbSessionInvalidated
{
[self.facebook authorize:[NSArray arrayWithObject:#"email"]];
}
#pragma mark -
#pragma mark FBRequestDelegate
- (void)apiFQLIMe {
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"SELECT name, first_name, middle_name, last_name, username, contact_email FROM user WHERE uid=me()", #"query",
nil];
[self.facebook requestWithMethodName:#"fql.query"
andParams:params
andHttpMethod:#"POST"
andDelegate:self];
}
/**
* Called when the Facebook API request has returned a response.
*
* This callback gives you access to the raw response. It's called before
* (void)request:(FBRequest *)request didLoad:(id)result,
* which is passed the parsed response object.
*/
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response
{
DLog(#"received response");
}
/**
* Called when a request returns and its response has been parsed into
* an object.
*
* The resulting object may be a dictionary, an array or a string, depending
* on the format of the API response. If you need access to the raw response,
* use:
*
* (void)request:(FBRequest *)request
* didReceiveResponse:(NSURLResponse *)response
*/
- (void)request:(FBRequest *)request didLoad:(id)result
{
NSLog(#"%#",result);
// check the log to know how you receive the result
}
/**
* Called when an error prevents the Facebook API request from completing
* successfully.
*/
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error
{
NSLog(#"Err message: %#", [[error userInfo] objectForKey:#"error_msg"]);
NSLog(#"Err code: %d", [error code]);
}
If you have questions ask them in the comments
If you are running the application on Simulator/device Try cleaning the build and fresh install the application. The current error might be due to inactive/revoked access token which is no longer valid to access user data.
Hope it helps!!!

iOS Facebook SDK connect fails on iDevice

I'm using facebook connect in an iOS app (ARC, running on iOS 5). it was working fine on both simulator and device but since this morning it has stopped working on the device, it does still work on the simulator. On the device i get the fbDinNotLogin method called.
Now, I know the differece is simulator uses mobile facebook and my app uses native iOS facebook app, and I also know that you can tweak the facebook.m file to force the app to do the login elsewhere but I don't want to do that.
loading my previous builds from yesterday (where everything was working fine) also gives me the same results. so same code that ran yesterday doesn't run today. any idea why this happens? below is my delegate .m file:
[EIDT] I get various different behaiviours from the native facebook app. sometimes it opens facebook app, and stays there not coming back to my app. also sometimes it just goes back to my app quickly without allowing facebook app to ask me for my permission. I'm very confused. [/EDIT]
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions {
user *userClass= [[user alloc] init];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedOnce"])
{
// app already launched for the first time
}
else
{
// This is the first launch ever
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
[userClass CopyDbToDocumentsFolder];
}
facebook = [[Facebook alloc] initWithAppId:#"XXXXXXXXXX" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![facebook isSessionValid]) {
[facebook authorize:nil];
}
return YES;
}
-(void)fbDidLogout
{
NSLog(#"Facebook loggedOut");
}
- (void)fbDidNotLogin:(BOOL)cancelled
{
NSLog(#"Facebook Connect Failed");
}
- (void)fbDidLogin {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
- (void)fbSessionInvalidated
{
NSLog(#"Facebook Session Invalidated");
}
- (void)fbDidExtendToken:(NSString*)accessToken
expiresAt:(NSDate*)expiresAt
{
NSLog(#"Facebook Toekn was extended");
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [self.facebook handleOpenURL:url];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication: (NSString *)sourceApplication annotation:(id)annotation {
return [self.facebook handleOpenURL:url];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Although the SDK attempts to refresh its access tokens when it makes API calls,
// it's a good practice to refresh the access token also when the app becomes active.
// This gives apps that seldom make api calls a higher chance of having a non expired
// access token.
[[self facebook] extendAccessTokenIfNeeded];
}
#end
Turned out the problem was indeed with facebook and not my app! my developer account had been failing to save changes etc, but it's back to a working now.

Facebook always reauthorizing on each app launch?

I have recently added Facebook integration to my app, and everything works fine except when the user relaunches the app. Each time the app is restarted, Facebook has to go back through its authorization process. This involves switching out of the app to Safari/Facebook, then back to my app. How can I make Facebook save the info, or be able to get blanket permissions for my app so that I doesn't constantly reauthorize?
Here is my code from the applicationDidFinishLaunchingWithOptions: method:
facebook = [[Facebook alloc] initWithAppId:#"203604286395694" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![facebook isSessionValid]) {
[facebook authorize:nil];
}
Relevant Facebook delegate methods:
- (void)fbDidLogin {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
- (void) requestDialogButtonClicked {
NSMutableDictionary* params =
[NSMutableDictionary dictionaryWithObjectsAndKeys:
#"invites you to check out cool stuff", #"message",
#"Check this out", #"notification_text",
nil];
[facebook dialog:#"apprequests"
andParams:params
andDelegate:self];
}
- (void)dialogDidComplete:(FBDialog *)dialog {
NSLog(#"dialog completed successfully");
}
Are you calling Facebook authorize: somewhere? That's how the fbDidLogin will be triggered. Assuming you are, the behavior indicates that either the token or the date (or both) is nil, or that the date is past expiration (unlikely).
Log the values upon writing and reading the user defaults. My guess is that the authorize either wasn't called, or failed (due to app key or some other problem not shown in the code), leaving the fbDidLogin method uncalled or saving nil values.
That's because you are not asking for permissions when you authorize your app .. "offline_access" provide a long term access token so you will not need to get a new access token every time the user wants to use the Facebook .. so what you need to authorize your app like this
if (![facebook isSessionValid]) {
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"user_likes",
#"read_stream",
#"offline_access"
nil];
[facebook authorize:permissions];
[permissions release];
}
Edit :
Please check the following in your implementation :
1.you need to add the following functions in your application delegate(the Facebook object here is your instance value of FaceBook Class).
// Pre 4.2 support
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
return [facebook handleOpenURL:url];
}
// For 4.2+ support
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [facebook handleOpenURL:url];
}
2.In your info.plist add to URL types > URL Schemes > your Facebook app ID with fb prefix (finally your value will be like this for ex. fb313714***).

Facebook SDK method 'fbDidLogin' never gets called after user authentication (iOS)

I'm having a lot of trouble posting comments to Facebook. Here is how I have got the code setup; in my viewController class I have set up a button that when pressed checks if the user is connected to Facebook. If they're not connected I attempts to make a connection. Here is the code the .h and .m files:
.h file
#import <UIKit/UIKit.h>
#import "FBConnect.h"
#interface Info_Main_ViewController : UIViewController <FBSessionDelegate>
{
Facebook *facebook;
}
#property(nonatomic, retain)Facebook *facebook;
- (IBAction)shareButtonPressed:(id)sender;
- (void)setUpFacebookConnection;
.m file
- (IBAction)shareButtonPressed:(id)sender
{
if (facebook == nil)
{
// Setup Facebook connection
[self setUpFacebookConnection];
}
}
- (void)setUpFacebookConnection
{
facebook = [[Facebook alloc] initWithAppId:#"xxxxxx" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"])
{
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![facebook isSessionValid])
{
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"publish_actions",
nil];
[facebook authorize:permissions];
}
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [facebook handleOpenURL:url];
}
- (void)fbDidLogin
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
When I run this code and press the button it opens up safari with a page allowing the user to choose whether to allow the app access to Facebook. Once you accept this it switched back to my app, however the method fbDidLogin never gets called so I can't ever post any messages.
Please can someone help me out, I've spent ages trawling the internet for advice but all of the relevant articles are either outdated or they have the connection to Facebook setup in the app delegate class. Whereas in my situation I only want to user to connect when they choose (i.e. when they press the button).
This method:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [facebook handleOpenURL:url];
}
must be placed in your application delegate. You will have to change the reference to the facebook instance so that it's valid in the app delegate, of course.