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:
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
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){
}
}
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
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With