AWS IOS SDK + Facebook Login Issue - ios

I am trying to log-in on Facebook with AWS IOS SDK, my code as below:
[[AWSFacebookSignInProvider sharedInstance] setPermissions:#[#"public_profile",#"email",#"user_friends"]];
[[AWSFacebookSignInProvider sharedInstance] setViewControllerForFacebookSignIn:self];
[[AWSIdentityManager defaultIdentityManager]
loginWithSignInProvider:[AWSFacebookSignInProvider sharedInstance]
completionHandler:^(id result, NSError *error) {
if (error) {
NSLog(#"^Login in with SignIn Provider has failed: %#", error);
completion(NO);
return;
}
completion(YES);
}];
In response of loginWithSignInProvider, I am getting an error as below:
Error Domain=com.facebook.sdk.login Code=306 "Access has not been granted to the Facebook account. Verify device settings." UserInfo={NSLocalizedDescription=Access has not been granted to the Facebook account. Verify device settings., com.facebook.sdk:FBSDKErrorLocalizedDescriptionKey=Access has not been granted to the Facebook account. Verify device settings.}
Here I am using Xcode 9.2 and IOS 11.0, Can please help me to solve that issue.

Try this:
+ (instancetype)sharedInstance {
static AWSFacebookSignInProviderCustom *_sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedInstance = [AWSFacebookSignInProviderCustom new];
});
return _sharedInstance;
}
- (void)login
{
if (!self.facebookLogin)
self.facebookLogin = [FBSDKLoginManager new];
[self.facebookLogin logInWithReadPermissions:#[#"public_profile", #"email", #"user_friends"]
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
NSLog(#"Error!");
} else if (result.isCancelled)
{
// Login canceled, do nothing
NSLog(#"Cancelled!");
} else {
NSLog(#"FSBKDAccess Token: %#", [FBSDKAccessToken currentAccessToken]);
[[AWSFacebookSignInProvider sharedInstance] login];
}
}];
}

Related

View showing up with delay after Facebook Authentication

I am using following code to display a toast after Facebook authentication
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) // check Fb is configured in Settings or not
{
accountStore = [[ACAccountStore alloc] init]; // you have to retain ACAccountStore
ACAccountType *fbAcc = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSString *key = #"xxxxx";
NSDictionary *dictFB = [NSDictionary dictionaryWithObjectsAndKeys:key,ACFacebookAppIdKey,#[#"email"],ACFacebookPermissionsKey, nil];
[accountStore requestAccessToAccountsWithType:fbAcc options:dictFB completion:^(BOOL granted, NSError *error) {
if (granted) {
NSLog(#"Perform fb registration");
} else {
NSLog(#"Facebook 1”);
[[Toast shared] showToast:self.view withText:#"You disabled your app from settings."];
NSLog(#"Facebook 2”);
}
}];
}
NSLog(#"Facebook 1”); and NSLog(#"Facebook 2”); are executing and printing logs respectively. However, toast statement in between these two logs delays and displays after 15-20 seconds.
If I put toast statement [[Toast shared] showToast:self.view withText:#"You disabled your app from settings."]; out of following completion handler:
[accountStore requestAccessToAccountsWithType:fbAcc options:dictFB completion:^(BOOL granted, NSError *error) {
}];
It works fine and displays toast timely, never delays. Any solution to remove the delay?
I believe what EDUsta said is correct. Try calling the toast message on the main thread. All UI changes should be handled on the main thread to avoid weird bugs. Try this:
[accountStore requestAccessToAccountsWithType:fbAcc options:dictFB completion:^(BOOL granted, NSError *error) {
if (granted) {
NSLog(#"Perform fb registration");
} else {
NSLog(#"Facebook 1”);
dispatch_async(dispatch_get_main_queue(), ^{
[[Toast shared] showToast:self.view withText:#"You disabled your app from settings."];
});
NSLog(#"Facebook 2”);
}
}];

Cannot post to Facebook using iOS app

I am creating an iOS app. I need to post some links to Facebook events using my app. I have integrated Facebook SDK. By using Facebook Graph API, i found the code for the same and it works fine in Graph API Explorer. But it does not working in my app. When trying to post the link to Facebook,it shows the following error. I am using Xcode 7.3 and iOS 9.
error=Error Domain=com.facebook.sdk.core Code=8 "(null)" UserInfo={com.facebook.sdk:FBSDKGraphRequestErrorCategoryKey=0, com.facebook.sdk:FBSDKGraphRequestErrorHTTPStatusCodeKey=403, com.facebook.sdk:FBSDKErrorDeveloperMessageKey=(#200) Insufficient permission to post to target on behalf of the viewer, com.facebook.sdk:FBSDKGraphRequestErrorGraphErrorCode=200, com.facebook.sdk:FBSDKGraphRequestErrorParsedJSONResponseKey={
body = {
error = {
code = 200;
"fbtrace_id" = DWR8SW4K1Ls;
message = "(#200) Insufficient permission to post to target on behalf of the viewer";
type = OAuthException;
};
};
code = 403;
My code is given below.
-(void)postToFacebook
{
if ([[FBSDKAccessToken currentAccessToken] hasGranted:#"publish_actions"]) {
[self post];
// TODO: publish content.
} else {
FBSDKLoginManager *loginManager = [[FBSDKLoginManager alloc] init];
[loginManager logInWithPublishPermissions:#[#"publish_actions"]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if(error)
{
NSLog(#"error=%#",error);
}
else{
[self post];
}
//TODO: process error or result.
}];
}
}
-(void)post
{
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc]
initWithGraphPath:3466734743/feed
parameters:#{ #"link": #"http://www.dhip.in/ofc/metatest.html",}
HTTPMethod:#"POST"];
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
// Insert your code here
if(error)
{
NSLog(#"error=%#",error);
}
else
{
NSLog(#"success");
}
}];
}
And i have looked into https://developers.facebook.com/docs/ios/ios9 and tried all the combination of LSApplicationQueriesSchemes in my info.plist.Please help me.What is the problem? Why i can't post to Facebook?
SLComposeViewController *fbCompose;
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
fbCompose=[[SLComposeViewController alloc]init];
fbCompose=[SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[fbCompose setInitialText:#"My Score in AlphaMarics is"];
[fbCompose addImage:image];
[self presentViewController:fbCompose animated:YES completion:nil];
}
[fbCompose setCompletionHandler:^(SLComposeViewControllerResult result)
{
NSString * fbOutput=[[NSString alloc]init];
switch (result){
case SLComposeViewControllerResultCancelled:
fbOutput=#"You Post is cancelled";
break;
case SLComposeViewControllerResultDone:
fbOutput=#"Your post Posted Succesfully";
break;
default:
break;
}
UIAlertView * fbAlert=[[UIAlertView alloc]initWithTitle:#"Warning" message:fbOutput delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[fbAlert show];
}];

Upload Facebook Photo And Auto Log User Out (Kiosk App)

I have an iPad app designed for use in a kiosk environment.
The user flow should be
Take Photo
Choose photo from iPad Album view
Share to Facebook and / or Twitter
Automatically log user out after image has been posted
I have the auto-logout of Twitter working properly, my issue is with the Facebook portion.
I have implemented the Graph API for internal testing, and would love to be able to post a complete story this way, but I don't think there is a way to log out from the Facebook app once the authorization and post is complete.
For a fallback, I can use the Feed Dialog and auto-logout from there, but as far as I can tell, there is no way to upload a local image for sharing to Facebook from there.
My Facebook Sharing code is as follows:
- (IBAction)facebookShare:(id)sender {
/// Package the image inside a dictionary
NSArray* image = #[#{#"url": self.mergeImages, #"user_generated": #"true"}];
// Create an object
id<FBGraphObject> object =
[FBGraphObject openGraphObjectForPostWithType:#"me/feed:photo"
title:#"a photo"
image:self.mergeImages
url:nil
description:nil];
// Create an action
id<FBOpenGraphAction> action = (id<FBOpenGraphAction>)[FBGraphObject graphObject];
// Set image on the action
[action setObject:image forKey:#"image"];
// Link the object to the action
[action setObject:object forKey:#"photo"];
// Hardcode the location based on Facebook Place ID
id<FBGraphPlace> place = (id<FBGraphPlace>)[FBGraphObject graphObject];
[place setId:#"279163865580772"]; // Singley + Mackie
[action setPlace:place];
// Check if the Facebook app is installed and we can present the share dialog
FBOpenGraphActionShareDialogParams *params = [[FBOpenGraphActionShareDialogParams alloc] init];
params.action = action;
params.actionType = #"me/feed:share";
// If the Facebook app is installed and we can present the share dialog
if([FBDialogs canPresentShareDialogWithOpenGraphActionParams:params]) {
// Show the share dialog
[FBDialogs presentShareDialogWithOpenGraphAction:action
actionType:#"photo_overlay:share"
previewPropertyName:#"photo"
handler:^(FBAppCall *call, NSDictionary *results, NSError *error) {
if(error) {
// An error occurred, we need to handle the error
// See: https://developers.facebook.com/docs/ios/errors
// NSLog([NSString stringWithFormat:#"Error publishing story: %#", error.description]);
} else {
// Success
NSLog(#"result %#", results);
}
}];
// If the Facebook app is NOT installed and we can't present the share dialog
} else {
// Put together the Feed dialog parameters
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"name",
#"caption",
#"description",
#"link",
#"picture",
nil];
// Show the feed dialog
[FBWebDialogs presentFeedDialogModallyWithSession:nil
parameters:params
handler:^(FBWebDialogResult result, NSURL *resultURL, NSError *error) {
if (error) {
// An error occurred, we need to handle the error
// See: https://developers.facebook.com/docs/ios/errors
// NSLog([NSString stringWithFormat:#"Error publishing story: %#", error.description]);
} else {
if (result == FBWebDialogResultDialogNotCompleted) {
// User cancelled.
NSLog(#"User cancelled.");
} else {
// Handle the publish feed callback
NSDictionary *urlParams = [self parseURLParams:[resultURL query]];
if (![urlParams valueForKey:#"post_id"]) {
// User cancelled.
NSLog(#"User cancelled.");
} else {
// User clicked the Share button
NSString *result = [NSString stringWithFormat: #"Posted story, id: %#", [urlParams valueForKey:#"post_id"]];
NSLog(#"result %#", result);
}
}
}
// Auto log the user out
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSLog(#"defaults fbDidLogout ........%#",defaults);
if ([defaults objectForKey:#"FBAccessTokenKey"])
{
[defaults removeObjectForKey:#"FBAccessTokenKey"];
[defaults removeObjectForKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
NSHTTPCookie *cookie;
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [storage cookies])
{
NSString* domainName = [cookie domain];
NSRange domainRange = [domainName rangeOfString:#"facebook"];
if(domainRange.length > 0)
{
[storage deleteCookie:cookie];
}
}
[FBSession.activeSession closeAndClearTokenInformation];
}];
}
}
// A function for parsing URL parameters.
- (NSDictionary*)parseURLParams:(NSString *)query {
NSArray *pairs = [query componentsSeparatedByString:#"&"];
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
for (NSString *pair in pairs) {
NSArray *kv = [pair componentsSeparatedByString:#"="];
NSString *val =
[kv[1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
params[kv[0]] = val;
}
return params;
}
I have searched Stack Overflow far and wide for an answer to this, but have found no solutions.
I was finally able to figure this out! Posting the answer here to hopefully benefit others who are in the same situation.
First, add the following to your AppDelegate.m:
-(BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [FBAppCall handleOpenURL:url sourceApplication:sourceApplication fallbackHandler:^(FBAppCall *call) {
// Facebook SDK * App Linking *
// For simplicity, this sample will ignore the link if the session is already
// open but a more advanced app could support features like user switching.
if (call.accessTokenData) {
if ([FBSession activeSession].isOpen) {
NSLog(#"INFO: Ignoring app link because current session is open.");
}
else {
[self handleAppLink:call.accessTokenData];
}
}
}];
}
// Helper method to wrap logic for handling app links.
- (void)handleAppLink:(FBAccessTokenData *)appLinkToken {
// Initialize a new blank session instance...
FBSession *appLinkSession = [[FBSession alloc] initWithAppID:nil
permissions:nil
defaultAudience:FBSessionDefaultAudienceNone
urlSchemeSuffix:nil
tokenCacheStrategy:[FBSessionTokenCachingStrategy nullCacheInstance] ];
[FBSession setActiveSession:appLinkSession];
// ... and open it from the App Link's Token.
[appLinkSession openFromAccessTokenData:appLinkToken
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
// Forward any errors to the FBLoginView delegate.
if (error) {
//[self.loginViewController loginView:nil handleError:error];
}
}];
}
Wherever you are calling the posting action in your app, add this line to your header file:
#property (strong, nonatomic) FBRequestConnection *requestConnection;
And the following to your implementation file:
#synthesize requestConnection;
- (IBAction)facebookShare:(id)sender {
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"publish_actions", #"publish_checkins", nil];
UIImage *img = self.facebookImage;
[FBSession openActiveSessionWithPublishPermissions:permissions
defaultAudience:FBSessionDefaultAudienceEveryone allowLoginUI:YES
completionHandler:^(FBSession *session,FBSessionState s, NSError *error) {
[FBSession setActiveSession:session];
if (!error) {
// Now have the permission
[self processPostingImage:img WithMessage:#"Enter_your_message_here"];
} else {
// Facebook SDK * error handling *
// if the operation is not user cancelled
if (error.fberrorCategory != FBErrorCategoryUserCancelled) {
[self presentAlertForError:error];
}
}
}];
}
-(void)logout {
[FBSession.activeSession closeAndClearTokenInformation];
[FBSession.activeSession close];
[FBSession setActiveSession:nil];
}
- (void)processPostingImage:(UIImage *) img WithMessage:(NSString *)message {
FBRequestConnection *newConnection = [[FBRequestConnection alloc] init];
FBRequestHandler handler =
^(FBRequestConnection *connection, id result, NSError *error) {
// output the results of the request
[self requestCompleted:connection forFbID:#"me" result:result error:error];
};
FBRequest *request=[[FBRequest alloc] initWithSession:FBSession.activeSession graphPath:#"me/photos" parameters:[NSDictionary dictionaryWithObjectsAndKeys:UIImageJPEGRepresentation(img, 0.7),#"source",message,#"message",#"{'value':'EVERYONE'}",#"privacy", nil] HTTPMethod:#"POST"];
[newConnection addRequest:request completionHandler:handler];
[self.requestConnection cancel];
self.requestConnection = newConnection;
[newConnection start];
}
// FBSample logic
// Report any results. Invoked once for each request we make.
- (void)requestCompleted:(FBRequestConnection *)connection
forFbID:fbID
result:(id)result
error:(NSError *)error
{
// not the completion we were looking for...
if (self.requestConnection &&
connection != self.requestConnection)
{
return;
}
// clean this up, for posterity
self.requestConnection = nil;
if (error)
{
}
else
{
[self logout];
};
}
- (void) presentAlertForError:(NSError *)error {
// Facebook SDK * error handling *
// Error handling is an important part of providing a good user experience.
// When fberrorShouldNotifyUser is YES, a fberrorUserMessage can be
// presented as a user-ready message
if (error.fberrorShouldNotifyUser) {
// The SDK has a message for the user, surface it.
[[[UIAlertView alloc] initWithTitle:#"Something Went Wrong"
message:error.fberrorUserMessage
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil] show];
} else {
}
}
Note:
To make this work with auto-logout, you also have to disable Safari on the device. This can be done by going to Settings > General > Restrictions > Allow Safari > Off. Once that is turned off, the Facebook IBAction will popup a UIWebView inside the app itself. When tapped, the current user can enter their Facebook credentials, then the app will post the image, and log the user out so the next user can use the app without having access to the previous user's Facebook details.

Facebook SDK: incorrect login behaviour. Push safari login window in session state "open"

Situation:
Person login in FBApp but not login in System FB account.
What I do:
I ask readPermissions and publishPermissions. After that I send request for person identity (id,name,username,profile_picture_url).
Behaviour:
Everything works fine, facebook ios sdk go to fb app twice (for each request - read and publish) and after that miracle appears.
I request for person identity and see facebook window, which suggest to download fb app for iPhone (fb app've been already on it!) and ask me to login on website. I think that this is a safari login appears.
Code:
/*login here*/
if([_facebookSession state] == FBSessionStateCreated){
[FBSession openActiveSessionWithReadPermissions:readPermissions allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if (error || status == FBSessionStateClosedLoginFailed){
[_facebookSession openWithBehavior:FBSessionLoginBehaviorWithNoFallbackToWebView completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if (error || status == FBSessionStateClosedLoginFailed){
LoginFailedBlock(YES);
}
else
if (error == nil && status == FBSessionStateOpen){
_facebookSession = session;
LoginSucessBlock(YES);
}
}];
}else{
dispatch_async(dispatch_get_current_queue(), ^{
[FBSession openActiveSessionWithPublishPermissions:publishPermissions defaultAudience:FBSessionDefaultAudienceFriends allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if (error == nil && status == FBSessionStateOpen){
_facebookSession = session;
LoginSucessBlock(YES);
}
}];
});
}
}];
/*request for person identity*/
/*SOMEWHERE HERE A SAFARI LOGIN WINDOW APPEARS*/
[FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, id<FBGraphUser> result, NSError *error) {
if (error){
ErrorBlock(error);
}
else{
if ([result id] && [result name]){
NSDictionary* resultDictionary = #{#"id":result.id,
#"name":result.name,
#"username":result.username,
#"picture":result.link,
};
AfterLoadUserInfoBlock(YES,resultDictionary);
}
else{
AfterLoadUserInfoBlock(NO,nil);
}
}
}];
in view controller :
self.loginview = [[FBLoginView alloc] init];
self.loginview.frame = CGRectMake(-500, -500, 0, 0);
[self.view addSubview:self.loginview];
self.loginview.delegate = self;
[loginview setReadPermissions:#[#"basic_info",#"email"]];
[loginview setDelegate:self];
-(IBAction)loginWithFB:(id)sender{
for(id object in self.loginview.subviews){
if([[object class] isSubclassOfClass:[UIButton class]]){
UIButton* button = (UIButton*)object;
[button sendActionsForControlEvents:UIControlEventTouchUpInside];
}
}
}
in appdelegate :
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// Call FBAppCall's handleOpenURL:sourceApplication to handle Facebook app responses
BOOL wasHandled = [FBAppCall handleOpenURL:url sourceApplication:sourceApplication];
// You can add your app-specific url handling code here if needed
return wasHandled;
}
then please register your application in developer.facebook.com with your bundle id finally you will get one id and configure in your plist file

EvernoteSession authenticateWithViewController:completionHandler: does not trigger completionHandler

When I authenticate within the iPhone Simulater in debug mode the first if statement in the code below is run. However, when I debug on an iPhone that has the Evernote client installed the if statement does not appear evaluated. Instead the Evernote iOS app comes up for just a moment, then straight back to this ViewController without hitting any set breakpoints below the if, or the segue being fired.
Any ideas?
[session authenticateWithViewController:self completionHandler:^(NSError *error) {
if (error || !session.isAuthenticated){
if (error) {
NSLog(#"Error authenticating with Evernote Cloud API: %#", error);
}
if (!session.isAuthenticated) {
NSLog(#"Session not authenticated");
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Could not authenticate"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
} else {
// We're authenticated!
EvernoteUserStore *userStore = [EvernoteUserStore userStore];
[userStore getUserWithSuccess:^(EDAMUser *user) {
// success
NSLog(#"Authenticated as %#", [user username]);
[self performSegueWithIdentifier:#"introductionStepOne" sender:self];
} failure:^(NSError *error) {
// failure
NSLog(#"Error getting user: %#", error);
} ];
}
}];
Make sure you modify your AppDelegate properly. More information here : https://github.com/evernote/evernote-sdk-ios#modify-your-appdelegate
You need to add :
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication: (NSString *)sourceApplication annotation:(id)annotation {
BOOL canHandle = NO;
if ([[NSString stringWithFormat:#"en-%#", [[EvernoteSession sharedSession] consumerKey]] isEqualToString:[url scheme]] == YES) {
canHandle = [[EvernoteSession sharedSession] canHandleOpenURL:url];
}
return canHandle;
}
And
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
[[EvernoteSession sharedSession] handleDidBecomeActive];
}

Resources