Skip to content

Instantly share code, notes, and snippets.

@ruddell
Created January 13, 2018 23:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ruddell/380f5c4de45a0069e746b1e22f2a963d to your computer and use it in GitHub Desktop.
Save ruddell/380f5c4de45a0069e746b1e22f2a963d to your computer and use it in GitHub Desktop.
JWT SocialService.java for Ignite JHipster Social Login
package com.mycompany.myapp.service;
import com.mycompany.myapp.domain.Authority;
import com.mycompany.myapp.domain.User;
import com.mycompany.myapp.repository.AuthorityRepository;
import com.mycompany.myapp.repository.UserRepository;
import com.mycompany.myapp.security.AuthoritiesConstants;
import com.mycompany.myapp.security.jwt.TokenProvider;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.social.connect.*;
import org.springframework.social.facebook.connect.FacebookConnectionFactory;
import org.springframework.social.google.connect.GoogleConnectionFactory;
import org.springframework.social.oauth1.OAuthToken;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.social.twitter.connect.TwitterConnectionFactory;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
public class SocialService {
private final Logger log = LoggerFactory.getLogger(SocialService.class);
private final UsersConnectionRepository usersConnectionRepository;
private final AuthorityRepository authorityRepository;
private final PasswordEncoder passwordEncoder;
private final UserRepository userRepository;
private final UserDetailsService userDetailsService;
private final TokenProvider tokenProvider;
private final ConnectionFactoryLocator connectionFactoryLocator;
private final MailService mailService;
public SocialService(UsersConnectionRepository usersConnectionRepository, AuthorityRepository authorityRepository,
PasswordEncoder passwordEncoder, UserRepository userRepository,
UserDetailsService userDetailsService, TokenProvider tokenProvider, ConnectionFactoryLocator connectionFactoryLocator, MailService mailService) {
this.usersConnectionRepository = usersConnectionRepository;
this.authorityRepository = authorityRepository;
this.passwordEncoder = passwordEncoder;
this.userRepository = userRepository;
this.userDetailsService = userDetailsService;
this.tokenProvider = tokenProvider;
this.connectionFactoryLocator = connectionFactoryLocator;
this.mailService = mailService;
}
public void deleteUserSocialConnection(String login) {
ConnectionRepository connectionRepository = usersConnectionRepository.createConnectionRepository(login);
connectionRepository.findAllConnections().keySet().stream()
.forEach(providerId -> {
connectionRepository.removeConnections(providerId);
log.debug("Delete user social connection providerId: {}", providerId);
});
}
public User createSocialUser(Connection<?> connection, String langKey) {
if (connection == null) {
log.error("Cannot create social user because connection is null");
throw new IllegalArgumentException("Connection cannot be null");
}
UserProfile userProfile = connection.fetchUserProfile();
String providerId = connection.getKey().getProviderId();
String imageUrl = connection.getImageUrl();
User user = createUserIfNotExist(userProfile, langKey, providerId, imageUrl);
createSocialConnection(user.getLogin(), connection);
mailService.sendSocialRegistrationValidationEmail(user, providerId);
return user;
}
private User createUserIfNotExist(UserProfile userProfile, String langKey, String providerId, String imageUrl) {
String email = userProfile.getEmail();
String userName = userProfile.getUsername();
if (!StringUtils.isBlank(userName)) {
userName = userName.toLowerCase(Locale.ENGLISH);
}
if (StringUtils.isBlank(email) && StringUtils.isBlank(userName)) {
log.error("Cannot create social user because email and login are null");
throw new IllegalArgumentException("Email and login cannot be null");
}
if (StringUtils.isBlank(email) && userRepository.findOneByLogin(userName).isPresent()) {
log.error("Cannot create social user because email is null and login already exist, login -> {}", userName);
throw new IllegalArgumentException("Email cannot be null with an existing login");
}
if (!StringUtils.isBlank(email)) {
Optional<User> user = userRepository.findOneByEmailIgnoreCase(email);
if (user.isPresent()) {
log.info("User already exist associate the connection to this account");
return user.get();
}
}
String login = getLoginDependingOnProviderId(userProfile, providerId);
String encryptedPassword = passwordEncoder.encode(RandomStringUtils.random(10));
Set<Authority> authorities = new HashSet<>(1);
authorities.add(authorityRepository.findOne(AuthoritiesConstants.USER));
User newUser = new User();
newUser.setLogin(login);
newUser.setPassword(encryptedPassword);
newUser.setFirstName(userProfile.getFirstName());
newUser.setLastName(userProfile.getLastName());
newUser.setEmail(email);
newUser.setActivated(true);
newUser.setAuthorities(authorities);
newUser.setLangKey(langKey);
newUser.setImageUrl(imageUrl);
return userRepository.save(newUser);
}
/**
* @return login if provider manage a login like Twitter or GitHub otherwise email address.
* Because provider like Google or Facebook didn't provide login or login like "12099388847393"
*/
public String getLoginDependingOnProviderId(UserProfile userProfile, String providerId) {
switch (providerId) {
case "twitter":
return userProfile.getUsername().toLowerCase();
default:
return userProfile.getFirstName().toLowerCase() + "_" + userProfile.getLastName().toLowerCase();
}
}
private void createSocialConnection(String login, Connection<?> connection) {
ConnectionRepository connectionRepository = usersConnectionRepository.createConnectionRepository(login);
connectionRepository.addConnection(connection);
}
public String loadConnectionFromToken(String token, String secret, String provider) {
Connection connection = null;
UserProfile userProfile = null;
if ("facebook".equals(provider)) {
AccessGrant accessGrant = new AccessGrant(token);
connection = ((FacebookConnectionFactory)connectionFactoryLocator.getConnectionFactory(provider)).createConnection(accessGrant);
userProfile = connection.fetchUserProfile();
} else if ("twitter".equals(provider)) {
OAuthToken oAuthToken = new OAuthToken(token, secret);
connection = ((TwitterConnectionFactory)connectionFactoryLocator.getConnectionFactory("twitter")).createConnection(oAuthToken);
userProfile = connection.fetchUserProfile();
} else if ("google".equals(provider)) {
AccessGrant accessGrant = new AccessGrant(token);
connection = ((GoogleConnectionFactory)connectionFactoryLocator.getConnectionFactory(provider)).createConnection(accessGrant);
userProfile = connection.fetchUserProfile();
}
// check if the user exists
List<String> userIds = usersConnectionRepository.findUserIdsWithConnection(connection);
String userLogin;
if (userIds.size() == 0) {
log.debug("User needs to be created");
userLogin = createSocialUser(connection, "en").getLogin();
} else {
log.debug("User already exists, logging in");
userLogin = getLoginDependingOnProviderId(userProfile, provider);
}
UserDetails user = userDetailsService.loadUserByUsername(userLogin);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user,null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
return tokenProvider.createToken(authenticationToken, false);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment