samedi 25 juin 2016

Exception while handling OAuth2 callback (null). Spring Social facebook login

I have some problems with facebook login integration. Here is my Social configuration: @Configuration @EnableSocial public class SocialConfig implements SocialConfigurer { private final Logger log = LoggerFactory.getLogger(SocialConfig.class); @Inject Environment environment; @Inject ConnectionRepository customSocialConnectionRepository; @Inject SocialUserConnectionRepository socialUserConnectionRepository; @Bean public ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator) { ConnectController controller = new ConnectController(connectionFactoryLocator, customSocialConnectionRepository); controller.addInterceptor(new FacebookCustomConnectInterceptor()); return controller; } @Override public void addConnectionFactories(ConnectionFactoryConfigurer connectionFactoryConfigurer, Environment environment) { // Facebook configuration String facebookClientId = environment.getProperty("spring.social.facebook.clientId"); String facebookClientSecret = environment.getProperty("spring.social.facebook.clientSecret"); if (facebookClientId != null && facebookClientSecret != null) { log.debug("Configuration FacebookConnectionFactory"); connectionFactoryConfigurer.addConnectionFactory( new FacebookConnectionFactory( facebookClientId, facebookClientSecret ) ); } else { log.error("Cannot configure FacebookConnectionFactory id or secret null"); } } @Override public UserIdSource getUserIdSource() { return new AuthenticationNameUserIdSource(); } @Override public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) { return new CustomSocialUsersConnectionRepository(socialUserConnectionRepository, connectionFactoryLocator); } } I have domain object for store SocialUserConnection. I override ConnectionRepository public class CustomSocialConnectionRepository implements ConnectionRepository { private String userId; private SocialUserConnectionRepository socialUserConnectionRepository; private ConnectionFactoryLocator connectionFactoryLocator; public CustomSocialConnectionRepository(String userId, SocialUserConnectionRepository socialUserConnectionRepository, ConnectionFactoryLocator connectionFactoryLocator) { this.userId = userId; this.socialUserConnectionRepository = socialUserConnectionRepository; this.connectionFactoryLocator = connectionFactoryLocator; } @Override public MultiValueMap<String, Connection<?>> findAllConnections() { List<SocialUserConnection> socialUserConnections = socialUserConnectionRepository.findAllByUserIdOrderByProviderIdAscRankAsc(userId); List<Connection<?>> connections = socialUserConnectionsToConnections(socialUserConnections); MultiValueMap<String, Connection<?>> connectionsByProviderId = new LinkedMultiValueMap<>(); Set<String> registeredProviderIds = connectionFactoryLocator.registeredProviderIds(); for (String registeredProviderId : registeredProviderIds) { connectionsByProviderId.put(registeredProviderId, Collections.emptyList()); } for (Connection<?> connection : connections) { String providerId = connection.getKey().getProviderId(); if (connectionsByProviderId.get(providerId).size() == 0) { connectionsByProviderId.put(providerId, new LinkedList<>()); } connectionsByProviderId.add(providerId, connection); } return connectionsByProviderId; } @Override public List<Connection<?>> findConnections(String providerId) { List<SocialUserConnection> socialUserConnections = socialUserConnectionRepository.findAllByUserIdAndProviderIdOrderByRankAsc(userId, providerId); return socialUserConnectionsToConnections(socialUserConnections); } @Override @SuppressWarnings("unchecked") public <A> List<Connection<A>> findConnections(Class<A> apiType) { List<?> connections = findConnections(getProviderId(apiType)); return (List<Connection<A>>) connections; } @Override public MultiValueMap<String, Connection<?>> findConnectionsToUsers(MultiValueMap<String, String> providerUserIdsByProviderId) { if (providerUserIdsByProviderId == null || providerUserIdsByProviderId.isEmpty()) { throw new IllegalArgumentException("Unable to execute find: no providerUsers provided"); } MultiValueMap<String, Connection<?>> connectionsForUsers = new LinkedMultiValueMap<>(); for (Map.Entry<String, List<String>> entry : providerUserIdsByProviderId.entrySet()) { String providerId = entry.getKey(); List<String> providerUserIds = entry.getValue(); List<Connection<?>> connections = providerUserIdsToConnections(providerId, providerUserIds); connections.forEach(connection -> connectionsForUsers.add(providerId, connection)); } return connectionsForUsers; } @Override public Connection<?> getConnection(ConnectionKey connectionKey) { SocialUserConnection socialUserConnection = socialUserConnectionRepository.findOneByUserIdAndProviderIdAndProviderUserId(userId, connectionKey.getProviderId(), connectionKey.getProviderUserId()); return Optional.ofNullable(socialUserConnection) .map(this::socialUserConnectionToConnection) .orElseThrow(() -> new NoSuchConnectionException(connectionKey)); } @Override @SuppressWarnings("unchecked") public <A> Connection<A> getConnection(Class<A> apiType, String providerUserId) { String providerId = getProviderId(apiType); return (Connection<A>) getConnection(new ConnectionKey(providerId, providerUserId)); } @Override @SuppressWarnings("unchecked") public <A> Connection<A> getPrimaryConnection(Class<A> apiType) { String providerId = getProviderId(apiType); Connection<A> connection = (Connection<A>) findPrimaryConnection(providerId); if (connection == null) { throw new NotConnectedException(providerId); } return connection; } @Override @SuppressWarnings("unchecked") public <A> Connection<A> findPrimaryConnection(Class<A> apiType) { String providerId = getProviderId(apiType); return (Connection<A>) findPrimaryConnection(providerId); } @Override @Transactional public void addConnection(Connection<?> connection) { Long rank = getNewMaxRank(connection.getKey().getProviderId()).longValue(); SocialUserConnection socialUserConnectionToSave = connectionToUserSocialConnection(connection, rank); socialUserConnectionRepository.save(socialUserConnectionToSave); } @Override @Transactional public void updateConnection(Connection<?> connection) { SocialUserConnection socialUserConnection = socialUserConnectionRepository.findOneByUserIdAndProviderIdAndProviderUserId(userId, connection.getKey().getProviderId(), connection.getKey().getProviderUserId()); if (socialUserConnection != null) { SocialUserConnection socialUserConnectionToUdpate = connectionToUserSocialConnection(connection, socialUserConnection.getRank()); socialUserConnectionToUdpate.setId(socialUserConnection.getId()); socialUserConnectionRepository.save(socialUserConnectionToUdpate); } } @Override @Transactional public void removeConnections(String providerId) { socialUserConnectionRepository.deleteByUserIdAndProviderId(userId, providerId); } @Override @Transactional public void removeConnection(ConnectionKey connectionKey) { socialUserConnectionRepository.deleteByUserIdAndProviderIdAndProviderUserId(userId, connectionKey.getProviderId(), connectionKey.getProviderUserId()); } private Double getNewMaxRank(String providerId) { List<SocialUserConnection> socialUserConnections = socialUserConnectionRepository.findAllByUserIdAndProviderIdOrderByRankAsc(userId, providerId); return socialUserConnections.stream() .mapToDouble(SocialUserConnection::getRank) .max() .orElse(0D) + 1D; } private Connection<?> findPrimaryConnection(String providerId) { List<SocialUserConnection> socialUserConnections = socialUserConnectionRepository.findAllByUserIdAndProviderIdOrderByRankAsc(userId, providerId); if (socialUserConnections.size() > 0) { return socialUserConnectionToConnection(socialUserConnections.get(0)); } else { return null; } } private SocialUserConnection connectionToUserSocialConnection(Connection<?> connection, Long rank) { ConnectionData connectionData = connection.createData(); return new SocialUserConnection( userId, connection.fetchUserProfile().getEmail(), connection.getKey().getProviderId(), connection.getKey().getProviderUserId(), rank, connection.getDisplayName(), connection.getProfileUrl(), connection.getImageUrl(), connectionData.getAccessToken(), connectionData.getSecret(), connectionData.getRefreshToken(), connectionData.getExpireTime() ); } private List<Connection<?>> providerUserIdsToConnections(String providerId, List<String> providerUserIds) { List<SocialUserConnection> socialUserConnections = socialUserConnectionRepository.findAllByUserIdAndProviderIdAndProviderUserIdIn(userId, providerId, providerUserIds); return socialUserConnectionsToConnections(socialUserConnections); } private List<Connection<?>> socialUserConnectionsToConnections(List<SocialUserConnection> socialUserConnections) { return socialUserConnections.stream() .map(this::socialUserConnectionToConnection) .collect(Collectors.toList()); } private Connection<?> socialUserConnectionToConnection(SocialUserConnection socialUserConnection) { ConnectionData connectionData = new ConnectionData(socialUserConnection.getProviderId(), socialUserConnection.getProviderUserId(), socialUserConnection.getDisplayName(), socialUserConnection.getProfileURL(), socialUserConnection.getImageURL(), socialUserConnection.getAccessToken(), socialUserConnection.getSecret(), socialUserConnection.getRefreshToken(), socialUserConnection.getExpireTime()); ConnectionFactory<?> connectionFactory = connectionFactoryLocator.getConnectionFactory(connectionData.getProviderId()); return connectionFactory.createConnection(connectionData); } private <A> String getProviderId(Class<A> apiType) { return connectionFactoryLocator.getConnectionFactory(apiType).getProviderId(); } } and UsersConnectionRepository (http://pastebin.com/7UzsndJq) I use ConnectController to handle facebook connection, register and login user into application. public class FacebookCustomConnectInterceptor implements ConnectInterceptor<Facebook> { private final Logger log = LoggerFactory.getLogger(FacebookCustomConnectInterceptor.class); @Inject SocialService socialService; @Inject CustomSocialUsersConnectionRepository customSocialUsersConnectionRepository; @Inject SocialUserConnectionRepository socialUserConnectionRepository; @Override public void preConnect(ConnectionFactory<Facebook> connectionFactory, MultiValueMap<String, String> valueMap, WebRequest request) { // events before connection } @Override public void postConnect(Connection<Facebook> connection, WebRequest request) { UserProfile userProfile = connection.fetchUserProfile(); socialService.loginOrCreateFacebookUser(userProfile); } } public void loginOrCreateFacebookUser(UserProfile userProfile) { SocialUserConnection socialUserConnection = socialUserConnectionRepository.findOneByEmailAndProviderId(userProfile.getEmail(), "facebook"); Optional<User> foundUser = userRepository.findByUsername(socialUserConnection.getEmail()); User user = new User(); if(!foundUser.isPresent()) { user.setUsername(socialUserConnection.getEmail()); user.setEmail(socialUserConnection.getEmail()); user.setPassword(RandomUtil.generatePassword()); user.setActivated(true); Authority authority = authorityRepository.findOne("ROLE_USER"); Set<Authority> authorities = new HashSet<>(); authorities.add(authority); user.setAuthorities(authorities); user = userRepository.save(user); } else { user = foundUser.get(); } String lowercaseLogin = user.getUsername().toLowerCase(); List<GrantedAuthority> grantedAuthorities = user.getAuthorities().stream() .map(authority -> new SimpleGrantedAuthority(authority.getName())) .collect(Collectors.toList()); UserDetails userDetails = new org.springframework.security.core.userdetails.User(lowercaseLogin, user.getPassword(), grantedAuthorities); Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); //SecurityContextHolder.clearContext(); SecurityContextHolder.getContext().setAuthentication(authentication); } The problem is when i try to run some functions in postConnect. When i try to do this i got error: WARN 3232 --- [nio-8080-exec-3] o.s.s.connect.web.ConnectController : Exception while handling OAuth2 callback (null). Redirecting to facebook connection status page. Full stack: http://pastebin.com/QXGtv3xe I can't post more than 2 links :) I use Spring Boot 1.3.5

Aucun commentaire:

Enregistrer un commentaire