Facebook Login with Spring Social using Existing U

2019-03-09 12:08发布

问题:

Here's what I currently have:

  • Spring REST service where many of the APIs require the user to be authenticated
  • A 'registration' API (/api/v1/register)
  • A 'login' API that takes username/password (/api/v1/login)
  • 'Facebook Login' API that relies on Spring Social and Spring Security to create a User Connection and log my user in (/auth/facebook)

My problem is that I want these APIs to be used by multiple clients, but the way Facebook Login is right now, it doesn't work well on mobile (works great on a website).

Here's the mobile scenario:

  • I use Facebook's iOS SDK to request permission from the user
  • Facebook returns a user access token
  • I want to send my backend service this token and have Spring Social accept it, create the User Connection, etc.

Can this be done? Or am I going to have to write my own API to persist the User Connection?

Appreciate any help!

回答1:

I had the exact same issue and here's how I made it work. You probably have a SocialConfigurer somewhere with the following:

@Configuration
@EnableSocial
public class SocialConfig implements SocialConfigurer {

    @Autowired
    private DataSource dataSource;

    @Bean
    public FacebookConnectionFactory facebookConnectionFactory() {
        FacebookConnectionFactory facebookConnectionFactory = new FacebookConnectionFactory("AppID", "AppSecret");
        facebookConnectionFactory.setScope("email");
        return facebookConnectionFactory;
    }

    @Override
    public void addConnectionFactories(ConnectionFactoryConfigurer cfConfig, Environment env) {
        cfConfig.addConnectionFactory(facebookConnectionFactory());
    }

    @Override
    public UserIdSource getUserIdSource() {
        return new AuthenticationNameUserIdSource();
    }

    @Override
    public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
        return new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator, Encryptors.noOpText());
    }

    // Other @Bean maybe ...
}

From here, what you can do is, in a Controller/RestController, add a mapping with a RequestParam for your token that you will send to your server:

@Autowired
private FacebookConnectionFactory facebookConnectionFactory;

@Autowired
private UsersConnectionRepository usersConnectionRepository;

@RequestMapping(value = "/my-facebook-url", method = RequestMethod.POST)
public String fb(@RequestParam String token) {
    AccessGrant accessGrant = new AccessGrant(token);
    Connection<Facebook> connection = facebookConnectionFactory.createConnection(accessGrant);

    UserProfile userProfile = connection.fetchUserProfile();
    usersConnectionRepository.createConnectionRepository(userProfile.getEmail()).addConnection(connection);

    // ...

    return "Done";
}

Useful references

  • UsersConnectionRepository
  • ConnectionRepository