Announcement Announcement Module
Collapse
No announcement yet.
Handling when user removes app from FB account - signs in normally, etc? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Handling when user removes app from FB account - signs in normally, etc?

    I'm digging into best approaches to handle when a User removes your application from their facebook account within facebook.

    For example, note how in the Spring Social Application:
    1) user connects Facebook to Spring Social App
    2) In another tab user removes Spring Social App as an application in their account preferences
    3) Back within the Spring Social App user tries to make a post to their facebook account, they'll receive an ugly org.springframework.social.RevokedAuthorizationExc eption. Or they could even signout of Spring Social Showcase and then sign back in using the username/password they signed up with and Spring Social Showcase still thinks they are connected to Facebook (when they really aren't.)

    Handling a scenario where a Facebook operation tries to take place that is invalid seems pretty straightforward: You could have a servlet/bean defined for that Exception and catch it, clean up any user connection info in the db, and redirect to them to the signin page. (Possibly Spring Social Showcase should even implement this)

    However what's the best approach for determining if you still have permissions to their facebook account in general - for use "upon Signin" ? The issue is if the user has previously connected to Facebook, then they remove the app from within facebook, and then they try to use their standard username/password to sign in to the application the app thinks they are still a valid facebook connection, since their previous facebook information still remains in the UsersConnection table (and since I also initially prompted them for 'offline access' earlier, it also assumes I could post status updates.)

    I'm thinking maybe the best way to handle this is on a standard signin I make "some kind of check to facebook to be SURE they are still valid." If that returns false then I go and clean out the UserConnections table of that user (plus some of my own internal tables related to storage of facebook data.) If this approach is taken "What is the best way to make this check? Just make a call to connection.getApi() getUserProfile() and catch any Exception?

  • #2
    Ok, cool Connection has a test() method which works great.

    So here is what I implemented in my controller that gets hit when a user does a signin. I thought about doing this just on a manual signin but now that I think about it I should do it on even a social signin so that it cleans up connections from other providers (other than the one they signed up with.) [wondering if maybe this should maybe should even be done somewhere in the social samples?] For example, user first connects with Facebook and Twitter. Later on within their Facebook account they remove access to my app. User logs into the app with their twitter account. App then tries to make a post to facebook and twitter. The app will think the facebook account is still valid when it isn't so exception will be thrown. Although you can handle this exception, it's also not nice for the app in general since you won't show a "connect with twitter" button since it'll think it's connected (and you might even be showing an incorrect "disconnect from facebook" button.)

    Not sure if the below is the best way to handle this. Since JdbConnectionRespository is a bit difficult to extend due to some access issues with things private in it, I'll probably just make my own Request scoped proxy bean like JdbcConnectionRepository that returns what the first line does in MultiValueMap<String, Connection<?>> findAllConnections() of the JdbcConnectionRepository (or submit a patch that exposes the following as a public method):

    Code:
    List<Connection<?>> resultList = jdbcTemplate.query(selectFromUserConnection() + " where userId = ? order by providerId, rank", connectionMapper, userId);

    For now I'm doing it an ugly way using the MultiValueMap that is exposed through the ConnectionRepository:

    Code:
    public void validateConnectionsAreValidForUser(int memberId) {
        MultiValueMap<String, Connection<?>> map = connectionRepository.findAllConnections();
        Collection<List<Connection<?>>> listOfListsOfConnections = map.values();
        for(List<Connection<?>> connections: listOfListsOfConnections) {
            for(Connection<?> connection: connections) {
                if (!connection.test()) {
                    connectionRepository.removeConnection(connection.getKey());
    
                    //our cleanup stuff we need to do for facebook related stuff that we store
                    if (connection.getKey().getProviderId().equals(SocialConstants.PROVIDER_FACEBOOK)) {
                        deleteProfilesAndRules(memberId, SocialConstants.PROVIDER_FACEBOOK);
                    }
                }
            }
        }
    }
    One other thing that would also be nice in an updated version of spring-social-core (and when I get time I'll try and submit a patch for review) is if ConnectionData just added the userId property that is already being returned in the ResultSet. The ConnectionData mapConnectionData(ResultSet rs) doesn't map this property when it could. So in my code above, had I had access to userId from the Connection.getConnectionData, I wouldn't need to be passing userId to my method.

    Comment

    Working...
    X