use of com.tremolosecurity.proxy.auth.saml2.Saml2SingleLogout in project OpenUnison by TremoloSecurity.
the class SAML2Auth method doPost.
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp, AuthStep as) throws ServletException, IOException {
MyVDConnection myvd = cfgMgr.getMyVD();
// HttpSession session = (HttpSession)
// req.getAttribute(ConfigFilter.AUTOIDM_SESSION);//((HttpServletRequest)
// req).getSession();
// //SharedSession.getSharedSession().getSession(req.getSession().getId());
// SharedSession.getSharedSession().getSession(req.getSession().getId());
HttpSession session = ((HttpServletRequest) req).getSession();
UrlHolder holder = (UrlHolder) req.getAttribute(ProxyConstants.AUTOIDM_CFG);
String urlChain = holder.getUrl().getAuthChain();
AuthChainType act = holder.getConfig().getAuthChains().get(urlChain);
AuthInfo userData = ((AuthController) req.getSession().getAttribute(ProxyConstants.AUTH_CTL)).getAuthInfo();
if (userData.isAuthComplete() && userData.getAuthLevel() > 0) {
// Session is already set, just redirect to relay state
String relayState = this.getFinalURL(req, resp);
if (relayState == null) {
throw new ServletException("No RelayState or default RelayState");
}
resp.sendRedirect(relayState);
return;
}
if (as == null) {
// this is a special case - idp initiated means there's no context
ArrayList<AuthStep> auths = ((AuthController) session.getAttribute(ProxyConstants.AUTH_CTL)).getAuthSteps();
int id = 0;
for (AuthMechType amt : act.getAuthMech()) {
AuthStep asx = new AuthStep();
asx.setId(id);
asx.setExecuted(false);
asx.setRequired(amt.getRequired().equals("required"));
asx.setSuccess(false);
auths.add(asx);
id++;
}
as = auths.get(0);
}
HashMap<String, Attribute> authParams = (HashMap<String, Attribute>) session.getAttribute(ProxyConstants.AUTH_MECH_PARAMS);
String defaultOC = authParams.get("defaultOC").getValues().get(0);
String spEncKey = null;
if (authParams.get("spEncKey") != null) {
spEncKey = authParams.get("spEncKey").getValues().get(0);
}
RequestHolder reqHolder = ((AuthController) session.getAttribute(ProxyConstants.AUTH_CTL)).getHolder();
AuthMechType amt = act.getAuthMech().get(as.getId());
List<String> sigCertNames = authParams.get("idpSigKeyName").getValues();
List<X509Certificate> sigCerts = new ArrayList<X509Certificate>();
boolean isMultiIdp = authParams.get("isMultiIdP") != null && authParams.get("isMultiIdP").getValues().get(0).equalsIgnoreCase("true");
String ldapAttrib = authParams.get("ldapAttribute").getValues().get(0);
String dnLabel = authParams.get("dnOU").getValues().get(0);
String samlResp = req.getParameter("SAMLResponse");
String xml = null;
xml = new String(Base64.decodeBase64(samlResp), "UTF-8");
boolean assertionSigned = true;
if (authParams.get("assertionsSigned") != null) {
assertionSigned = Boolean.parseBoolean(authParams.get("assertionsSigned").getValues().get(0));
}
boolean responseSigned = false;
if (authParams.get("responsesSigned") != null) {
responseSigned = Boolean.parseBoolean(authParams.get("responsesSigned").getValues().get(0));
}
boolean assertionEncrypted = false;
if (authParams.get("assertionEncrypted") != null) {
assertionEncrypted = Boolean.parseBoolean(authParams.get("assertionEncrypted").getValues().get(0));
}
if (logger.isDebugEnabled()) {
logger.debug("=========saml2resp============");
logger.debug(xml);
logger.debug("=========saml2resp============");
}
xml = xml.replaceAll("<!--.*-->", "");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Element root = builder.parse(new InputSource(new StringReader(xml))).getDocumentElement();
Response samlResponse = (Response) XMLObjectSupport.getUnmarshaller(root).unmarshall(root);
if (isMultiIdp) {
try {
String dn = authParams.get("idpDir").getValues().get(0);
LDAPSearchResults res = cfgMgr.getMyVD().search(dn, 2, equal("issuer", samlResponse.getIssuer().getValue()).toString(), new ArrayList<String>());
if (!res.hasMore()) {
throw new ServletException("No IdP found");
}
LDAPEntry entry = res.next();
java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X.509");
sigCerts.add((java.security.cert.X509Certificate) cf.generateCertificate(new ByteArrayInputStream(Base64.decodeBase64(entry.getAttribute("idpSig").getStringValue()))));
} catch (LDAPException e) {
throw new ServletException("Could not load IdP data", e);
} catch (CertificateException e) {
throw new ServletException("Could not load IdP data", e);
}
} else {
for (String sigCertName : sigCertNames) {
sigCerts.add(cfgMgr.getCertificate(sigCertName));
}
}
if (responseSigned) {
if (samlResponse.getSignature() != null) {
boolean foundSigned = false;
for (X509Certificate sigCert : sigCerts) {
if (sigCert != null) {
BasicCredential sigCred = new BasicCredential(sigCert.getPublicKey());
sigCred.setUsageType(UsageType.SIGNING);
try {
SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
profileValidator.validate(samlResponse.getSignature());
SignatureValidator.validate(samlResponse.getSignature(), sigCred);
foundSigned = true;
} catch (org.opensaml.xmlsec.signature.support.SignatureException se) {
}
}
}
if (!foundSigned) {
throw new ServletException("could not validate response");
}
} else {
throw new Exception("Response not signed");
}
}
Assertion assertion = null;
if (samlResponse.getEncryptedAssertions().size() > 0) {
try {
EncryptedAssertion encAssertion = samlResponse.getEncryptedAssertions().get(0);
PrivateKey privKey = this.cfgMgr.getPrivateKey(spEncKey);
PublicKey pubKey = this.cfgMgr.getCertificate(spEncKey).getPublicKey();
Credential credential = new BasicCredential(pubKey, privKey);
StaticKeyInfoCredentialResolver resolver = new StaticKeyInfoCredentialResolver(credential);
Decrypter decrypter = new Decrypter(null, resolver, new InlineEncryptedKeyResolver());
decrypter.setRootInNewDocument(true);
assertion = decrypter.decrypt(encAssertion);
} catch (Exception e) {
throw new ServletException("Error decrypting assertion", e);
}
} else {
if (assertionEncrypted) {
throw new Exception("Assertion not encrypted");
}
if (samlResponse.getAssertions().size() == 0) {
throw new Exception("No assertions found");
}
assertion = (Assertion) samlResponse.getAssertions().get(0);
}
if (assertionSigned) {
if (assertion.getSignature() != null) {
boolean foundSigned = false;
for (X509Certificate sigCert : sigCerts) {
if (sigCert != null) {
BasicCredential sigCred = new BasicCredential(sigCert.getPublicKey());
sigCred.setUsageType(UsageType.SIGNING);
try {
SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
profileValidator.validate(assertion.getSignature());
SignatureValidator.validate(assertion.getSignature(), sigCred);
foundSigned = true;
} catch (org.opensaml.xmlsec.signature.support.SignatureException se) {
}
}
}
if (!foundSigned) {
throw new ServletException("Assertion can not be validated with a trusted certificate");
}
} else {
throw new Exception("No assertion signature");
}
}
// If it made it here, the assertion is valid, lets check the authncontextclassref
Attribute authnContextClassRef = authParams.get("authCtxRef");
if (authnContextClassRef != null && authnContextClassRef.getValues().size() > 0 && !authnContextClassRef.getValues().get(0).isEmpty() && !authnContextClassRef.getValues().get(0).equalsIgnoreCase("none") && (assertion.getAuthnStatements() == null || assertion.getAuthnStatements().size() == 0 || assertion.getAuthnStatements().get(0).getAuthnContext() == null || assertion.getAuthnStatements().get(0).getAuthnContext().getAuthnContextClassRef() == null || assertion.getAuthnStatements().get(0).getAuthnContext() == null || assertion.getAuthnStatements().get(0).getAuthnContext().getAuthnContextClassRef() == null || assertion.getAuthnStatements().get(0).getAuthnContext().getAuthnContextClassRef().getURI() == null || !assertion.getAuthnStatements().get(0).getAuthnContext().getAuthnContextClassRef().getURI().equalsIgnoreCase(authnContextClassRef.getValues().get(0)))) {
logger.warn("Can not validate the authentication context classref");
as.setSuccess(false);
holder.getConfig().getAuthManager().nextAuth(req, resp, session, false);
return;
}
try {
if (authParams.get("dontLinkToLDAP") == null || authParams.get("dontLinkToLDAP").getValues().get(0).equalsIgnoreCase("false")) {
StringBuffer filter = new StringBuffer();
filter.append('(').append(ldapAttrib).append('=').append(assertion.getSubject().getNameID().getValue()).append(')');
LDAPSearchResults res = myvd.search(AuthUtil.getChainRoot(cfgMgr, act), 2, filter.toString(), new ArrayList<String>());
if (res.hasMore()) {
createUserFromDir(session, act, ldapAttrib, assertion, res);
} else {
createUnlinkedUser(session, act, ldapAttrib, dnLabel, defaultOC, assertion);
}
} else {
createUnlinkedUser(session, act, ldapAttrib, dnLabel, defaultOC, assertion);
}
} catch (LDAPException e) {
if (e.getResultCode() == 32) {
createUnlinkedUser(session, act, ldapAttrib, dnLabel, defaultOC, assertion);
} else {
throw e;
}
}
// logout management
Attribute logoutURLAttr = authParams.get("idpRedirLogoutURL");
if (logoutURLAttr != null && logoutURLAttr.getValues().size() > 0 && !logoutURLAttr.getValues().get(0).isEmpty() && authParams.get("spSigKey") != null && authParams.get("spSigKey").getValues().size() > 0) {
String logoutURL = logoutURLAttr.getValues().get(0);
String sessionIndex = assertion.getAuthnStatements().get(0).getSessionIndex();
String nameID = assertion.getSubject().getNameID().getValue();
String nameIDFormat = assertion.getSubject().getNameID().getFormat();
Saml2SingleLogout handler = new Saml2SingleLogout(logoutURL, sessionIndex, nameID, nameIDFormat, samlResponse.getDestination(), authParams.get("spSigKey").getValues().get(0), authParams.get("sigAlg").getValues().get(0), authParams.get("entityID").getValues().get(0));
LogoutUtil.addLogoutHandler(req, handler);
}
as.setSuccess(true);
} catch (Exception e) {
logger.error("Error Parsing Assertion", e);
throw new ServletException("error parsing assertion", e);
}
holder.getConfig().getAuthManager().nextAuth(req, resp, session, false);
}
Aggregations