Unable to login via Facebook (Parse): error code 251 - ios

I have an app in the App Store which is using Parse and automatically creates anonymous users (I set [PFUser enableAutomaticUser]). So now I have several thousands of users in a Parse users table.
Now I'm trying to implement full profiles and convert anonymous users to non-anonymous by calling:
[PFFacebookUtils linkUser:currentUser permissions:#[#"public_profile", #"email", #"user_friends"] block:^(BOOL succeeded, NSError *error) {
if (succeeded) {
//some logic
} else {
NSLog(#"Error: %#", error);
}
}];
BTW I've also tried:
[PFFacebookUtils logInWithPermissions:#[#"public_profile", #"email", #"user_friends"] block:^(PFUser *user, NSError *error) {
if (!user) {
NSLog(#"Uh oh. The user cancelled the Facebook login.");
} else if (user.isNew) {
NSLog(#"User signed up through Facebook!");
} else {
NSLog(#"User logged in through Facebook!");
}
}];
But in both cases I get an error: 251 - The supplied Facebook session token is expired or invalid.
What I've already tried:
Logout anonymous user
Refresh session
Close and re-auth session
Nothing here works for me. Does anyone know what to do in this case? How do I correctly convert anonymous user to non-anonymous?

I'm pretty sure the problem is your Facebook App configuration.
Please go to your Facebook App settings (Advanced section) https://developers.facebook.com/apps/YOUR_FB_APP_ID/settings/advanced/
You should have enabled the option "Native or desktop app?" When you do so, you'll have other option with the message "Is your App Secret embedded?" The error 251 on iOS only comes up when you enable this second option because your app secret is not embedded so the token is invalid.
Please go to your settings and make sure the option "Is your App Secret embedded?" is NOT enabled.
I hope it helps.

verify your fb dev account at "Approved Items" > "Login Permissions" must be the same as you requesting in your permissions array in your code. In my case I am using the new API 2.0.
Hope you help it.
Regards from Cancun

The problem for me was that i copied the App Secret when it was in dots, click on the show button in your Developer Settings and copy the string in there on to Parse.
Hope it helps.

Related

Firebase Phone Auth along with account linking

I am having a problem with phone authentication credentials persistence/expiry.
My scenario is like this:
I have a guest user, that I want to link with a phone number. The flow works perfectly if an account is not registered with that phone number. But if it does exist, then I have to:
SignIn and Unlink account.
Link account.
Sign In.
This requires 3 different credentials. But credentials expire for phone authentication after it gets used once - as per my understanding from the error message :
The SMS code has expired. Please re-send the verification code to try
again.
I do not want to ask user 3 times in a row for verification code on his mobile so new credentials can be generated. Any way to make credentials stick or a way around this problem ?
I can share the code if needed but I do not think it would be of any help.
Here is what you should do:
Initialize the phone auth credential first. Try to link that credential to the guest account always. If it fails with an error "credential already in user", the error userinfo will contain a new credential. This credential can then be used to sign in to the existing phone number account. Here is an example in objective-c.
[[FIRAuth auth].currentUser linkWithCredential:credential
completion:^(FIRUser *_Nullable user,
NSError *_Nullable error) {
if (user) {
// Successfully linked credential.
return;
}
if (error.code == FIRAuthErrorCodePhoneAlreadyInUse) {
// Save guest user data.
// Sign in the user instead if applicable.
FIRAuthCredential *credential = error.userInfo[FIRAuthUpdatedCredentialKey];
[[FIRAuth auth] signInWithCredential:credential
completion:^(FIRUser *_Nullable user,
NSError *_Nullable error) {
// copy guest user data to existing phone number user.
}];
return;
}
// Other errors.
}];
You can then programmatically copy the data of the guest user to the existing user and delete the guest user.
All this can be done efficiently with one SMS sent.

iOS ADAL-Make silent call using refresh token

I am using iOS ADAL library version 2.2.6 and receiving refresh token upon successful login. Now I want to make a silent call by using this refresh token. I tried with following method but it fails to return the access token.
ADAuthenticationContext *authContext;
[authContext acquireTokenSilentWithResource:resourceId
clientId:clientId
redirectUri:redirectUri
userId:strUserID //loggedIn userID
completionBlock:^(ADAuthenticationResult *result){
// It alway throws an error //Please call the non-silent acquireTokenWithResource methods.
if(result.error){
ADAuthenticationError *error = nil;
authContext = [ADAuthenticationContext authenticationContextWithAuthority:inputData.authority error:&error];
[authContext acquireTokenWithResource:inputData.ResourceID
clientId:inputData.ClientId // Comes from App Portal
redirectUri:inputData.RedirectUri // Comes from App Portal
completionBlock:^(ADAuthenticationResult *result)
{
if (AD_SUCCEEDED != result.status){
// Show alert with error description
}
else{
//Handle Success token
}
}];
}else{
//Handle Success token
}
}];
But it always throws an error saying "The user credentials are needed to obtain access token. Please call the non-silent acquireTokenWithResource methods."
Is there any way to make a silent call using refresh token? please help me on it. Thanks in advance.
When you use Microsoft's authentication libraries, you should always first check to see if there is a user in the cache that can be used for your resource before prompting the user to sign in. This allows us to check if the user had previously signed in to your app or if there are other apps that share state with your app that may have already asked the user to sign in elsewhere.
If the user is found, we will try to acquire a token without interrupting the user at all. Sometimes a user will have changed their password or done some other action that will require them to sign in again even if they have signed in to your app previously. This is what you are seeing. The library is telling you that for the user you are trying to acquire a token for, they need to sign in again to make something right.
In order to handle all these cases elegantly, we recommend that you use the pseudocode pattern of:
acquireTokenSilent()
(if error InteractiveAuthenticationRequired) {
acquireTokenInteractively() }
The pattern first checks if a user you specify is available in the token cache. If it is, we then call the Azure Active Directory service to see if the Refresh token for that user is valid. If both of these are true, then the user is signed in silently. If the user isn't found or the server rejects the Refresh Token, then an error is sent from the library that indicates the user needs to sign in interactively.
In the above, you are doing this first part, but you aren't handling the case where the user needs to sign in if there is a problem.
The best way is to catch the error with a ADErrorCode of AD_ERROR_USER_INPUT_NEEDED
Here is a code sample on how to do this pattern.
// Here we try to get a token from the stored user information we would have from a successful authentication
[authContext acquireTokenSilentWithResource:data.resourceId
clientId:data.clientId
redirectUri:redirectUri
userId:data.userItem.userInformation.userId
completionBlock:^(ADAuthenticationResult *result) {
if (!result.error)
{
completionBlock(result.tokenCacheStoreItem.userInformation, nil);
} else {
if ([result.error.domain isEqual:ADAuthenticationErrorDomain] && result.error.code == AD_ERROR_USER_INPUT_NEEDED) {
// Here we know that input is required because we couldn't get a token from the cache
[authContext acquireTokenWithResource:data.resourceId
clientId:data.clientId
redirectUri:redirectUri
userId:data.userItem.userInformation.userId
completionBlock:^(ADAuthenticationResult *result) {
if (result.status != AD_SUCCEEDED)
{
completionBlock(nil, result.error);
}
else
{
data.userItem = result.tokenCacheStoreItem;
completionBlock(result.tokenCacheStoreItem.userInformation, nil);
}
}];
} else {
completionBlock(nil, result.error);
}
}
}];
Keep in mind this code is very verbose. You will most likely want to have acquireTokenWithResource: a separate method that you could call with [self acquireTokenWithResource]

Pinterest SDK authenticate permission fail

I am trying to pin an image to pinterest. However, when I tried to authenticate the user, it fails.
I am calling the following code on button click, which takes me to pinterest app and the authentication dialog is shown,
[[PDKClient sharedInstance] authenticateWithPermissions:#[PDKClientReadPublicPermissions,
PDKClientWritePublicPermissions,
PDKClientReadPrivatePermissions,
PDKClientWritePrivatePermissions,
PDKClientReadRelationshipsPermissions,
PDKClientWriteRelationshipsPermissions]
withSuccess:^(PDKResponseObject *responseObject)
{
PDKUser *user = [responseObject user];
NSLog(#"%# authenticated!", user.firstName);
} andFailure:^(NSError *error) {
NSLog(#"authentication failed: %#", error);
}];
Also nothing prints in the console. I am unable to access the responseObject inside the block.
when I click okay, the authentication fails.
I have no idea where I could be wrong. I followed the steps mentioned in the pinteret/Developers . Can anyone guide me in the right way?
Probably there is an error in the callback URL you are passing and /or which is provided by you in the app settings. Check that Url, as a recommendation.

iOS8 Touch ID getting error : Pending UI mechanism already set

Description of error is below:
Error Domain=com.apple.LocalAuthentication Code=-1000 "Pending UI mechanism already set." UserInfo=0x17406b0c0 {NSLocalizedDescription=Pending UI mechanism already set.}
I am also trying Apple's Sample Example app and getting same error. Previously it was working fine, but it has stopped working suddenly ad not working. Please help.
I am using iPhone 6 with iOS 8.1
This code just worked fine for me.
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
NSString *myLocalizedReasonString = #"String explaining why app needs authentication";
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL success, NSError *error) {
if (success) {
// User authenticated successfully, take appropriate action
NSLog(#"User authenticated successfully, take appropriate action");
} else {
// User did not authenticate successfully, look at error and take appropriate action
NSLog(#"User did not authenticate successfully, look at error and take appropriate action");
}
}];
} else {
// Could not evaluate policy; look at authError and present an appropriate message to user
NSLog(#"Could not evaluate policy: %#",authError);
}
Don't forget to import Local Authentication framework <LocalAuthentication/LAContext.h>. Hope this will solve your issue.
Try rebooting your phone.
I also started getting this error and decided to see if other apps were affected. I have both Dropbox and Mint set up for Touch ID. Sure enough Touch ID wasn't working for them either and they were falling back to passcodes.
I rebooted my phone and it started working again, so it would seem the Touch ID can bug out and stop working. I'm on iOS 8.2 btw.
I guess the proper way to handle this condition is like those apps do and fallback to password / passcode.

Facebook request does not return email

No email is outputted from the Facebook request. How do I get this? I need it for my login/signup process
- (void)request:(FBRequest *)request didLoad:(id)result{
NSLog(#"FACEBOOK RESULT %# ", result);
}
This is the initial request:
[facebook requestWithGraphPath:#"me" andDelegate:self];
The email property cannot be obtained without requesting additional permission to obtain it, see https://developers.facebook.com/docs/reference/login/email-permissions/.
My application uses the following code to first check whether the Facebook session is valid (self.facebook is a Facebook object initialized with initWithAppId):
if (![self.facebook isSessionValid]) {
NSArray* permissions = [NSArray arrayWithObjects: #"email", nil];
[self.facebook authorize:permissions];
} else {
// Since we have a valid session we can get the userinfo
[self getFacebookUserInfo];
}
Your application prompt will indicate "Using this app requires: * Your basic info * Your e-mail address" If the user authorizes you to obtain this information your access token returned will have bits in set to allow you to obtain the e-mail address, and the following will work:
-(void)getFacebookUserInfo {
[self.facebook requestWithGraphPath:#"me" andDelegate:self];
}
assuming your -(void)request:(FBRequest *)request didLoad:(id)result method is available (which it appears that it is).
Note that the full flow of SSO (Single Sign On) is not given here in this post, you'll need to go through https://developers.facebook.com/docs/tutorials/ios-sdk-tutorial/#implementsso in detail.
Note also that you may be using a deprecated API for iOS 6, you should look at https://developers.facebook.com/docs/tutorial/iossdk/upgrading-from-2.0-to-3.1/ before going further.
With 2.4 api, parameters are used in order to specify which user data items you are interested in receiving.
E.g.:
FBSDKGraphRequestConnection *connection2 = [[FBSDKGraphRequestConnection alloc] init];
FBSDKGraphRequest *selfRequest = [[FBSDKGraphRequest alloc] initWithGraphPath:#"me?"
parameters:#{#"fields":#"id,name,first_name,last_name,verified,email"}];
[connection2 addRequest:selfRequest
completionHandler:^(FBSDKGraphRequestConnection *innerConnection, NSDictionary *result, NSError *error) {
if (error) {
NSLog(#"%#", error);
return;
}
if (result) {
// get user data
NSMutableDictionary *facebookUserData = [NSMutableDictionary dictionaryWithDictionary:result];
NSLog(#"result=%#", result);
HOWEVER, they apparently messed up big time, as email is NOT CURRENTLY being returned for DEVELOPERS, and currently in development Apps.
Incidentally, it is IMPOSSIBLE to submit bugs on Apps in development, as they require approved apps in the feedback system...
I wonder how do they think we are going to make sure that something works BEFORE submitting an app for approval, or what is the logic of asking for an App Store id of an App which can't be approved BEFORE Facebook integration can be tested to the fullest.
Besides, who is the genius at Facebook who decides to break working code one day from another?

Resources