16

In my app, I'm trying to authenticate (login) by passing Facebook session information (token and expiration date) to my server.

My login sequence to the app server is as follows:

  1. Get active facebook session.
  2. If the session is valid, get token and send it on to the server.

And in code:

Session session = Session.getActiveSession();
if(session != null && session.isOpened() && !didLogin) {
    didLogin = true;
    String token = session.getAccessToken();
    Date expires = session.getExpirationDate();
    loginWithFacebookSession(token, expires);
}

I have noticed that suddenly, after a few months of this working just fine, the information being sent to the server is occasionally not valid, specifically the token is an empty string and the expires is an invalid date.

After going a bit through the Facebook SDK (version 3.0.1), I spotted what is probably the basis of my error:

private static final Date MIN_DATE = new Date(Long.MIN_VALUE);
private static final Date ALREADY_EXPIRED_EXPIRATION_TIME = MIN_DATE;
private static final Date DEFAULT_LAST_REFRESH_TIME = new Date();

static AccessToken createEmptyToken(List<String> permissions) {
    return new AccessToken("", ALREADY_EXPIRED_EXPIRATION_TIME, permissions, AccessTokenSource.NONE,
            DEFAULT_LAST_REFRESH_TIME);
}

This means that somewhere along the way, the Facebook SDK is creating an empty token and returning it with a SessionState.Category.OPENED_CATEGORY.

Why is session.isOpened() returning true when in fact there is no accessToken information? Should I be checking a different property? Is this a bug in Facebook's SDK?

EDIT:
Reported this to Facebook at: https://developers.facebook.com/bugs/121924628017965

thepoosh
  • 12,193
  • 14
  • 68
  • 129
  • How are you opening the sessions/setting the active session? – Ming Li Jun 17 '13 at 21:09
  • I'm using the `UiLifecycleHelper` class as documented [in the Facebook developers website](https://developers.facebook.com/docs/tutorials/androidsdk/3.0/scrumptious/authenticate/) – thepoosh Jun 18 '13 at 05:07
  • Maybe you have to check if the session is in the OPENED_TOKEN_UPDATED state, that is the token has changed, but the session is still in an opened state. – 5agado Jun 19 '13 at 12:10
  • 5
    welcome to the FacebookSDK... – Ovidiu Latcu Jun 21 '13 at 09:41
  • I am getting session as null, while running native fb app in background. What will be the issue? – Manesh Appukuttan Apr 09 '14 at 05:15
  • How did you solved this ? – Renetik Jun 24 '14 at 06:17
  • @ReneDohan - we noticed that this happens only on specific versions of facebook – thepoosh Jun 24 '14 at 07:54
  • You mean facebook sdk of facebook app ? I have problems reproducing this issue and I am looking to workaround as it seems that UiLifecycleHelper is not enough to have updated token in active session... Maybe Session.openActiveSessionFromCache(context()) could help ? I have to reproduce it somehow , both testers have this issue but not me... – Renetik Jun 24 '14 at 09:00
  • it was an issue with clients that have an outdated Facebook application installed. – thepoosh Jun 24 '14 at 11:02

3 Answers3

2

Use this method and check if your hash is correct

public void getHashKeyForFacebook(Activity activity, String packageName){
    try{
        PackageInfo info = activity.getPackageManager().getPackageInfo(packageName,  PackageManager.GET_SIGNATURES);

        for (Signature signature : info.signatures){
                MessageDigest md = MessageDigest.getInstance("SHA");
                md.update(signature.toByteArray());
                Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
        }
    } catch (Exception ex){

    }
}
1

Apart from the Facebook SDK being like voodoo magic, there are some thing you are doing that I do not do in my auth flow. I'm assuming here that your code snippet is not in the Session.StatusCallback call function. No matter what, I always open the session for read before accessing the token from the callback. This request just inconveniences the user for a few milliseconds with a loading spinner before it returns. It also helps in case when the user has deleted the permissions from their Facebook settings page.

My auth flow is something like this:

private void startFbAuth() {
    Session session = Session.getActiveSession();
    if (session == null) {
        session = new Session(getApplicationContext());
        Session.setActiveSession(session);

        Session.OpenRequest openReadRequest = new Session.OpenRequest(this);
        openReadRequest.setPermissions(Arrays.asList({ "email" }));
        openReadRequest.setCallback(statusCallback);

        Session.NewPermissionsRequest permissionReadRequest = new Session.NewPermissionsRequest(this, Arrays.asList(EMAIL_PERMISSIONS));
        permissionReadRequest.setCallback(statusCallback);

        if (!session.isOpened() && !session.isClosed()) {
            session.openForRead(openReadRequest);
        } else {
            session.requestNewReadPermissions(permissionReadRequest);
        }
    }

    private Session.StatusCallback statusCallback = new SessionStatusCallback();

    private class SessionStatusCallback implements Session.StatusCallback {
        @Override
        public void call(Session session, SessionState state, Exception exception) {
            if (session.isClosed()) {
                session.closeAndClearTokenInformation();
                Session.setActiveSession(null);
                SessionStore.clearFacebookInformation(Activity.this);
                // Either throw an error or try reconnecting by calling startFbAuth
            }
            if (exception != null) {
                session.closeAndClearTokenInformation();
                Session.setActiveSession(session);
                // Either throw an error or try reconnecting by calling startFbAuth
            } else {
                if (session.isOpened()) {
                    String token = session.getAccessToken();
                    // It shouldn't be null or empty here
                }
            }
        }
    }
rarp
  • 1,122
  • 10
  • 20
0

I Solved the problem. The problem was in key Hash.

Follow this tutorial

go to step no. 4 Run the Samples.

at last you will found Troubleshooting section and that is the solution.

Thanks! https://developers.facebook.com/docs/getting-started/facebook-sdk-for-android/3.0/