143 lines
6.2 KiB
Java
143 lines
6.2 KiB
Java
package net.gepafin.tendermanagement.config;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.IOException;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import javax.xml.parsers.DocumentBuilder;
|
|
import javax.xml.parsers.DocumentBuilderFactory;
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.security.core.Authentication;
|
|
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
|
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
|
import org.springframework.stereotype.Component;
|
|
import org.w3c.dom.Document;
|
|
import org.w3c.dom.Element;
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
import net.gepafin.tendermanagement.constants.GepafinConstant;
|
|
import net.gepafin.tendermanagement.entities.HubEntity;
|
|
import net.gepafin.tendermanagement.entities.SamlResponseEntity;
|
|
import net.gepafin.tendermanagement.entities.UserEntity;
|
|
import net.gepafin.tendermanagement.enums.SamlResponseStatusEnum;
|
|
import net.gepafin.tendermanagement.repositories.SamlResponseRepository;
|
|
import net.gepafin.tendermanagement.repositories.UserRepository;
|
|
import net.gepafin.tendermanagement.service.HubService;
|
|
import net.gepafin.tendermanagement.util.Utils;
|
|
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
|
|
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
|
|
|
|
@Component
|
|
public class SamlSuccessHandler implements AuthenticationSuccessHandler {
|
|
|
|
private final Logger logger = LoggerFactory.getLogger(SamlSuccessHandler.class);
|
|
|
|
@Autowired
|
|
private SamlResponseRepository samlResponseLogRepository;
|
|
|
|
@Autowired
|
|
private UserRepository userRepository;
|
|
|
|
@Value("${fe.base.url}")
|
|
private String feBaseUrl;
|
|
|
|
@Autowired
|
|
private HubService hubService;
|
|
|
|
@Override
|
|
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
|
|
Authentication authentication) throws IOException {
|
|
try {
|
|
logger.info("SAML login in Authentication Success Handler");
|
|
Saml2Authentication samlAuth = (Saml2Authentication) authentication;
|
|
Saml2AuthenticatedPrincipal principal = (Saml2AuthenticatedPrincipal) samlAuth.getPrincipal();
|
|
|
|
Map<String, List<Object>> userAttributes = principal.getAttributes();
|
|
String token = Utils.generateSecureToken();
|
|
logger.info("SAML User Attributes: " + userAttributes);
|
|
|
|
// Extracting raw SAML response
|
|
String samlResponse = samlAuth.getSaml2Response();
|
|
logger.info("Raw SAML Response: " + samlResponse);
|
|
|
|
// If samlResponse is already in XML format, do not Base64 decode it
|
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
|
factory.setNamespaceAware(true);
|
|
DocumentBuilder builder = factory.newDocumentBuilder();
|
|
Document document = builder.parse(new ByteArrayInputStream(samlResponse.getBytes())); // Remove the Base64 decoding
|
|
|
|
// Extracting ID, InResponseTo, and IssueInstant from the Response element
|
|
Element responseElement = (Element) document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:protocol", "Response").item(0);
|
|
String responseId = responseElement.getAttribute("ID");
|
|
String inResponseTo = responseElement.getAttribute("InResponseTo");
|
|
String issueInstant = responseElement.getAttribute("IssueInstant");
|
|
|
|
logger.info("SAML Response ID: " + responseId);
|
|
logger.info("InResponseTo: " + inResponseTo);
|
|
logger.info("IssueInstant: " + issueInstant);
|
|
|
|
SamlResponseEntity samlResponseLogEntity = samlResponseLogRepository
|
|
.findByInResponseToAndStatus(inResponseTo, SamlResponseStatusEnum.INITIATED.getValue())
|
|
.orElseThrow(() -> new CustomValidationException(Status.BAD_REQUEST,
|
|
Translator.toLocale(GepafinConstant.INVALID_REQUEST)));
|
|
ObjectMapper objectMapper = new ObjectMapper();
|
|
String userAttributesJson = objectMapper.writeValueAsString(userAttributes);
|
|
|
|
samlResponseLogEntity.setAuthenticationObject(userAttributesJson);
|
|
samlResponseLogEntity.setToken(token);
|
|
samlResponseLogEntity.setStatus(SamlResponseStatusEnum.SUCCESS.getValue());
|
|
samlResponseLogEntity.setInResponseTo(inResponseTo);
|
|
samlResponseLogEntity.setSamlId(responseId);
|
|
samlResponseLogEntity.setIssueInstant(issueInstant);
|
|
samlResponseLogRepository.save(samlResponseLogEntity);
|
|
|
|
HubEntity hub = hubService.getHubByUuid(samlResponseLogEntity.getHubUuid());
|
|
|
|
String redirectUrl = feBaseUrl;
|
|
if (Boolean.FALSE.equals(StringUtils.isEmpty(hub.getDomainName()))) {
|
|
redirectUrl = hub.getDomainName();
|
|
}
|
|
|
|
logger.info("SAML login successful for user: " + principal.getName());
|
|
String cf = userAttributes.get("CodiceFiscale").get(0).toString();
|
|
UserEntity userEntity = userRepository.findByBeneficiaryCodiceFiscale(cf).orElse(null);
|
|
if (userEntity == null) {
|
|
redirectUrl += "/registration?temp_token=" + token;
|
|
} else {
|
|
redirectUrl += "/login?temp_token=" + token;
|
|
}
|
|
response.sendRedirect(redirectUrl);
|
|
logger.info("SAML redirect Url: " + redirectUrl);
|
|
} catch (Exception e) {
|
|
logger.error("Error processing SAML success handler", e);
|
|
}
|
|
}
|
|
|
|
public void validateToken(String token, String codiceFiscale) {
|
|
SamlResponseEntity samlResponseLogEntity = samlResponseLogRepository.findByToken(token);
|
|
if (samlResponseLogEntity == null) {
|
|
throw new CustomValidationException(Status.VALIDATION_ERROR,
|
|
Translator.toLocale(GepafinConstant.INVALID_TOKEN_MSG));
|
|
}
|
|
Map<String, List<Object>> userAttributes = Utils
|
|
.convertStringIntoMap(samlResponseLogEntity.getAuthenticationObject());
|
|
String cf = userAttributes.get("CodiceFiscale").get(0).toString();
|
|
if (codiceFiscale == null || Boolean.FALSE.equals(codiceFiscale.equals(cf))) {
|
|
throw new CustomValidationException(Status.VALIDATION_ERROR,
|
|
Translator.toLocale(GepafinConstant.INVALID_TOKEN_MSG));
|
|
}
|
|
samlResponseLogRepository.delete(samlResponseLogEntity);
|
|
}
|
|
|
|
}
|