From 759ac5f42c6aff901dbeede4fbf1a1d2e08cad0f Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 4 Dec 2019 19:43:32 +0100 Subject: common EGIZ code-style refactoring --- .../pvp2/sp/impl/PVPAuthnRequestBuilder.java | 259 --------- .../pvp2/sp/impl/PvpAuthnRequestBuilder.java | 263 +++++++++ .../sp/impl/utils/AssertionAttributeExtractor.java | 641 +++++++++++---------- 3 files changed, 591 insertions(+), 572 deletions(-) delete mode 100644 eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PVPAuthnRequestBuilder.java create mode 100644 eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java (limited to 'eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl') diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PVPAuthnRequestBuilder.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PVPAuthnRequestBuilder.java deleted file mode 100644 index e8cdd1f7..00000000 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PVPAuthnRequestBuilder.java +++ /dev/null @@ -1,259 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -package at.gv.egiz.eaaf.modules.pvp2.sp.impl; - -import java.security.NoSuchAlgorithmException; -import java.util.List; - -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.StringUtils; -import org.joda.time.DateTime; -import org.opensaml.common.impl.SecureRandomIdentifierGenerator; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.common.Extensions; -import org.opensaml.saml2.core.AuthnContextClassRef; -import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.core.Issuer; -import org.opensaml.saml2.core.NameID; -import org.opensaml.saml2.core.NameIDPolicy; -import org.opensaml.saml2.core.NameIDType; -import org.opensaml.saml2.core.RequestedAuthnContext; -import org.opensaml.saml2.core.RequesterID; -import org.opensaml.saml2.core.Scoping; -import org.opensaml.saml2.core.Subject; -import org.opensaml.saml2.core.SubjectConfirmation; -import org.opensaml.saml2.core.SubjectConfirmationData; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml2.metadata.SingleSignOnService; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.xml.security.SecurityException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.stereotype.Service; - -import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttributes; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; -import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding; -import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestExtensionBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; -import at.gv.egiz.eaaf.modules.pvp2.sp.api.IPVPAuthnRequestBuilderConfiguruation; -import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AuthnRequestBuildException; - -/** - * @author tlenz - * - */ -@Service("pvpAuthnRequestBuilder") -public class PVPAuthnRequestBuilder { - private static final Logger log = LoggerFactory.getLogger(PVPAuthnRequestBuilder.class); - - - @Autowired(required=true) ApplicationContext springContext; - - - /** - * Build a PVP2.x specific authentication request - * - * @param pendingReq Currently processed pendingRequest - * @param config AuthnRequest builder configuration, never null - * @param idpEntity SAML2 EntityDescriptor of the IDP, which receive this AuthnRequest, never null - * @param httpResp - * @throws NoSuchAlgorithmException - * @throws SecurityException - * @throws PVP2Exception - * @throws MessageEncodingException - */ - public void buildAuthnRequest(IRequest pendingReq, IPVPAuthnRequestBuilderConfiguruation config, - HttpServletResponse httpResp) throws NoSuchAlgorithmException, MessageEncodingException, PVP2Exception, SecurityException { - //get IDP Entity element from config - EntityDescriptor idpEntity = config.getIDPEntityDescriptor(); - - AuthnRequest authReq = SAML2Utils - .createSAMLObject(AuthnRequest.class); - - //select SingleSignOn Service endpoint from IDP metadata - SingleSignOnService endpoint = null; - for (SingleSignOnService sss : - idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) { - - // use POST binding as default if it exists - if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { - endpoint = sss; - - } else if ( sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) - && endpoint == null ) - endpoint = sss; - - } - - if (endpoint == null) { - log.warn("Building AuthnRequest FAILED: > Requested IDP " + idpEntity.getEntityID() - + " does not support POST or Redirect Binding."); - throw new AuthnRequestBuildException("sp.pvp2.00", new Object[]{config.getSPNameForLogging(), idpEntity.getEntityID()}); - - } else - authReq.setDestination(endpoint.getLocation()); - - - //set basic AuthnRequest information - String reqID = config.getRequestID(); - if (StringUtils.isNotEmpty(reqID)) - authReq.setID(reqID); - - else { - SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); - authReq.setID(gen.generateIdentifier()); - - } - - authReq.setIssueInstant(new DateTime()); - - //set isPassive flag - if (config.isPassivRequest() == null) - authReq.setIsPassive(false); - else - authReq.setIsPassive(config.isPassivRequest()); - - //set EntityID of the service provider - Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); - issuer.setFormat(NameIDType.ENTITY); - issuer.setValue(config.getSPEntityID()); - authReq.setIssuer(issuer); - - //set AssertionConsumerService ID - if (config.getAssertionConsumerServiceId() != null) - authReq.setAssertionConsumerServiceIndex(config.getAssertionConsumerServiceId()); - - //set NameIDPolicy - if (config.getNameIDPolicyFormat() != null) { - NameIDPolicy policy = SAML2Utils.createSAMLObject(NameIDPolicy.class); - policy.setAllowCreate(config.getNameIDPolicyAllowCreation()); - policy.setFormat(config.getNameIDPolicyFormat()); - authReq.setNameIDPolicy(policy); - } - - //set requested QAA level - if (config.getAuthnContextClassRef() != null) { - RequestedAuthnContext reqAuthContext = SAML2Utils.createSAMLObject(RequestedAuthnContext.class); - AuthnContextClassRef authnClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class); - - authnClassRef.setAuthnContextClassRef(config.getAuthnContextClassRef()); - - if (config.getAuthnContextComparison() == null) - reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); - else - reqAuthContext.setComparison(config.getAuthnContextComparison()); - - reqAuthContext.getAuthnContextClassRefs().add(authnClassRef); - authReq.setRequestedAuthnContext(reqAuthContext); - } - - //set request Subject element - if (StringUtils.isNotEmpty(config.getSubjectNameID())) { - Subject reqSubject = SAML2Utils.createSAMLObject(Subject.class); - NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class); - - subjectNameID.setValue(config.getSubjectNameID()); - if (StringUtils.isNotEmpty(config.getSubjectNameIDQualifier())) - subjectNameID.setNameQualifier(config.getSubjectNameIDQualifier()); - - if (StringUtils.isNotEmpty(config.getSubjectNameIDFormat())) - subjectNameID.setFormat(config.getSubjectNameIDFormat()); - else - subjectNameID.setFormat(NameID.TRANSIENT); - - reqSubject.setNameID(subjectNameID); - - if (config.getSubjectConformationDate() != null) { - SubjectConfirmation subjectConformation = SAML2Utils.createSAMLObject(SubjectConfirmation.class); - SubjectConfirmationData subjectConformDate = SAML2Utils.createSAMLObject(SubjectConfirmationData.class); - subjectConformation.setSubjectConfirmationData(subjectConformDate); - reqSubject.getSubjectConfirmations().add(subjectConformation ); - - if (config.getSubjectConformationMethode() != null) - subjectConformation.setMethod(config.getSubjectConformationMethode()); - - subjectConformDate.setDOM(config.getSubjectConformationDate()); - - } - - authReq.setSubject(reqSubject ); - - } - - - //set ProviderName - if (StringUtils.isNotEmpty(config.getProviderName())) - authReq.setProviderName(config.getProviderName()); - - //set RequesterId in case of proxy mode - if (StringUtils.isNotEmpty(config.getScopeRequesterId())) { - Scoping scope = SAML2Utils.createSAMLObject(Scoping.class); - RequesterID requesterId = SAML2Utils.createSAMLObject(RequesterID.class); - requesterId.setRequesterID(config.getScopeRequesterId()); - scope.getRequesterIDs().add(requesterId ); - authReq.setScoping(scope ); - - } - - //add optional requested attributes - if (config.getRequestedAttributes() != null) { - List reqAttr = config.getRequestedAttributes(); - Extensions extenstions = new EAAFRequestExtensionBuilder().buildObject(); - EAAFRequestedAttributes reqAttributs = SAML2Utils.createSAMLObject(EAAFRequestedAttributes.class); - reqAttributs.getAttributes().addAll(reqAttr); - extenstions.getUnknownXMLObjects().add(reqAttributs); - authReq.setExtensions(extenstions ); - - } - - //select message encoder - IEncoder binding = null; - if (endpoint.getBinding().equals( - SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { - binding = springContext.getBean("PVPRedirectBinding", RedirectBinding.class); - - } else if (endpoint.getBinding().equals( - SAMLConstants.SAML2_POST_BINDING_URI)) { - binding = springContext.getBean("PVPPOSTBinding", PostBinding.class); - - } - - //encode message - binding.encodeRequest(null, httpResp, authReq, - endpoint.getLocation(), pendingReq.getPendingRequestId(), config.getAuthnRequestSigningCredential(), pendingReq); - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java new file mode 100644 index 00000000..36f43cc8 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java @@ -0,0 +1,263 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.modules.pvp2.sp.impl; + +import java.security.NoSuchAlgorithmException; +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestExtensionBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.sp.api.IPvpAuthnRequestBuilderConfiguruation; +import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AuthnRequestBuildException; +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.opensaml.common.impl.SecureRandomIdentifierGenerator; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.common.Extensions; +import org.opensaml.saml2.core.AuthnContextClassRef; +import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml2.core.AuthnRequest; +import org.opensaml.saml2.core.Issuer; +import org.opensaml.saml2.core.NameID; +import org.opensaml.saml2.core.NameIDPolicy; +import org.opensaml.saml2.core.NameIDType; +import org.opensaml.saml2.core.RequestedAuthnContext; +import org.opensaml.saml2.core.RequesterID; +import org.opensaml.saml2.core.Scoping; +import org.opensaml.saml2.core.Subject; +import org.opensaml.saml2.core.SubjectConfirmation; +import org.opensaml.saml2.core.SubjectConfirmationData; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.SingleSignOnService; +import org.opensaml.ws.message.encoder.MessageEncodingException; +import org.opensaml.xml.security.SecurityException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; + +/** + * PVP2 S-Profil Authentication-Request builder-implementation. + * + * @author tlenz + * + */ +@Service("pvpAuthnRequestBuilder") +public class PvpAuthnRequestBuilder { + private static final Logger log = LoggerFactory.getLogger(PvpAuthnRequestBuilder.class); + + + @Autowired(required = true) + ApplicationContext springContext; + + + /** + * Build a PVP2.x specific authentication request + * + * @param pendingReq Currently processed pendingRequest + * @param config AuthnRequest builder configuration, never null + * @param httpResp http response object + * @throws NoSuchAlgorithmException In case of error + * @throws SecurityException In case of error + * @throws Pvp2Exception In case of error + * @throws MessageEncodingException In case of error + */ + public void buildAuthnRequest(final IRequest pendingReq, + final IPvpAuthnRequestBuilderConfiguruation config, final HttpServletResponse httpResp) + throws NoSuchAlgorithmException, MessageEncodingException, Pvp2Exception, SecurityException { + // get IDP Entity element from config + final EntityDescriptor idpEntity = config.getIdpEntityDescriptor(); + + final AuthnRequest authReq = Saml2Utils.createSamlObject(AuthnRequest.class); + + // select SingleSignOn Service endpoint from IDP metadata + SingleSignOnService endpoint = null; + for (final SingleSignOnService sss : idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS) + .getSingleSignOnServices()) { + + // use POST binding as default if it exists + if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { + endpoint = sss; + + } else if (sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) + && endpoint == null) { + endpoint = sss; + } + + } + + if (endpoint == null) { + log.warn("Building AuthnRequest FAILED: > Requested IDP " + idpEntity.getEntityID() + + " does not support POST or Redirect Binding."); + throw new AuthnRequestBuildException("sp.pvp2.00", + new Object[] {config.getSpNameForLogging(), idpEntity.getEntityID()}); + + } else { + authReq.setDestination(endpoint.getLocation()); + } + + + // set basic AuthnRequest information + final String reqID = config.getRequestID(); + if (StringUtils.isNotEmpty(reqID)) { + authReq.setID(reqID); + } else { + final SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); + authReq.setID(gen.generateIdentifier()); + + } + + authReq.setIssueInstant(new DateTime()); + + // set isPassive flag + if (config.isPassivRequest() == null) { + authReq.setIsPassive(false); + } else { + authReq.setIsPassive(config.isPassivRequest()); + } + + // set EntityID of the service provider + final Issuer issuer = Saml2Utils.createSamlObject(Issuer.class); + issuer.setFormat(NameIDType.ENTITY); + issuer.setValue(config.getSpEntityID()); + authReq.setIssuer(issuer); + + // set AssertionConsumerService ID + if (config.getAssertionConsumerServiceId() != null) { + authReq.setAssertionConsumerServiceIndex(config.getAssertionConsumerServiceId()); + } + + // set NameIDPolicy + if (config.getNameIdPolicyFormat() != null) { + final NameIDPolicy policy = Saml2Utils.createSamlObject(NameIDPolicy.class); + policy.setAllowCreate(config.getNameIdPolicyAllowCreation()); + policy.setFormat(config.getNameIdPolicyFormat()); + authReq.setNameIDPolicy(policy); + } + + // set requested QAA level + if (config.getAuthnContextClassRef() != null) { + final RequestedAuthnContext reqAuthContext = + Saml2Utils.createSamlObject(RequestedAuthnContext.class); + final AuthnContextClassRef authnClassRef = + Saml2Utils.createSamlObject(AuthnContextClassRef.class); + + authnClassRef.setAuthnContextClassRef(config.getAuthnContextClassRef()); + + if (config.getAuthnContextComparison() == null) { + reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); + } else { + reqAuthContext.setComparison(config.getAuthnContextComparison()); + } + + reqAuthContext.getAuthnContextClassRefs().add(authnClassRef); + authReq.setRequestedAuthnContext(reqAuthContext); + } + + // set request Subject element + if (StringUtils.isNotEmpty(config.getSubjectNameID())) { + final Subject reqSubject = Saml2Utils.createSamlObject(Subject.class); + final NameID subjectNameID = Saml2Utils.createSamlObject(NameID.class); + + subjectNameID.setValue(config.getSubjectNameID()); + if (StringUtils.isNotEmpty(config.getSubjectNameIdQualifier())) { + subjectNameID.setNameQualifier(config.getSubjectNameIdQualifier()); + } + + if (StringUtils.isNotEmpty(config.getSubjectNameIdFormat())) { + subjectNameID.setFormat(config.getSubjectNameIdFormat()); + } else { + subjectNameID.setFormat(NameIDType.TRANSIENT); + } + + reqSubject.setNameID(subjectNameID); + + if (config.getSubjectConformationDate() != null) { + final SubjectConfirmation subjectConformation = + Saml2Utils.createSamlObject(SubjectConfirmation.class); + final SubjectConfirmationData subjectConformDate = + Saml2Utils.createSamlObject(SubjectConfirmationData.class); + subjectConformation.setSubjectConfirmationData(subjectConformDate); + reqSubject.getSubjectConfirmations().add(subjectConformation); + + if (config.getSubjectConformationMethode() != null) { + subjectConformation.setMethod(config.getSubjectConformationMethode()); + } + + subjectConformDate.setDOM(config.getSubjectConformationDate()); + + } + + authReq.setSubject(reqSubject); + + } + + + // set ProviderName + if (StringUtils.isNotEmpty(config.getProviderName())) { + authReq.setProviderName(config.getProviderName()); + } + + // set RequesterId in case of proxy mode + if (StringUtils.isNotEmpty(config.getScopeRequesterId())) { + final Scoping scope = Saml2Utils.createSamlObject(Scoping.class); + final RequesterID requesterId = Saml2Utils.createSamlObject(RequesterID.class); + requesterId.setRequesterID(config.getScopeRequesterId()); + scope.getRequesterIDs().add(requesterId); + authReq.setScoping(scope); + + } + + // add optional requested attributes + if (config.getRequestedAttributes() != null) { + final List reqAttr = config.getRequestedAttributes(); + final Extensions extenstions = new EaafRequestExtensionBuilder().buildObject(); + final EaafRequestedAttributes reqAttributs = + Saml2Utils.createSamlObject(EaafRequestedAttributes.class); + reqAttributs.getAttributes().addAll(reqAttr); + extenstions.getUnknownXMLObjects().add(reqAttributs); + authReq.setExtensions(extenstions); + + } + + // select message encoder + IEncoder binding = null; + if (endpoint.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { + binding = springContext.getBean("PVPRedirectBinding", RedirectBinding.class); + + } else if (endpoint.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { + binding = springContext.getBean("PVPPOSTBinding", PostBinding.class); + + } + + // encode message + binding.encodeRequest(null, httpResp, authReq, endpoint.getLocation(), + pendingReq.getPendingRequestId(), config.getAuthnRequestSigningCredential(), pendingReq); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java index 22f1cb06..e0cad257 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + package at.gv.egiz.eaaf.modules.pvp2.sp.impl.utils; import java.util.ArrayList; @@ -34,7 +27,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; - +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AssertionAttributeExtractorExeption; import org.apache.commons.lang3.StringUtils; import org.opensaml.saml2.core.Assertion; import org.opensaml.saml2.core.Attribute; @@ -48,295 +42,316 @@ 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); - internalInitialize(); - - } else - throw new AssertionAttributeExtractorExeption(); - } - - /** - * Parse the SAML2 Assertion element and extracts included information - *

- * - * @param assertion SAML2 Assertion - * @throws AssertionAttributeExtractorExeption - */ - public AssertionAttributeExtractor(Assertion assertion) throws AssertionAttributeExtractorExeption { - this.assertion = assertion; - internalInitialize(); - - } - - /** - * 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"); - } - - /** - * Get the Id attribute from SAML2 assertion - * - * @return - */ - public String getAssertionID() { - return assertion.getID(); - - } - - 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(); - - } - - /** - * Get the Assertion validFrom period - * - * This method returns value of SAML 'Conditions' element. - * - * @return Date, after this SAML2 assertion is valid, otherwise null - */ - public Date getAssertionNotBefore() { - try { - return getFullAssertion().getConditions().getNotBefore().toDate(); - - } catch (NullPointerException e) { - return null; - - } - - } - - 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); - } - - private void internalInitialize() { - 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); - - } - } - } - } + + private static final Logger log = LoggerFactory.getLogger(AssertionAttributeExtractor.class); + + private Assertion assertion = null; + private final 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 In case of an error + */ + public AssertionAttributeExtractor(final StatusResponseType samlResponse) + throws AssertionAttributeExtractorExeption { + if (samlResponse != null && samlResponse instanceof Response) { + final 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); + internalInitialize(); + + } else { + throw new AssertionAttributeExtractorExeption(); + } + } + + /** + * Parse the SAML2 Assertion element and extracts included information.
+ *
+ * + * @param assertion SAML2 Assertion + * @throws AssertionAttributeExtractorExeption In case of an error + */ + public AssertionAttributeExtractor(final Assertion assertion) + throws AssertionAttributeExtractorExeption { + this.assertion = assertion; + internalInitialize(); + + } + + /** + * 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(final 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 attributeNameList List of attributes which are required + * + * @return + */ + public boolean containsAllRequiredAttributes(final Collection attributeNameList) { + + // first check if a bPK or an encrypted bPK is available + boolean flag = true; + for (final 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(final String attributeName) { + return attributs.containsKey(attributeName); + + } + + /** + * Get single attribute with name. + * + * @param attributeName attribute Name + * @return Attribute value + */ + public String getSingleAttributeValue(final String attributeName) { + if (attributs.containsKey(attributeName) && attributs.get(attributeName).size() > 0) { + return attributs.get(attributeName).get(0); + } else { + return null; + } + + } + + public List getAttributeValues(final String attributeName) { + return attributs.get(attributeName); + + } + + /** + * Return all include PVP attribute names. + * + * @return + */ + public Set getAllIncludeAttributeNames() { + return attributs.keySet(); + + } + + /** + * Get User's nameId. + * + * @return nameId + * @throws AssertionAttributeExtractorExeption In case of an error + */ + public String getNameID() throws AssertionAttributeExtractorExeption { + if (assertion.getSubject() != null) { + final 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"); + } + + /** + * Get the Id attribute from SAML2 assertion. + * + * @return + */ + public String getAssertionID() { + return assertion.getID(); + + } + + /** + * Get SessionIndex from assertion. + * + * @return sessionIndex + * @throws AssertionAttributeExtractorExeption In case of an error + */ + public String getSessionIndex() throws AssertionAttributeExtractorExeption { + final AuthnStatement authn = getAuthnStatement(); + + if (StringUtils.isNotEmpty(authn.getSessionIndex())) { + return authn.getSessionIndex(); + } else { + throw new AssertionAttributeExtractorExeption("SessionIndex"); + } + } + + /** + * Get LoA from Assertion. + * + * @return LoA + * @throws AssertionAttributeExtractorExeption In case of an error + */ + public String getQaaLevel() throws AssertionAttributeExtractorExeption { + final AuthnStatement authn = getAuthnStatement(); + if (authn.getAuthnContext() != null + && authn.getAuthnContext().getAuthnContextClassRef() != null) { + final 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 (final AuthnStatement el : getFullAssertion().getAuthnStatements()) { + if (el.getSessionNotOnOrAfter() != null) { + return (el.getSessionNotOnOrAfter().toDate()); + } + } + + } + + return getFullAssertion().getConditions().getNotOnOrAfter().toDate(); + + } + + /** + * Get the Assertion validFrom period. + * + *

+ * This method returns value of SAML 'Conditions' element. + *

+ * + * @return Date, after this SAML2 assertion is valid, otherwise null + */ + public Date getAssertionNotBefore() { + try { + return getFullAssertion().getConditions().getNotBefore().toDate(); + + } catch (final NullPointerException e) { + return null; + + } + + } + + private AuthnStatement getAuthnStatement() throws AssertionAttributeExtractorExeption { + final 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); + } + + private void internalInitialize() { + if (assertion.getAttributeStatements() != null + && assertion.getAttributeStatements().size() > 0) { + final AttributeStatement attrStat = assertion.getAttributeStatements().get(0); + for (final Attribute attr : attrStat.getAttributes()) { + if (attr.getName().startsWith(PvpConstants.STORK_ATTRIBUTE_PREFIX)) { + final List storkAttrValues = new ArrayList<>(); + for (final XMLObject el : attr.getAttributeValues()) { + storkAttrValues.add(el.getDOM().getTextContent()); + } + + // PersonalAttribute storkAttr = new PersonalAttribute(attr.getName(), + // false, storkAttrValues , "Available"); + // storkAttributes.put(attr.getName(), storkAttr ); + + } else { + final List attrList = new ArrayList<>(); + for (final XMLObject el : attr.getAttributeValues()) { + attrList.add(el.getDOM().getTextContent()); + } + + attributs.put(attr.getName(), attrList); + + } + } + } + } } -- cgit v1.2.3