I'm trying to integrate Facebook to my app, I've implemented the SSO feature, however I ran into a bit of a snag, once I quit the app I am unable to restore the user's session. I store the token and expiry date as shown:
-(void)fbDidLogin {
NSString *tokenString = [[self facebook] accessToken];
NSDate * expirationDate = [[self facebook] expirationDate];
[[NSUserDefaults standardUserDefaults] setValue: tokenString forKey:#"FacebookToken"];
[[NSUserDefaults standardUserDefaults] setObject: expirationDate forKey:#"FacebookExpirationDate"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"Login");
}
this is the delegate method called upon successful login.
and resume the session:
NSString *tokenString = [[NSUserDefaults standardUserDefaults] stringForKey:#"FacebookToken"];
NSDate *expDate = [[NSUserDefaults standardUserDefaults] objectForKey:#"FacebookExpirationDate"];
if (tokenString != nil && expDate != nil)
{
[[facebookFetcher facebook]setAccessToken:tokenString];
[[facebookFetcher facebook] setExpirationDate:expDate];
}
if ([[facebookFetcher facebook] isSessionValid])
{
NSLog(#"YES");
}
else
{
NSLog(#"Bummer");
}
I've tried tackling the problem in a number of ways without luck. One thing I've noticed is that the expiry date seems to be a bit weird:4001-01-01 00:00:00 +0000 Any suggestions? Thanks.
Your answer is at the following link
Does the Facebook iOS SDK require the user to authenticate every time they use the app?
The date 4001-01-01 00:00:00 +0000 is seen when using the extended permission offline_access.
I ran into trouble with this because I was converting the date into "seconds since 1970" like how it's done on the Android Facebook SDK. If you convert 4001-01-01 to seconds using NSDate's timeIntervalSince1970, you'll get a negative number (-2147483648), so watch out.
Related
I have a program that authorize on facebook with cookies. So the modal dialog with facebook authorizing every time displaying. I want to hide it from user. Any help please..
When your login was successful you could do something like:
[[NSUserDefaults standardUserDefaults] setObject:_facebook.accessToken forKey:#"FBAccessToken"];
[[NSUserDefaults standardUserDefaults] setObject:_facebook.expirationDate forKey:#"FBExpirationDate"];
[[NSUserDefaults standardUserDefaults] synchronize];
then when your application starts up, do something similar to this:
if ( [[NSUserDefaults standardUserDefaults] objectForKey:#"FBAccessToken"] != nil ) {
_facebook.accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:#"FBAccessToken"];
_facebook.expirationDate = [[NSUserDefaults standardUserDefaults] objectForKey:#"FBExpirationDate"];
}
What this is doing is, that it saves the "cookie" of the facebook authentication and reuses it when the application is restarted.
Hope this helps.
I have the following function to post to Facebook using the latest iOS Facebook SDK.
-(void)fbPost:(NSMutableDictionary *) params{
NSLog(#"fbPost called");
if (![facebook isSessionValid]) {
NSLog(#"session invalid, calling fblogin");
[self fblogin];
}
if ([facebook isSessionValid]) {
NSLog(#"session valid, calling publishToFB");
[self.facebook dialog:#"stream.publish" andParams:params andDelegate:self];
}
}
It works fine when there is no existing session: it logs in to facebook, gets permissions, returns to the app, shows the dialog and publishes the status. However, when trying a second time, isSessionValid returns true the first time and nothing happens, although the log shows publishToFB is called.
The session is persisted in fbDidLogin:
[[NSUserDefaults standardUserDefaults] setObject:self.facebook.accessToken forKey:#"AccessToken"];
[[NSUserDefaults standardUserDefaults] setObject:self.facebook.expirationDate forKey:#"ExpirationDate"];
[[NSUserDefaults standardUserDefaults] synchronize];
and loaded in application didFinishLaunchingWithOptions:
facebook.accessToken = [[NSUserDefaults standardUserDefaults] stringForKey:#"AccessToken"];
facebook.expirationDate = (NSDate *) [[NSUserDefaults standardUserDefaults] objectForKey:#"ExpirationDate"];
I made sure to ask for offline_access permission when logging in:
_permissions = [[NSArray arrayWithObjects:
#"publish_stream",#"offline_access",nil] retain];
It appears the problem was in drawing the dialog in this code in FBDialog.m
UIWindow* window = [UIApplication sharedApplication].keyWindow;
if (!window) {
window = [[UIApplication sharedApplication].windows objectAtIndex:0];
}
If I comment out the If clause, it works OK. I guess that in my app setup, "keyWindow" is not front-most, so the dialog was not showing up.
I've been toying with the new facebook iOS sdk. I have gotten my project to the point where someone can login successfully. However I have 2 questions:
1) to hit the graph api you issue the following call: [facebookInstance requestWIthGraphPath:#"me" andDelegate:self]. Is it possible to specificy a delegate other than self? Currently all responses go to the (void)request: (FBRequest *) request didLOad:(id) result. But since my app may issue requests to the facebook api at different times and need different things to happen for each respective request issued, how can I specifiy which callback function the response should hit in my app? Is this possible?
2) Once the user has logged in, how can you check their authorization/login status so that I can disable the login button if they are already logged in? Consider the example of a user turning on the app for the 1st time and logging in. Then closing the app, and opening a few minutes later. I rather not show the user the login button the 2nd time and instead start pulling information to display such as their name.
1) There shouldn't be anything wrong with specifying a delegate other than self, as long as the object you provide as the delegate conforms to the FBRequestDelegate protocol. Alternately you can interrogate the FBRequest object you get in the delegate method to determine which request it was that just loaded and what the appropriate response is.
2) To make it so the user stays logged in, you need to save the accessToken (an NSString) and the expirationDate (an NSDate) properties of the Facebook object when the user logs in. Then, when you would log your user in, attempt to restore these values.
Some code snippets that may help:
- (void)fbDidLogin
{
NSString *tokenString = [[self facebook] accessToken];
NSDate * expirationDate = [[self facebook] expirationDate];
[[NSUserDefaults standardUserDefaults] setObject: tokenString forKey:#"FacebookToken"];
[[NSUserDefaults standardUserDefaults] setObject: expirationDate forKey:#"FacebookExpirationDate"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
And, when you need to log the user in:
NSString *tokenString = [[NSUserDefaults standardUserDefaults] objectForKey:#"FacebookToken"];
NSDate *expDate = [[NSUserDefaults standardUserDefaults] objectForKey:#"FacebookExpirationDate"];
if (tokenString != nil && expDate != nil)
{
[facebook setAccessToken:tokenString];
[facebook setExpirationDate:expDate];
}
if ([facebook isSessionValid])
{
//Your session is valid, do whatever you want.
}
else
{
//Your session is invalid
//(either the session is past the expiration date or there is no saved data for the login)
//you need to ask the user to log in
}
After
_facebook = [[Facebook alloc] init];
and
[_facebook authorize:kAppId permissions:_permissions delegate:self];
How can I tell whether the _facebook is (still) logged-in/valid to do further [_facebook requestWithMethodName: ...]?
Or should I just simply [_facebook authorize:...] again and again? Thanks!
I was having the same issue which i solved with the solution of another Member from here, dont know link exactly. but here's the solution
When you are logged into the facebook
[[NSUserDefaults standardUserDefaults] setObject:self.facebook.accessToken forKey:#"AccessToken"];
[[NSUserDefaults standardUserDefaults] setObject:self.facebook.expirationDate forKey:#"ExpirationDate"];
In next View Controller, where you want to use the facebook with same session
_facebook.accessToken = [[NSUserDefaults standardUserDefaults] stringForKey:#"AccessToken"];
_facebook.expirationDate = (NSDate *) [[NSUserDefaults standardUserDefaults] objectForKey:#"ExpirationDate"];
if ([_facebook isSessionValid] == NO) {
//[_facebook authorize:kAppId permissions:self.permissions delegate:self]; //Create new facebook instance
}
Let me know if i put something which does not work for you.
Thanks
My iPhone app has a UIWebView that loads a page containing javascript that sets a cookie. It seems that if i set a cookie and exit the app within 10-15 seconds then the cookie is never saved, however if i set the cookie, wait 10-15 seconds THEN exit the app, the cookie is saved.
Anyone have any info about why their is a delay and how to go about having the cookies saved immediately.
The only workaround i was able to come up with is to save the cookies to the user defaults right before the app terminates. When the app is opened, go through the user defaults, pull out the cookies, and rewrite them to the cookie storage. It works but if your app is forcefully terminated then it doesnt really.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
[cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
// Load the saved cookies
NSDate *currentDate = [NSDate date];
NSTimeInterval expirationAmount = 5 * 365 * 24 * 60 * 60;
NSDate *expirationDate = [currentDate dateByAddingTimeInterval:expirationAmount];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
for (id theKey in [defaults dictionaryRepresentation]) {
if ([theKey hasPrefix:#"cookie:"]) {
[self setCookie:[theKey substringFromIndex:7] value:[defaults objectForKey:theKey] expiration:[expirationDate description] domain:urlDomain];
}
}
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Save the cookies to the user defaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray* theCookies = [cookieStorage cookies];
for(NSHTTPCookie *myStr in theCookies) {
[defaults setValue:[myStr value] forKey:[NSString stringWithFormat:#"cookie:%#", [myStr name]]];
}
[[NSUserDefaults standardUserDefaults] synchronize];
}
Having this same problem. The delay is actually 30 seconds exactly from my tests. I lost a couple days trying to debug this. There might be a way to work around this by manually re-saving the cookies before the 30 seconds has elapsed, but I haven't tried this yet.