package com.mothsoft.alexis.web.security;
import java.util.ArrayList;
import java.util.List;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.transaction.annotation.Transactional;
import com.mothsoft.alexis.domain.SocialConnection;
import com.mothsoft.alexis.domain.SocialNetworkType;
import com.mothsoft.alexis.domain.User;
import com.mothsoft.alexis.domain.UserAuthenticationDetails;
import com.mothsoft.alexis.service.UserService;
import com.mothsoft.alexis.web.security.GoogleOauthAuthenticationFilter.OauthAuthenticationToken;
public class GoogleOauthAuthenticationProvider implements AuthenticationProvider {
private UserService userService;
private UserDetailsService userDetailsService;
public GoogleOauthAuthenticationProvider(final UserService userService, final UserDetailsService userDetailsService) {
this.userService = userService;
this.userDetailsService = userDetailsService;
}
@Override
public boolean supports(final Class<? extends Object> authenticationType) {
return OauthAuthenticationToken.class.isAssignableFrom(authenticationType);
}
@Transactional
@Override
public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
final String username = authentication.getName();
SocialConnection socialConnection = userService.findSocialConnectionByRemoteUsername(username,
SocialNetworkType.G);
final OauthAuthenticationToken oauthToken = (OauthAuthenticationToken) authentication;
final String email = oauthToken.getEmail();
final User user;
if (socialConnection == null) {
// create user
user = new User();
user.setAdmin(false);
user.setHashedPassword(oauthToken.getAccessToken());
user.setPasswordSalt(null);
user.setUsername(email);
socialConnection = new SocialConnection(user, username, oauthToken.getAccessToken(),
oauthToken.getRefreshToken(), SocialNetworkType.G);
user.getSocialConnections().add(socialConnection);
userService.addUser(user);
} else {
if (!socialConnection.getUser().getUsername().equals(email)) {
throw new BadCredentialsException("Identity mismatch");
}
socialConnection.setOauthToken(oauthToken.getAccessToken());
socialConnection.setOauthTokenSecret(oauthToken.getRefreshToken());
user = socialConnection.getUser();
}
this.userService.createApiToken(user);
this.userService.update(user);
final List<GrantedAuthority> userAuthorities = new ArrayList<GrantedAuthority>();
userAuthorities.add(new GrantedAuthorityImpl("ROLE_USER"));
if (user.isAdmin()) {
userAuthorities.add(new GrantedAuthorityImpl("ROLE_ADMIN"));
}
if (user.isAnalysisRole() || user.isAdmin()) {
userAuthorities.add(new GrantedAuthorityImpl("ROLE_ANALYSIS"));
}
final UserAuthenticationDetails details = (UserAuthenticationDetails) this.userDetailsService
.loadUserByUsername(email);
final UsernamePasswordAuthenticationToken newAuthentication = new UsernamePasswordAuthenticationToken(details,
oauthToken.getAccessToken(), userAuthorities);
return newAuthentication;
}
}