Android Facebook API errors with SSO when Facebook App installed - android

I have been messing with the facebook API/SDK for a while now as I integrate it into an app I am working on. The only real facebook feature I need is checkins, and they work. Most of the time. And here begins my problem.
After looking over the facebook API. I am starting to suspect that either I'm not understanding the API fully, or it is extremely buggy and lacking some important features (like logout?!).
My main problem with these said bugs is that if I have my application checking in to facebook perfectly (on all accounts, not just developer), and then I install the facebook application in order to change users, then the checkin process through my app will not work unless and until I uninstall the facebook application. I have seen several posts about it, but the topic has to my knowledge never been fully discussed here.
I would normally have been more direct with my question, but I fear I may simply be using the api like a moron, and would like to first make sure that this is an actual issue for others besides just me (especially before I commit to the idea that facebook has no idea what they are doing with the API), and second, see if there is any workaround (maybe even the easy facebook library).
Thanks in advance for any advice and/or confirmation of these issues.
EDIT:
So I ended up using the Easy Android facebook Sdk (http://www.easyfacebookandroidsdk.com/). It has poor documentation, but the examples show you enough of what to do that you can mess with it to work.
But my question about how/why facebook can just not include this in their api still stands

This solution worked for me after no other solution did (Cygwin, openssl, wrong alias, wrong password)
The problem is that Windows generates an invalid key.
Run this with your app:
try {
PackageInfo info = getPackageManager().getPackageInfo("**YOURPACKAGENAME**", PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
Log.i("PXR", Base64.encodeBytes(md.digest()));
}
}
catch (NameNotFoundException e) {}
catch (NoSuchAlgorithmException e) {}
Don't forget to get Base64 (http://iharder.sourceforge.net/current/java/base64/).
The generated key is on your logcat, replace the old one with this.
Solution thanks to: http://p-xr.com/implementing-facebook-into-your-app-invalid-key-with-keytool/

If you get invalid_key when the FB app is installed its due to the wrong key you're using.
When running keytool with the debug key such as:
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
Be sure to enter 'android' as password, and not your keystore password. To verify, make sure the key that you get is not ga0RGNYHvNM5d0SLGQfpQWAPGJ8= but should be something else.
In order to 'logout' try calling SessionStore.clear()

I forgot to update my progress with this. I ended up going with the easy facebook android api because even though it has bugs, it is actively developed, and not a utter useless piece of crap.
For any having the same problems of facebook not fixing their software bugs, check out http://www.easyfacebookandroidsdk.com/

As Guy said, an invalid Key Hash may be the problem. In my case, it turns out that was actually it. Jessy, if that is not your problem, you might want to have a look at the error message generated by the AuthListener.
Before logging in, you probably assign an Authentication listener to the session:
SessionEvents.addAuthListener(new FbAPIsAuthListener());
Now, just go to the function where you implement the listener and try to catch the error:
/*
* The Callback for notifying the application when authorization succeeds or
* fails.
*/
public class FbAPIsAuthListener implements AuthListener {
#Override
public void onAuthSucceed() {
requestUserData();
}
#Override
public void onAuthFail(String error) {
//Could not authenticate. Check error message.
System.out.println("Login error due to " + error)
}
}
Hope that helps.

Related

Tampered Android App Has Original Signature

What I Have
I have an Android app with some sensitive data. I want to make sure that the client app calls the server only if it has not been tampered with in any way. Basically, I want to check the integrity of the Android app.
What I Have Done
For that, I have implemented a method that can check if the signature is same as the signature I have signed the APK with. Here is a code sample,
fun isApkSignatureBroken(): Boolean {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, GET_SIGNATURES)
val signatures = packageInfo.signatures
if (signatures == null || signatures.isEmpty()) {
return true
}
return signatures
.map { it.toByteArray() }
.map { hash.getSha1(it) }
.none { it.equals(getRealAppSignature(), true) }
}
Here, getRealAppSignature() returns my actual signature with which I have signed the app.
Observations
I have seen this method to work well sometimes. Whenever a tampered app is discovered, this method returns true and the user is blocked from using the app and I am notified by an event. I have found many users being blocked in this way.
I have seen many other cases being reported in forums and other social media sites, that people are using my app even if they are having tampered apps. I have observed many of my apps having malformed version names and application names being used by many users. Like, if my original apps version is 2.2 then they will create a malformed version 2.2-TERMINATOR.
Analysis
I did some analysis on the apps and found some tampered apps from some forums. Those are clearly modded apps having malformed version and application names. Some even have minor UI changes. I tried to install those apps, but they can't be installed with the message "Package is corrupted".
I tried to run keytool on those apps to check their signature, like this,
keytool -list -printcert -jarfile TAMPERED_APP.apk
but I always got,
keytool error: java.lang.SecurityException: SHA1 digest error for classes.dex
I finally rooted my device, installed Xposed Framework and disabled "App Signature Verification" and then was able to install those apps. What I found was that the app was not getting blocked as my signature checking method always returned "false". That means, it always found the original signature inside the apk.
More Analysis
I spend some more time and was able to unpackage the APK using ApkTool. Inside the META-INF folder I found the CERT.RSA to only contain my original signature and no other signature. I opened the MANIFEST.MF file and found that all the entries have different SHA1 than my original APKs manifest file.
It clearly means that the app was modified and was signed by another signature (hence the change in MANIFEST.MF) but my CERTIFICATE.RSA only had my original signature because of which my app always got the original SHA from PackageManager.
Questions
How is the app being re-signed but the new signature is not stored in CERTIFICATE.RSA?
Why is my original certificate still present in CERTIFICATE.RSA?
If the app was resigned, then multiple signatures should be present? But that is true here.
In this situation, how do I detect that the app has been tampered with? Is there any way I can compute the SHA of the app myself instead of querying the PackageManager?
EDIT #1: The entire code is obfuscated using DexGuard. So, the chance of the tamper detection logic getting messed up is pretty less.

