User is asked for login credentials during reauthorization

1.1k Views Asked by At

I am trying to implement the new Facebook SDK 3.0 into my Android app and I have run into a problem. The problem I am having is that the user is asked to log in again to give publish ("post_to_wall") permissions, even though the user is already logged in, with read permissions. This only happens if the user doesn't have the FB application installed. If he has the FB application installed, then he is only asked to grant the permissions.

This is how I implemented the login:

public void login(Activity activity) {
    Session session = Session.getActiveSession();

    if (session == null || !session.isOpened()) {
        openActiveSession(activity, true, sessionStatusCallback);
    }
}

private Session openActiveSession(final Activity activity, final boolean allowLoginUI, final StatusCallback callback) {
    return openActiveSession(activity, allowLoginUI, new OpenRequest(activity).setCallback(callback));
}

private Session openActiveSession(final Context context, final boolean allowLoginUI, final OpenRequest openRequest) {
    Session session = new Builder(context).setApplicationId(FACEBOOK_APPLICATION_ID).build();
    if (SessionState.CREATED_TOKEN_LOADED.equals(session.getState()) || allowLoginUI) {
        Session.setActiveSession(session);
        session.openForRead(openRequest);
        return session;
    }
    return null;
}

This is the callback's call method:

public void call(final Session session, final SessionState state, final Exception exception) {
    if (session.isOpened()) {
        if (state.equals(SessionState.OPENED_TOKEN_UPDATED)) {
            // code if new permissions have been granted
        } else {
            // code for login
        }
    } else if (session.isClosed()) {
            // code for user canceled login
        } else if (exception != null) {
            // code if there were errors during login 
        }
    }
}

This is the code I added to onActivityResult method of the activity that calls the login:

Session.getActiveSession().onActivityResult(activity, requestCode, resultCode, data);

And this is how I ask for new permissions:

Session session = Session.getActiveSession();
if (session != null && session.isOpened()) {    
    if (DONT_HAVE_PERMISSIONS) {
        Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest(activity,
                            FACEBOOK_PERMISSIONS).setRequestCode(FACEBOOK_AUTHORIZE_ACTIVITY_CODE);
        session.requestNewPublishPermissions(newPermissionsRequest);
    }
}

I've tried to find out more about this problem, and I only found out some hints that this is intended, but I haven't found anything concrete.

Is this the default behavior? If so, is there a way around it? Or, perhaps I did something wrong?

Thanks for the help.

2

There are 2 best solutions below

0
On

Update your SDK version; this issue is resolved in Facebook Android SDK v3.0.1.

0
On

Looking at facebooks source code I think it should be possible to start trying to get the permissions directly as both login, and permissions classes derive from the same AuthorizationRequest class, and the AuthorizationRequest class does all the work, like really all the work. The Session.NewPermissionsRequest class just makes some private methods, public in the AuthorizationRequest class and that's it! They might as well give us access to AuthorizationRequest directly. The new facebook API doesn't seem to have any form of "OnFailed/OnSuccess" callbacks, so I end up having a state machine to remember the goal of firing up facebook (login, permissions, get friends list ...), and which step I'm on. If they have done some form of onFailed/onSuccess callbacks it would be simple to make a chain rather than keeping track of a state machine.

I haven't tried what I said. If I do, I'll update the answer. If you try and it works to just fire up Session.NewPermissionsRequest directly without logging in let me know!

Update

I got it working with only asking for credentials once as I explained above.

  1. goto src/com/facebook/Sessions.java
  2. On line 862 you will find

    private static Session openActiveSession(Context context, boolean allowLoginUI, OpenRequest openRequest)
    
  3. make it be a public function and save.

Now instead of creating the Session.NewPermissionsRequest object. Make Session.OpenRequest

        permisions = new ArrayList<String>();
        permisions.add("user_photos");
        permisions.add("friends_photos");
        Session.NewPermissionsRequest request = new Session.NewPermissionsRequest(
                activity, permisions);
        request.setCallback(helper);

        if (Session.getActiveSession() != null)
            Session.getActiveSession().requestNewReadPermissions(request);
        else {
            Session.OpenRequest orequest = new Session.OpenRequest(activity);
            orequest.setPermissions(permisions);
            orequest.setCallback(helper);
                            // its now public so you can call it
            Session.openActiveSession(act, true, request);
        }

Now make sure you do set a callback, for one important reason

@Override
public void call(Session session, SessionState state, Exception exception) {
    if (state.isClosed()) {
                    // we are doing unofficial stuff so we loose guarantees.
                    // Set the active session to null if we logout or user cancels
                    // logging in. If you don't do this, the second time it will result
                    // in a crash.
        Session.setActiveSession(null);
    }
}

Now it will ask for all permissions directly and login in one go.