package qa.qcri.aidr.manager.social.security; import java.io.IOException; import java.util.List; import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.collections.CollectionUtils; import org.socialsignin.springsocial.security.signin.AuthenticatedUserIdHolder; import org.socialsignin.springsocial.security.signin.SpringSocialSecurityAuthenticationFactory; import org.socialsignin.springsocial.security.signin.SpringSocialSecuritySignInDetails; import org.socialsignin.springsocial.security.signin.SpringSocialSecuritySignInService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; 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.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.authentication.RememberMeServices; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.social.connect.ConnectionData; import org.springframework.stereotype.Component; import qa.qcri.aidr.manager.persistence.entities.UserConnection; import qa.qcri.aidr.manager.service.UserConnectionService; import qa.qcri.aidr.manager.util.Constants; @Component @Qualifier("springSocialAuthenticationFilter") public class SpringSocialAuthenticationFilter extends AbstractAuthenticationProcessingFilter { @Value("${socialsignin.defaultAuthenticationSuccessUrl:}") private String defaultAuthenticationSuccessUrl; public final static String DEFAULT_AUTHENTICATION_URL = "/authenticate"; private boolean removeSignInDetailsFromSessionOnSuccessfulAuthentication = true; private boolean allowRepeatedAuthenticationAttempts = false; public void setAllowRepeatedAuthenticationAttempts( boolean allowRepeatedAuthenticationAttempts) { this.allowRepeatedAuthenticationAttempts = allowRepeatedAuthenticationAttempts; } @Override @Autowired(required = false) public void setRememberMeServices(RememberMeServices rememberMeServices) { super.setRememberMeServices(rememberMeServices); } @Autowired @Qualifier("springSocialUserDetailsService") private UserDetailsService userDetailsService; @Inject private UserConnectionService userConnectionService; @Autowired private SpringSocialSecurityAuthenticationFactory authenticationFactory; public void setRemoveSignInDetailsFromSessionOnSuccessfulAuthentication( boolean removeSignInDetailsFromSessionOnSuccessfulAuthentication) { this.removeSignInDetailsFromSessionOnSuccessfulAuthentication = removeSignInDetailsFromSessionOnSuccessfulAuthentication; } @Autowired public void setAuthenticationManager(AuthenticationManager authenticationManager) { super.setAuthenticationManager(authenticationManager); } public SpringSocialAuthenticationFilter() { super(DEFAULT_AUTHENTICATION_URL); } @PostConstruct public void init(){ if (defaultAuthenticationSuccessUrl != null && !defaultAuthenticationSuccessUrl.isEmpty()){ SavedRequestAwareAuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler = new SavedRequestAwareAuthenticationSuccessHandler(); savedRequestAwareAuthenticationSuccessHandler.setDefaultTargetUrl(defaultAuthenticationSuccessUrl); setAuthenticationSuccessHandler(savedRequestAwareAuthenticationSuccessHandler); } } protected SpringSocialAuthenticationFilter(String authenticationUrl) { super(authenticationUrl); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { SpringSocialSecuritySignInDetails signInDetails = (SpringSocialSecuritySignInDetails) request.getSession().getAttribute( SpringSocialSecuritySignInService.SIGN_IN_DETAILS_SESSION_ATTRIBUTE_NAME); String alreadyAuthenticatedUserId = AuthenticatedUserIdHolder.getAuthenticatedUserId(); if (signInDetails != null) { UserDetails user = userDetailsService.loadUserByUsername(signInDetails.getConnectionData().getProviderId() + Constants.USER_NAME_SPLITTER + signInDetails.getUserId()); if (removeSignInDetailsFromSessionOnSuccessfulAuthentication) { request.getSession().removeAttribute(SpringSocialSecuritySignInService.SIGN_IN_DETAILS_SESSION_ATTRIBUTE_NAME); } updateUserKeys(signInDetails.getConnectionData(), signInDetails.getUserId()); //Setting social login provider for current session //request.getSession().setAttribute("provider", signInDetails.getConnectionData().getProviderId()); return authenticationFactory.createAuthenticationFromUserDetails(user); } else if (allowRepeatedAuthenticationAttempts && alreadyAuthenticatedUserId != null) { return SecurityContextHolder.getContext().getAuthentication(); } else { logger.info("SpringSocialSecurity sign in details not found in session"); throw new InsufficientAuthenticationException( "SpringSocialSecurity sign in details not found in session"); } } private void updateUserKeys(ConnectionData connectionData, String userId){ List<UserConnection> userConnections = userConnectionService.getByUserIdAndProviderUserId(userId, connectionData.getProviderUserId()); if(!CollectionUtils.isFull(userConnections)){ for(UserConnection uc : userConnections){ uc.setAccessToken(connectionData.getAccessToken()); uc.setSecret(connectionData.getSecret()); userConnectionService.update(uc); } } } }