Android App Signature Key

I want to get the key-hash from signed signature of my Android App so that I can integrate facebook login in my android app. I have created the signed signature using AndroidTools-->Export Signed Application Package. How can I read the key generated in the signature file.
Solution 1:
Try this link: http://www.helloandroid.com/tutorials/using-facebook-sdk-android-development-part-1. I found that using the Facebook method of getting a Hash Key did not always work as advertised. This link however, has a different method of getting the Hash Key and has pretty much always worked.
Solution 2:
That being said, I always found the simplest thing to do was, let the Facebook SDK tell you what your Hash Key is. This is by far more simpler and shouldn't take more than a couple of minutes.
Step 1: In your Facebook SDK, locate the Util.java class. In that, change this:
private static boolean ENABLE_LOG = false;
to:
private static boolean ENABLE_LOG = true;
Step 2: Create a new Signed APK, transfer to your device and install. If it is already installed, naturally, it will prompt.
Step 3: With your DDMS (Logcat) running and your device connected to the computer, run the application and keep looking for a key mismatch warning. That warning has the actual Hash Key. Copy that key, go to your Facebook Developer page and add the new key to the list.

Hashkey mismatch android facebook app

Downloaded recent facebook android sdk 3.7 and i tried to run sample apps in the sdk. When I tried helloFacebookSample app i got hashkey problem. I searched through web and got my hashkey correct i.e DSygOIIJUkYyHy/duT1e72ZHl5U=.
My app is showing "hashkey not stored" error. When I logged my sample app hashkey I found strange thing happening.
I am using this code:
Toast.makeText(getApplicationContext(),Base64.encodeToString(md.digest(), Base64.DEFAULT), Toast.LENGTH_LONG).show();
Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
Toast.makeText(getApplicationContext(),Base64.encodeToString(md.digest(), Base64.DEFAULT), Toast.LENGTH_LONG).show();
Same piece of code is showing different hashkeys
DSygOIIJUkYyHy/duT1e72ZHl5U=
2jmj7l5rSw0yVb/vlWAYkK/YBwk=
and when I try to post status it shows a different hashkey.
DSygOIIJUkYyHy_duT1e72ZHl5U=
I have stored all three hashkeys in my sample app, and it is still showing me this error.
This problem usually comes when hashkey generated by your app doesnt match with the one which you have put in facebook developers site. Try to generate the hashkey programmatically and put it in developers site. Hope this solution helps
The same problem occurred to me , i had no idea what gone wrong ,then i realized that that key store that i used to generate the key hash was a different one ,if you have signed your app you will get a .jks key store file ,you have to specify that path of the file in the code generating the key hash like
keytool -list -v -keystore yourkeystore_path/yourkeystore.jks -alias your_aliase_name
the names of the keystore file and aliases name should be same as the one when you signed your app then your get the correct code for sure.
then there also a work around just write down the code displaying in the error and put it in the keyhash field simple as that...
hope it helps

