/******************************************************************************* *******************************************************************************/ package at.gv.egiz.eaaf.modules.pvp2.sp.impl.utils; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.opensaml.saml2.core.Assertion; import org.opensaml.saml2.core.Attribute; import org.opensaml.saml2.core.AttributeStatement; import org.opensaml.saml2.core.AuthnContextClassRef; import org.opensaml.saml2.core.AuthnStatement; import org.opensaml.saml2.core.Response; import org.opensaml.saml2.core.StatusResponseType; import org.opensaml.saml2.core.Subject; import org.opensaml.xml.XMLObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AssertionAttributeExtractorExeption; public class AssertionAttributeExtractor { private static final Logger log = LoggerFactory.getLogger(AssertionAttributeExtractor.class); private Assertion assertion = null; private Map> attributs = new HashMap>(); //private PersonalAttributeList storkAttributes = new PersonalAttributeList(); private final List minimalMDSAttributeNamesList = Arrays.asList( PVPConstants.PRINCIPAL_NAME_NAME, PVPConstants.GIVEN_NAME_NAME, PVPConstants.BIRTHDATE_NAME, PVPConstants.BPK_NAME); private final List minimalIDLAttributeNamesList = Arrays.asList( PVPConstants.EID_IDENTITY_LINK_NAME, PVPConstants.EID_SOURCE_PIN_NAME, PVPConstants.EID_SOURCE_PIN_TYPE_NAME); /** * Parse the SAML2 Response element and extracts included information *

* INFO: Actually, only the first SAML2 Assertion of the SAML2 Response is used! * * @param samlResponse SAML2 Response * @throws AssertionAttributeExtractorExeption */ public AssertionAttributeExtractor(StatusResponseType samlResponse) throws AssertionAttributeExtractorExeption { if (samlResponse != null && samlResponse instanceof Response) { List assertions = ((Response) samlResponse).getAssertions(); if (assertions.size() == 0) throw new AssertionAttributeExtractorExeption("Assertion"); else if (assertions.size() > 1) log.warn("Found more then ONE PVP2.1 assertions. Only the First is used."); assertion = assertions.get(0); if (assertion.getAttributeStatements() != null && assertion.getAttributeStatements().size() > 0) { AttributeStatement attrStat = assertion.getAttributeStatements().get(0); for (Attribute attr : attrStat.getAttributes()) { if (attr.getName().startsWith(PVPConstants.STORK_ATTRIBUTE_PREFIX)) { List storkAttrValues = new ArrayList(); for (XMLObject el : attr.getAttributeValues()) storkAttrValues.add(el.getDOM().getTextContent()); // PersonalAttribute storkAttr = new PersonalAttribute(attr.getName(), // false, storkAttrValues , "Available"); // storkAttributes.put(attr.getName(), storkAttr ); } else { List attrList = new ArrayList(); for (XMLObject el : attr.getAttributeValues()) attrList.add(el.getDOM().getTextContent()); attributs.put(attr.getName(), attrList); } } } } else throw new AssertionAttributeExtractorExeption(); } /** * Get all SAML2 attributes from first SAML2 AttributeStatement element * * @return List of SAML2 Attributes */ public List getAllResponseAttributesFromFirstAttributeStatement() { return assertion.getAttributeStatements().get(0).getAttributes(); } /** * Get all SAML2 attributes of specific SAML2 AttributeStatement element * * @param attrStatementID List ID of the AttributeStatement element * @return List of SAML2 Attributes */ public List getAllResponseAttributes(int attrStatementID) { return assertion.getAttributeStatements().get(attrStatementID).getAttributes(); } /** * check attributes from assertion with minimal required attribute list * @return */ public boolean containsAllRequiredAttributes() { return containsAllRequiredAttributes(minimalMDSAttributeNamesList) || containsAllRequiredAttributes(minimalIDLAttributeNamesList); } /** * check attributes from assertion with attributeNameList * bPK or enc_bPK are always needed * * @param List of attributes which are required * * @return */ public boolean containsAllRequiredAttributes(Collection attributeNameList) { //first check if a bPK or an encrypted bPK is available boolean flag = true; for (String attr : attributeNameList) { if (!attributs.containsKey(attr)) { flag = false; log.debug("Assertion contains no Attribute " + attr); } } if (flag) return flag; else { log.debug("Assertion contains no all minimum attributes from: " + attributeNameList.toString()); return false; } } public boolean containsAttribute(String attributeName) { return attributs.containsKey(attributeName); } public String getSingleAttributeValue(String attributeName) { if (attributs.containsKey(attributeName) && attributs.get(attributeName).size() > 0) return attributs.get(attributeName).get(0); else return null; } public List getAttributeValues(String attributeName) { return attributs.get(attributeName); } /** * Return all include PVP attribute names * * @return */ public Set getAllIncludeAttributeNames() { return attributs.keySet(); } // public PersonalAttributeList getSTORKAttributes() { // return storkAttributes; // } public String getNameID() throws AssertionAttributeExtractorExeption { if (assertion.getSubject() != null) { Subject subject = assertion.getSubject(); if (subject.getNameID() != null) { if (StringUtils.isNotEmpty(subject.getNameID().getValue())) return subject.getNameID().getValue(); else log.error("SAML2 NameID Element is empty."); } } throw new AssertionAttributeExtractorExeption("nameID"); } public String getSessionIndex() throws AssertionAttributeExtractorExeption { AuthnStatement authn = getAuthnStatement(); if (StringUtils.isNotEmpty(authn.getSessionIndex())) return authn.getSessionIndex(); else throw new AssertionAttributeExtractorExeption("SessionIndex"); } /** * @return * @throws AssertionAttributeExtractorExeption */ public String getQAALevel() throws AssertionAttributeExtractorExeption { AuthnStatement authn = getAuthnStatement(); if (authn.getAuthnContext() != null && authn.getAuthnContext().getAuthnContextClassRef() != null) { AuthnContextClassRef qaaClass = authn.getAuthnContext().getAuthnContextClassRef(); if (StringUtils.isNotEmpty(qaaClass.getAuthnContextClassRef())) return qaaClass.getAuthnContextClassRef(); else throw new AssertionAttributeExtractorExeption("AuthnContextClassRef (QAALevel)"); } throw new AssertionAttributeExtractorExeption("AuthnContextClassRef"); } public Assertion getFullAssertion() { return assertion; } /** * Get the Assertion validTo period * * Primarily, the 'SessionNotOnOrAfter' attribute in the SAML2 'AuthnStatment' element is used. * If this is empty, this method returns value of SAML 'Conditions' element. * * @return Date, until this SAML2 assertion is valid */ public Date getAssertionNotOnOrAfter() { if (getFullAssertion().getAuthnStatements() != null && getFullAssertion().getAuthnStatements().size() > 0) { for (AuthnStatement el : getFullAssertion().getAuthnStatements()) { if (el.getSessionNotOnOrAfter() != null) return (el.getSessionNotOnOrAfter().toDate()); } } return getFullAssertion().getConditions().getNotOnOrAfter().toDate(); } private AuthnStatement getAuthnStatement() throws AssertionAttributeExtractorExeption { List authnList = assertion.getAuthnStatements(); if (authnList.size() == 0) throw new AssertionAttributeExtractorExeption("AuthnStatement"); else if (authnList.size() > 1) log.warn("Found more then ONE AuthnStatements in PVP2.1 assertions. Only the First is used."); return authnList.get(0); } }