Commit d19b55a9 authored by michael.simon's avatar michael.simon
Browse files

Refactor and speedup saml2post handler to service layer

parent 4b67382c
......@@ -18,4 +18,5 @@ public interface SamlUserDao extends BaseDao<SamlUserEntity, Long> {
String persistentId);
SamlUserEntity findByEppn(String eppn);
SamlUserEntity findByIdWithStore(Long id);
SamlUserEntity findByPersistent(String spId, String idpId, String persistentId);
}
......@@ -54,6 +54,26 @@ public class JpaSamlUserDao extends JpaBaseDao<SamlUserEntity, Long> implements
}
}
@Override
public SamlUserEntity findByPersistent(String spId, String idpId, String persistentId) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<SamlUserEntity> criteria = builder.createQuery(SamlUserEntity.class);
Root<SamlUserEntity> user = criteria.from(SamlUserEntity.class);
criteria.where(builder.and(
builder.equal(user.get("persistentSpId"), spId),
builder.equal(user.get("persistentIdpId"), idpId),
builder.equal(user.get("persistentId"), persistentId)
));
criteria.select(user);
try {
return em.createQuery(criteria).getSingleResult();
}
catch (NoResultException e) {
return null;
}
}
@Override
public SamlUserEntity findByEppn(String eppn) {
CriteriaBuilder builder = em.getCriteriaBuilder();
......
package edu.kit.scc.webreg.service.saml;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import edu.kit.scc.webreg.entity.SamlSpConfigurationEntity;
public interface SamlSpPostService {
void consumePost(HttpServletRequest request, HttpServletResponse response, SamlSpConfigurationEntity spConfig)
throws Exception;
}
package edu.kit.scc.webreg.service.saml;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.opensaml.messaging.decoder.MessageDecodingException;
import org.opensaml.saml.saml2.core.Assertion;
import org.opensaml.saml.saml2.core.Response;
import org.opensaml.saml.saml2.metadata.EntityDescriptor;
import org.opensaml.xmlsec.encryption.support.DecryptionException;
import org.slf4j.Logger;
import org.slf4j.MDC;
import edu.kit.scc.webreg.bootstrap.ApplicationConfig;
import edu.kit.scc.webreg.dao.SamlIdpMetadataDao;
import edu.kit.scc.webreg.dao.SamlUserDao;
import edu.kit.scc.webreg.drools.KnowledgeSessionService;
import edu.kit.scc.webreg.entity.SamlIdpMetadataEntity;
import edu.kit.scc.webreg.entity.SamlIdpMetadataEntityStatus;
import edu.kit.scc.webreg.entity.SamlSpConfigurationEntity;
import edu.kit.scc.webreg.entity.SamlUserEntity;
import edu.kit.scc.webreg.exc.SamlAuthenticationException;
import edu.kit.scc.webreg.exc.UserUpdateException;
import edu.kit.scc.webreg.service.impl.UserUpdater;
import edu.kit.scc.webreg.session.SessionManager;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
@Stateless
public class SamlSpPostServiceImpl implements SamlSpPostService {
@Inject
private Logger logger;
@Inject
private SamlIdpMetadataDao idpDao;
@Inject
private SamlUserDao userDao;
@Inject
private UserUpdater userUpdater;
@Inject
private SamlHelper samlHelper;
@Inject
private Saml2DecoderService saml2DecoderService;
@Inject
private Saml2AssertionService saml2AssertionService;
@Inject
private KnowledgeSessionService knowledgeSessionService;
@Inject
private ApplicationConfig appConfig;
@Inject
private SessionManager session;
@Override
public void consumePost(HttpServletRequest request, HttpServletResponse response,
SamlSpConfigurationEntity spConfig) throws Exception {
try {
SamlIdpMetadataEntity idpEntity = idpDao.findById(session.getIdpId());
EntityDescriptor idpEntityDescriptor = samlHelper.unmarshal(
idpEntity.getEntityDescriptor(), EntityDescriptor.class);
Assertion assertion;
String persistentId;
try {
Response samlResponse = saml2DecoderService.decodePostMessage(request);
assertion = saml2AssertionService.processSamlResponse(samlResponse, idpEntity, idpEntityDescriptor, spConfig);
persistentId = saml2AssertionService.extractPersistentId(assertion, spConfig);
} catch (Exception e1) {
/*
* Catch Exception here for a probably faulty IDP. Register Exception and rethrow.
*/
if (! SamlIdpMetadataEntityStatus.FAULTY.equals(idpEntity.getIdIdpStatus())) {
idpEntity.setIdIdpStatus(SamlIdpMetadataEntityStatus.FAULTY);
idpEntity.setLastIdStatusChange(new Date());
}
throw e1;
}
if (! SamlIdpMetadataEntityStatus.GOOD.equals(idpEntity.getIdIdpStatus())) {
idpEntity.setIdIdpStatus(SamlIdpMetadataEntityStatus.GOOD);
idpEntity.setLastIdStatusChange(new Date());
}
Map<String, List<Object>> attributeMap = saml2AssertionService.extractAttributes(assertion);
SamlUserEntity user = userDao.findByPersistent(spConfig.getEntityId(),
idpEntity.getEntityId(), persistentId);
if (user != null) {
MDC.put("userId", "" + user.getId());
}
String userLoginRule = appConfig.getConfigValue("user_login_rule");
if (userLoginRule != null && (! "".equals(userLoginRule))) {
logger.debug("Checking User login rule {}", userLoginRule);
long start = System.currentTimeMillis();
knowledgeSessionService.checkRule(userLoginRule, user, attributeMap, assertion,
idpEntity, idpEntityDescriptor, spConfig);
long end = System.currentTimeMillis();
logger.debug("Rule processing took {} ms", end - start);
}
if (user == null) {
logger.info("New User detected, sending to register Page");
// Store SAML Data temporarily in Session
logger.debug("Storing relevant SAML data in session");
session.setPersistentId(persistentId);
session.setAttributeMap(attributeMap);
response.sendRedirect("/register/register.xhtml");
return;
}
logger.debug("Updating user {}", persistentId);
try {
user = userUpdater.updateUser(user, assertion, "web-sso");
} catch (UserUpdateException e) {
logger.warn("Could not update user {}: {}", e.getMessage(), user.getEppn());
throw new SamlAuthenticationException(e.getMessage());
}
session.setUserId(user.getId());
session.setTheme(user.getTheme());
session.setLocale(user.getLocale());
if (session.getOriginalRequestPath() != null) {
String orig = session.getOriginalRequestPath();
session.setOriginalRequestPath(null);
response.sendRedirect(orig);
}
else
response.sendRedirect("/index.xhtml");
return;
} catch (MessageDecodingException e) {
throw new ServletException("Authentication problem", e);
} catch (SecurityException e) {
throw new ServletException("Authentication problem", e);
} catch (DecryptionException e) {
throw new ServletException("Authentication problem", e);
} catch (SamlAuthenticationException e) {
throw new ServletException("Authentication problem", e);
} catch (ComponentInitializationException e) {
throw new ServletException("Authentication problem", e);
}
}
}
......@@ -11,8 +11,6 @@
package edu.kit.scc.webreg.sec;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import javax.faces.bean.ApplicationScoped;
import javax.inject.Inject;
......@@ -20,29 +18,11 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.opensaml.messaging.decoder.MessageDecodingException;
import org.opensaml.saml.saml2.core.Assertion;
import org.opensaml.saml.saml2.core.Response;
import org.opensaml.saml.saml2.metadata.EntityDescriptor;
import org.opensaml.xmlsec.encryption.support.DecryptionException;
import org.slf4j.Logger;
import org.slf4j.MDC;
import edu.kit.scc.webreg.bootstrap.ApplicationConfig;
import edu.kit.scc.webreg.drools.KnowledgeSessionService;
import edu.kit.scc.webreg.entity.SamlIdpMetadataEntity;
import edu.kit.scc.webreg.entity.SamlIdpMetadataEntityStatus;
import edu.kit.scc.webreg.entity.SamlSpConfigurationEntity;
import edu.kit.scc.webreg.entity.SamlUserEntity;
import edu.kit.scc.webreg.exc.SamlAuthenticationException;
import edu.kit.scc.webreg.exc.UserUpdateException;
import edu.kit.scc.webreg.service.SamlIdpMetadataService;
import edu.kit.scc.webreg.service.UserService;
import edu.kit.scc.webreg.service.saml.Saml2AssertionService;
import edu.kit.scc.webreg.service.saml.Saml2DecoderService;
import edu.kit.scc.webreg.service.saml.SamlHelper;
import edu.kit.scc.webreg.service.saml.SamlSpPostService;
import edu.kit.scc.webreg.session.SessionManager;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
@ApplicationScoped
public class Saml2PostHandler {
......@@ -54,25 +34,7 @@ public class Saml2PostHandler {
private SessionManager session;
@Inject
private UserService userService;
@Inject
private Saml2DecoderService saml2DecoderService;
@Inject
private Saml2AssertionService saml2AssertionService;
@Inject
private SamlHelper samlHelper;
@Inject
private SamlIdpMetadataService idpService;
@Inject
private KnowledgeSessionService knowledgeSessionService;
@Inject
private ApplicationConfig appConfig;
private SamlSpPostService spPostService;
public void service(HttpServletRequest request, HttpServletResponse response, SamlSpConfigurationEntity spConfig)
throws ServletException, IOException {
......@@ -87,94 +49,9 @@ public class Saml2PostHandler {
logger.debug("attempAuthentication, Consuming SAML Assertion");
try {
SamlIdpMetadataEntity idpEntity = idpService.findById(session.getIdpId());
EntityDescriptor idpEntityDescriptor = samlHelper.unmarshal(
idpEntity.getEntityDescriptor(), EntityDescriptor.class);
Assertion assertion;
String persistentId;
try {
Response samlResponse = saml2DecoderService.decodePostMessage(request);
assertion = saml2AssertionService.processSamlResponse(samlResponse, idpEntity, idpEntityDescriptor, spConfig);
persistentId = saml2AssertionService.extractPersistentId(assertion, spConfig);
} catch (Exception e1) {
/*
* Catch Exception here for a probably faulty IDP. Register Exception and rethrow.
*/
idpService.updateIdpStatus(SamlIdpMetadataEntityStatus.FAULTY, idpEntity);
throw e1;
}
idpService.updateIdpStatus(SamlIdpMetadataEntityStatus.GOOD, idpEntity);
Map<String, List<Object>> attributeMap = saml2AssertionService.extractAttributes(assertion);
SamlUserEntity user = userService.findByPersistentWithRoles(spConfig.getEntityId(),
idpEntity.getEntityId(), persistentId);
if (user != null) {
MDC.put("userId", "" + user.getId());
}
String userLoginRule = appConfig.getConfigValue("user_login_rule");
if (userLoginRule != null && (! "".equals(userLoginRule))) {
logger.debug("Checking User login rule {}", userLoginRule);
long start = System.currentTimeMillis();
knowledgeSessionService.checkRule(userLoginRule, user, attributeMap, assertion,
idpEntity, idpEntityDescriptor, spConfig);
long end = System.currentTimeMillis();
logger.debug("Rule processing took {} ms", end - start);
}
if (user == null) {
logger.info("New User detected, sending to register Page");
// Store SAML Data temporarily in Session
logger.debug("Storing relevant SAML data in session");
session.setPersistentId(persistentId);
session.setAttributeMap(attributeMap);
response.sendRedirect("/register/register.xhtml");
return;
}
logger.debug("Updating user {}", persistentId);
try {
user = userService.updateUserFromAssertion(user, assertion, "web-sso");
} catch (UserUpdateException e) {
logger.warn("Could not update user {}: {}", e.getMessage(), user.getEppn());
throw new SamlAuthenticationException(e.getMessage());
}
spPostService.consumePost(request, response, spConfig);
session.setUserId(user.getId());
session.setTheme(user.getTheme());
session.setLocale(user.getLocale());
if (session.getOriginalRequestPath() != null) {
String orig = session.getOriginalRequestPath();
session.setOriginalRequestPath(null);
response.sendRedirect(orig);
}
else
response.sendRedirect("/index.xhtml");
return;
} catch (MessageDecodingException e) {
throw new ServletException("Authentication problem", e);
} catch (SecurityException e) {
throw new ServletException("Authentication problem", e);
} catch (DecryptionException e) {
throw new ServletException("Authentication problem", e);
} catch (SamlAuthenticationException e) {
throw new ServletException("Authentication problem", e);
} catch (ComponentInitializationException e) {
} catch (Exception e) {
throw new ServletException("Authentication problem", e);
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment