package fr.openwide.maven.artifact.notifier.web.application.auth.pac4j.service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.pac4j.core.credentials.Credentials;
import org.pac4j.springframework.security.authentication.ClientAuthenticationToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AccountStatusUserDetailsChecker;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsChecker;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import fr.openwide.maven.artifact.notifier.web.application.auth.pac4j.util.Pac4jAuthenticationUtils;
public class Pac4jAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
@Autowired
private Pac4jUserDetailsService pac4jUserDetailsService;
private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
public Pac4jAuthenticationSuccessHandler() {
super();
setDefaultTargetUrl(Pac4jAuthenticationUtils.LOGIN_SUCCESS_URL);
setAlwaysUseDefaultTargetUrl(true);
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
String targetUrl;
try {
ClientAuthenticationToken tokenWithUserDetails = getAuthenticationTokenWithUserDetails(authentication);
SecurityContextHolder.getContext().setAuthentication(tokenWithUserDetails);
super.onAuthenticationSuccess(request, response, authentication);
return;
} catch (UsernameNotFoundException e) {
saveAuthentication(request, getAuthenticationToken(authentication));
targetUrl = Pac4jAuthenticationUtils.REGISTER_URL;
} catch (AuthenticationException e) {
saveException(request, e);
targetUrl = Pac4jAuthenticationUtils.LOGIN_FAILURE_URL;
}
// Failed to retrieve user details
SecurityContextHolder.clearContext();
getRedirectStrategy().sendRedirect(request, response, targetUrl);
}
private final void saveAuthentication(HttpServletRequest request, ClientAuthenticationToken token) {
request.getSession().setAttribute(Pac4jAuthenticationUtils.AUTH_TOKEN_ATTRIBUTE, token);
}
private final void saveException(HttpServletRequest request, AuthenticationException exception) {
request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
}
private ClientAuthenticationToken getAuthenticationTokenWithUserDetails(Authentication authentication) {
Collection<? extends GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
ClientAuthenticationToken token = getAuthenticationToken(authentication);
if (token != null) {
UserDetails userDetails = pac4jUserDetailsService.loadUserDetails(token);
if (userDetails != null) {
this.userDetailsChecker.check(userDetails);
authorities = userDetails.getAuthorities();
}
ClientAuthenticationToken result = new ClientAuthenticationToken((Credentials) token.getCredentials(),
token.getClientName(), token.getUserProfile(), authorities);
result.setDetails(userDetails);
return result;
}
return null;
}
private ClientAuthenticationToken getAuthenticationToken(Authentication authentication) {
return authentication instanceof ClientAuthenticationToken ? (ClientAuthenticationToken) authentication : null;
}
}