Android Google Plus getCurrentPerson returns null

When I'm calling plusClient.getCurrentPerson() I am getting NULL.
Method onConnected(Bundle...) called after a successful login:
#Override
public void onConnected(Bundle bundle)
{
if (plusClient.getCurrentPerson() == null)
{
Log.e("DD", "Person is null !");
}
}
I have added SHA1 directly from eclipse (Window->Preferences->Android->Build). I don't know what I am doing wrong!
SHA1 fingerprint from Eclipse ADT
Client ID for installed applications
Simple API access
In my case I forgot to enable permission for google-plus
Hope it works...Any doubt let me know
Check from scratch:
Sometime person info may be null
check : PERMISSIONS
Important things to do:
Enable Google plus API
Enable Google Maps Android API
If you test locally then add sha1 key in eclipse-->window-->preference option-->Android-->Build
OR
You can generate SHA1 key through command prompt
keytool -list -v -keystore "C:\Users\User.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
If you are publishing app in play-store then you need to change SHA1 key in google console
because in local SHA1 key is different . After doing signedApk SHA1 key is different
While generating signed apk -->in the last screen -->you can see SHA1 key
After adding in google console you will get API key
Add this key in Manifest file
I just found out that you need to pass multiple scopes when you're building the PlusClient object:
PlusClient plusClient = new PlusClient.Builder(this, this, this).setScopes(Scopes.PLUS_LOGIN, Scopes.PLUS_PROFILE ,"https://www.googleapis.com/auth/userinfo.email").build();
I encountered this today. This is an old post but I think others should know how I fixed this in Android Studio and what was the source of the problem.
I spent the last 6 hours with this and the problem was that a week ago I changed the package name using Refactoring from Android Studio but something must have gotten wrong since would always return me null, even though I refactored the project back to it's original package.
I fixed this by creating a new project, without closing the original, but using the same package name and the same login code from the original project and to my surprise it worked. The name of the new project was different but I named the package the same as the old one and it only had a button and code to manage the connection and nothing else.
The new project would read the data as it should and now the old project somehow got back on his feet and started reading the current user.
I closed the project with Close Project option from the File menu.
Best regards !
Please check your phone network. you can use those codes below to check:
Plus.PeopleApi.loadVisible(mGoogleApiClient, null).setResultCallback(this);
#Override
public void onResult(LoadPeopleResult result) {
Log.d(TAG, "result.getStatus():" + result.getStatus());
}
if the result status is network error. the current person will be null.
I'm in China, so as you know if we want to connect the google service , sometimes we need a good agent 。
This looks like a permissions issue. I added payment details in the Google API Console and it magically started working.

App is misconfigured for Facebook login : Kindle Fire Integration Issue

We integrated Facebook login on our Kindle Fire android app. It works without any problem most of the time. But occasionally for some users, when they try to register using facebook login, it fails with the error "APp is misconfigured for facebook login". We checked the hash key, package name and all that, they all are correct. As i said, it works for 95% of the users. For those users it fails, it fails repeatedly. Anybody from facebook can help us resolve this issue? Appreciated. (BTW, we use the same facebook app for our google play version of the android app also with a different hash key, we never had this problem for our google play app. We got the hash key for Kindle from Amazon.) Since it doesnt fail in any of our devices, and fails only on some random user's devices, we couldnt get any debug messages.
PS: I have already read the thread App is misconfigured for Facebook login: Android Facebook integration issue . I am a new user, i couldnt ask this question over there.
We just had the same problem with one of our apps on the Amazon appstore. In our case we realized the problem only happened if these three conditions were true:
Kindle Fire HD
Facebook App installed and user logged in
User also logged into facebook via Settings -> My Account -> Manage Social Accounts
That may explain why in your case it only happens in 5% of the cases.
As far as we could tell, Amazon resigns the .apk, which breaks the Facebook Android App Key Hash check.
The solution involved:
Obtaining the Amazon .apk of our app (not the one we submitted, but the one distributed by the Amazon appstore)
Extract the signing certificate from the .apk file
Base64 encode the SHA digest of the encoded certificate
Add the resulting Base64 key hash to our Facebook App settings
This fixed the problem.
Getting the .apk proved tricky. Applications reside in the /data/app folder of the device's filesystem. However, this directory is protected to prevent listing it, so unless you know the name of the file you're looking for, you're out of luck. You can of course, root the device. Alternatively you can try your blind luck by doing adb pull /data/app/<app-id><suffix>.apk where suffix is either an empty string or -1, -2, etc, until you succeed. E.g.:
$ adb pull /data/app/com.example.game.apk
remote object '/data/app/com.example.game.apk' does not exist
$ adb pull /data/app/com.example.game-1.apk
remote object '/data/app/com.example.game-1.apk' does not exist
$ adb pull /data/app/com.example.game-2.apk
3658 KB/s (1085140 bytes in 0.289s)
If this approach fails, rooting might be the only option.
Once you have the .apk file, you can use the code below to obtain the key hash. Save as Main.java, compile with javac Main.java and run with java Main <APK>, e.g.:
$ javac Main.java
$ java Main com.example.game-1.apk
com.example.game-1.apk: 478uEnKQV+fMQT8Dy4AKvHkYibo=
Adding 478uEnKQV+fMQT8Dy4AKvHkYibo= to the key hashes of our Facebook App settings then fixes the problem. I'm curious if other people find the same hash we got (which would mean all Amazon games are resigned with the same key). In our case, the hash started with wwYPegrz....
Here's the code:
import java.security.MessageDigest;
import java.security.cert.Certificate;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import sun.misc.BASE64Encoder;
public class Main {
public static void main(String[] args) throws Exception {
for (String jarFilename : args)
extractHash(jarFilename);
}
private static void extractHash(String jarFilename) throws Exception {
BASE64Encoder base64 = new BASE64Encoder();
MessageDigest sha1 = MessageDigest.getInstance("SHA");
Set<Certificate> certificates = new HashSet<Certificate>();
JarFile jarFile = new JarFile(jarFilename);
for (JarEntry jarEntry : Collections.list(jarFile.entries())) {
jarFile.getInputStream(jarEntry).skip(Long.MAX_VALUE);
Certificate[] certs = jarEntry.getCertificates();
if (certs == null)
continue;
certificates.addAll(Arrays.asList(certs));
}
System.out.printf("%s:", jarFilename);
for (Certificate cert : certificates) {
byte[] digest = sha1.digest(cert.getEncoded());
System.out.printf(" %s", base64.encode(digest));
}
if (certificates.isEmpty())
System.out.printf(" NOT SIGNED!");
System.out.println();
jarFile.close();
}
}
#Blanka's answer is technically correct, however I found an easier way: Simply go to Amazon developer console and copy the value I have highlighted in the red rectangle:
The solution from Blanka works.
However, here's another solution easier to do if you can reproduce the issue on a Kindle Fire.
Retrieve from LogCat the authentication request sent by Facebook:
03-13 15:21:19.360: D/WebCore(26863): *-* Total load time: 1535.31 ms, thread time: 287.00 ms for
https://m.facebook.com/dialog/oauth?android_key=XXXXXXXXXXXXX&calling_package_key=<app_package_id>
&client_id=YYYYYYYYYYYY&display=touch&redirect_uri=fbconnect%3A%2F%2Fsuccess&scope=email%
2Cpublish_stream&type=user_agent&_rdr
android_key parameter is the Hash Key of your app.
You need to add this key on the Facebook Dashboad.
Note: Be careful, the encoding format of your hash may in the https request be different that the one needed by Facebook.
I think the problem with hashkey, I also faced same issue. I resolved this by downloaded openssl and generated hash. Try with following answer https://stackoverflow.com/a/14826036/1258999
Discovered an even easier way to deal with this on Kindle or any other device. If you have the FB app installed (in my case I didn't try other sign in paths but may work too?), and the login you're using is listed as a developer in the FB app at developer.facebook.com for the app in question, the hash will appear in the error message it gives you in the app itself. Says something to the effect of "Hash key xxxxxxxxxxxxxxxxx was not recognized. Manage your hash keys in the developer portal for app id yyyyyyyyyyyy".
Sorry if the text isn't exactly right, i didn't screenshot it prior to fixing the problem myself, but that's the gist of it.

Categories

Resources