diff options
Diffstat (limited to 'id/server/modules/moa-id-module-AT_eIDAS_connector/src')
14 files changed, 2078 insertions, 0 deletions
diff --git a/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/EidasCentralAuthConstants.java b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/EidasCentralAuthConstants.java new file mode 100644 index 000000000..19950a078 --- /dev/null +++ b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/EidasCentralAuthConstants.java @@ -0,0 +1,94 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.eIDAScentralAuth; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.impl.data.Trible; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; + +/** + * @author tlenz + * + */ +public class EidasCentralAuthConstants { + + public static final String MODULE_NAME_FOR_LOGGING = "eIDAS central authentication"; + + public static final int METADATA_VALIDUNTIL_IN_HOURS = 24; + + public static final String HTTP_PARAM_CENTRAL_EIDAS_AUTH_SELECTION = "useeIDAS"; + + public static final String ENDPOINT_POST = "/sp/eidas/post"; + public static final String ENDPOINT_REDIRECT = "/sp/eidas/redirect"; + public static final String ENDPOINT_METADATA = "/sp/eidas/metadata"; + + public static final String CONFIG_PROPS_PREFIX = "modules.eidascentralauth."; + public static final String CONFIG_PROPS_KEYSTORE = CONFIG_PROPS_PREFIX + "keystore.path"; + public static final String CONFIG_PROPS_KEYSTOREPASSWORD = CONFIG_PROPS_PREFIX + "keystore.password"; + public static final String CONFIG_PROPS_SIGN_METADATA_KEY_PASSWORD = CONFIG_PROPS_PREFIX + "metadata.sign.password"; + public static final String CONFIG_PROPS_SIGN_METADATA_ALIAS_PASSWORD = CONFIG_PROPS_PREFIX + "metadata.sign.alias"; + public static final String CONFIG_PROPS_SIGN_SIGNING_KEY_PASSWORD = CONFIG_PROPS_PREFIX + "request.sign.password"; + public static final String CONFIG_PROPS_SIGN_SIGNING_ALIAS_PASSWORD = CONFIG_PROPS_PREFIX + "request.sign.alias"; + public static final String CONFIG_PROPS_ENCRYPTION_KEY_PASSWORD = CONFIG_PROPS_PREFIX + "response.encryption.password"; + public static final String CONFIG_PROPS_ENCRYPTION_ALIAS_PASSWORD = CONFIG_PROPS_PREFIX + "response.encryption.alias"; + public static final String CONFIG_PROPS_REQUIRED_PVP_ATTRIBUTES_LIST = CONFIG_PROPS_PREFIX + "required.additional.attributes"; + public static final String CONFIG_PROPS_NODE_ENTITYID = CONFIG_PROPS_PREFIX + "node.entityId"; + public static final String CONFIG_PROPS_NODE_METADATAURL = CONFIG_PROPS_PREFIX + "node.metadataUrl"; + public static final String CONFIG_PROPS_NODE_TRUSTPROFILEID = CONFIG_PROPS_PREFIX + "node.trustprofileID"; + + + public static final String CONFIG_DEFAULT_LOA_EIDAS_LEVEL = EAAFConstants.EIDAS_LOA_HIGH; + public static final List<Trible<String, String, Boolean>> DEFAULT_REQUIRED_PVP_ATTRIBUTES = + Collections.unmodifiableList(new ArrayList<Trible<String, String, Boolean>>() { + private static final long serialVersionUID = 1L; + { + //add PVP Version attribute + add(Trible.newInstance(PVPConstants.PVP_VERSION_NAME, PVPConstants.PVP_VERSION_FRIENDLY_NAME, true)); + + //request entity information + add(Trible.newInstance(PVPConstants.GIVEN_NAME_NAME, PVPConstants.GIVEN_NAME_FRIENDLY_NAME, true)); + add(Trible.newInstance(PVPConstants.PRINCIPAL_NAME_NAME, PVPConstants.PRINCIPAL_NAME_FRIENDLY_NAME, true)); + add(Trible.newInstance(PVPConstants.BIRTHDATE_NAME, PVPConstants.BIRTHDATE_FRIENDLY_NAME, true)); + add(Trible.newInstance(PVPConstants.BPK_NAME, PVPConstants.BPK_FRIENDLY_NAME, true)); + add(Trible.newInstance(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME, PVPConstants.EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME, true)); + add(Trible.newInstance(PVPConstants.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, PVPConstants.EID_CITIZEN_EIDAS_QAA_LEVEL_FRIENDLY_NAME, true)); + add(Trible.newInstance(PVPConstants.EID_ISSUING_NATION_NAME, PVPConstants.EID_ISSUING_NATION_FRIENDLY_NAME, true)); + add(Trible.newInstance(PVPConstants.EID_IDENTITY_LINK_NAME, PVPConstants.EID_IDENTITY_LINK_FRIENDLY_NAME, false)); + } + }); + + public static final List<String> DEFAULT_REQUIRED_PVP_ATTRIBUTE_NAMES = + Collections.unmodifiableList(new ArrayList<String>() { + private static final long serialVersionUID = 1L; + { + for (Trible<String, String, Boolean> el : DEFAULT_REQUIRED_PVP_ATTRIBUTES) + add(el.getFirst()); + } + }); +} + + diff --git a/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/EidasCentralAuthModuleImpl.java b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/EidasCentralAuthModuleImpl.java new file mode 100644 index 000000000..821a200c7 --- /dev/null +++ b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/EidasCentralAuthModuleImpl.java @@ -0,0 +1,103 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.eIDAScentralAuth; + +import java.io.Serializable; + +import javax.annotation.PostConstruct; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; + +import at.gv.egiz.eaaf.core.api.idp.auth.modules.AuthModule; +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egovernment.moa.id.moduls.AuthenticationManager; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +public class EidasCentralAuthModuleImpl implements AuthModule { + + @Autowired(required=true) private AuthenticationManager authManager; + + private int priority = 0; + + @PostConstruct + protected void initalCentralEidasAuthentication() { + //parameter to whiteList + authManager.addParameterNameToWhiteList(EidasCentralAuthConstants.HTTP_PARAM_CENTRAL_EIDAS_AUTH_SELECTION); + + } + + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getPriority() + */ + @Override + public int getPriority() { + return priority; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#selectProcess(at.gv.egovernment.moa.id.process.api.ExecutionContext) + */ + @Override + public String selectProcess(ExecutionContext context) { + Serializable paramObj = context.get(EidasCentralAuthConstants.HTTP_PARAM_CENTRAL_EIDAS_AUTH_SELECTION); + if (paramObj != null ) { + if (paramObj instanceof String) { + String param = (String)paramObj; + if (StringUtils.isNotEmpty(param) && Boolean.parseBoolean(param)) { + Logger.debug("Centrial eIDAS authentication process selected "); + return "centrialEidasAuthentication"; + + } else + Logger.trace(EidasCentralAuthConstants.HTTP_PARAM_CENTRAL_EIDAS_AUTH_SELECTION + + " is empty or has value: " + Boolean.parseBoolean(param)); + + } else + Logger.info("Find suspect http param '" + EidasCentralAuthConstants.HTTP_PARAM_CENTRAL_EIDAS_AUTH_SELECTION + + "' of type: " + paramObj.getClass().getName()); + } + return null; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions() + */ + @Override + public String[] getProcessDefinitions() { + return new String[] { "classpath:eIDAS_central_node_auth.process.xml" }; + } + + /** + * @param priority the priority to set + */ + public void setPriority(int priority) { + this.priority = priority; + + } +} diff --git a/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/EidasCentralAuthSpringResourceProvider.java b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/EidasCentralAuthSpringResourceProvider.java new file mode 100644 index 000000000..beaaee619 --- /dev/null +++ b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/EidasCentralAuthSpringResourceProvider.java @@ -0,0 +1,63 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.eIDAScentralAuth; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import at.gv.egiz.components.spring.api.SpringResourceProvider; + +/** + * @author tlenz + * + */ +public class EidasCentralAuthSpringResourceProvider implements SpringResourceProvider { + + /* (non-Javadoc) + * @see at.gv.egiz.components.spring.api.SpringResourceProvider#getResourcesToLoad() + */ + @Override + public Resource[] getResourcesToLoad() { + ClassPathResource federationAuthConfig = new ClassPathResource("/moaid_eIDAS_central_node_auth.beans.xml", EidasCentralAuthSpringResourceProvider.class); + + return new Resource[] {federationAuthConfig}; + } + + /* (non-Javadoc) + * @see at.gv.egiz.components.spring.api.SpringResourceProvider#getPackagesToScan() + */ + @Override + public String[] getPackagesToScan() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see at.gv.egiz.components.spring.api.SpringResourceProvider#getName() + */ + @Override + public String getName() { + return "MOA-ID Auth-module 'central eIDAS Authentication'"; + } + +} diff --git a/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/config/EidasCentralAuthMetadataConfiguration.java b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/config/EidasCentralAuthMetadataConfiguration.java new file mode 100644 index 000000000..aad1244f1 --- /dev/null +++ b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/config/EidasCentralAuthMetadataConfiguration.java @@ -0,0 +1,355 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.eIDAScentralAuth.config; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.opensaml.saml2.core.Attribute; +import org.opensaml.saml2.core.NameIDType; +import org.opensaml.saml2.metadata.ContactPerson; +import org.opensaml.saml2.metadata.Organization; +import org.opensaml.saml2.metadata.RequestedAttribute; +import org.opensaml.xml.security.credential.Credential; + +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.impl.data.Trible; +import at.gv.egiz.eaaf.modules.pvp2.api.IPVP2BasicConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPAttributeBuilder; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.EidasCentralAuthConstants; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.utils.EidasCentralAuthCredentialProvider; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +public class EidasCentralAuthMetadataConfiguration implements IPVPMetadataBuilderConfiguration { + + private Collection<RequestedAttribute> additionalAttributes = null; + + + private String authURL; + private EidasCentralAuthCredentialProvider credentialProvider; + private IPVP2BasicConfiguration pvpConfiguration; + + public EidasCentralAuthMetadataConfiguration(String authURL, + EidasCentralAuthCredentialProvider credentialProvider, + IPVP2BasicConfiguration pvpConfiguration) { + this.authURL = authURL; + this.credentialProvider = credentialProvider; + this.pvpConfiguration = pvpConfiguration; + } + + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getMetadataValidUntil() + */ + @Override + public int getMetadataValidUntil() { + return EidasCentralAuthConstants.METADATA_VALIDUNTIL_IN_HOURS; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#buildEntitiesDescriptorAsRootElement() + */ + @Override + public boolean buildEntitiesDescriptorAsRootElement() { + return false; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#buildIDPSSODescriptor() + */ + @Override + public boolean buildIDPSSODescriptor() { + return false; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#buildSPSSODescriptor() + */ + @Override + public boolean buildSPSSODescriptor() { + return true; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getEntityIDPostfix() + */ + @Override + public String getEntityID() { + return authURL + EidasCentralAuthConstants.ENDPOINT_METADATA; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getEntityFriendlyName() + */ + @Override + public String getEntityFriendlyName() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getContactPersonInformation() + */ + @Override + public List<ContactPerson> getContactPersonInformation() { + try { + return pvpConfiguration.getIDPContacts(); + + } catch (EAAFException e) { + Logger.warn("Can not load Metadata entry: Contect Person", e); + return null; + + } + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getOrgansiationInformation() + */ + @Override + public Organization getOrgansiationInformation() { + try { + return pvpConfiguration.getIDPOrganisation(); + + } catch (EAAFException e) { + Logger.warn("Can not load Metadata entry: Organisation", e); + return null; + + } + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getMetadataSigningCredentials() + */ + @Override + public Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException { + return credentialProvider.getIDPMetaDataSigningCredential(); + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getRequestorResponseSigningCredentials() + */ + @Override + public Credential getRequestorResponseSigningCredentials() throws CredentialsNotAvailableException { + return credentialProvider.getIDPAssertionSigningCredential(); + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getEncryptionCredentials() + */ + @Override + public Credential getEncryptionCredentials() throws CredentialsNotAvailableException { + return credentialProvider.getIDPAssertionEncryptionCredential(); + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getIDPWebSSOPostBindingURL() + */ + @Override + public String getIDPWebSSOPostBindingURL() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getIDPWebSSORedirectBindingURL() + */ + @Override + public String getIDPWebSSORedirectBindingURL() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getIDPSLOPostBindingURL() + */ + @Override + public String getIDPSLOPostBindingURL() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getIDPSLORedirectBindingURL() + */ + @Override + public String getIDPSLORedirectBindingURL() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getSPAssertionConsumerServicePostBindingURL() + */ + @Override + public String getSPAssertionConsumerServicePostBindingURL() { + return authURL + EidasCentralAuthConstants.ENDPOINT_POST; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getSPAssertionConsumerServiceRedirectBindingURL() + */ + @Override + public String getSPAssertionConsumerServiceRedirectBindingURL() { + return authURL + EidasCentralAuthConstants.ENDPOINT_REDIRECT; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getSPSLOPostBindingURL() + */ + @Override + public String getSPSLOPostBindingURL() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getSPSLORedirectBindingURL() + */ + @Override + public String getSPSLORedirectBindingURL() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getSPSLOSOAPBindingURL() + */ + @Override + public String getSPSLOSOAPBindingURL() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getIDPPossibleAttributes() + */ + @Override + public List<Attribute> getIDPPossibleAttributes() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getIDPPossibleNameITTypes() + */ + @Override + public List<String> getIDPPossibleNameITTypes() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getSPRequiredAttributes() + */ + @Override + public Collection<RequestedAttribute> getSPRequiredAttributes() { + Map<String, RequestedAttribute> requestedAttributes = new HashMap<String, RequestedAttribute>(); + for (Trible<String, String, Boolean> el : EidasCentralAuthConstants.DEFAULT_REQUIRED_PVP_ATTRIBUTES) + requestedAttributes.put(el.getFirst(), PVPAttributeBuilder.buildReqAttribute(el.getFirst(), el.getSecond(), el.getThird())); + + if (additionalAttributes != null) { + Logger.trace("Add additional PVP attributes into metadata ... "); + for (RequestedAttribute el : additionalAttributes) { + if (requestedAttributes.containsKey(el.getName())) + Logger.debug("Attribute " + el.getName() + " is already added by default configuration. Overwrite it by user configuration"); + + requestedAttributes.put(el.getName(), el); + + } + } + + return requestedAttributes.values(); + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getSPAllowedNameITTypes() + */ + @Override + public List<String> getSPAllowedNameITTypes() { + return Arrays.asList(NameIDType.PERSISTENT); + + } + + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPMetadataBuilderConfiguration#getSPNameForLogging() + */ + @Override + public String getSPNameForLogging() { + return EidasCentralAuthConstants.MODULE_NAME_FOR_LOGGING; + } + + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPMetadataBuilderConfiguration#wantAssertionSigned() + */ + @Override + public boolean wantAssertionSigned() { + return false; + } + + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPMetadataBuilderConfiguration#wantAuthnRequestSigned() + */ + @Override + public boolean wantAuthnRequestSigned() { + return true; + } + + /** + * Add additonal PVP attributes that are required by this deployment + * + * @param additionalAttr List of PVP attribute name and isRequired flag + */ + public void setAdditionalRequiredAttributes(List<Pair<String, Boolean>> additionalAttr) { + if (additionalAttr != null) { + additionalAttributes = new ArrayList<RequestedAttribute>(); + for (Pair<String, Boolean> el : additionalAttr) { + Attribute attributBuilder = PVPAttributeBuilder.buildEmptyAttribute(el.getFirst()); + if (attributBuilder != null) { + additionalAttributes.add( + PVPAttributeBuilder.buildReqAttribute( + attributBuilder.getName(), + attributBuilder.getFriendlyName(), + el.getSecond())); + + } else + Logger.info("NO PVP attribute with name: " + el.getFirst()); + + } + } + } + +} diff --git a/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/config/EidasCentralAuthRequestBuilderConfiguration.java b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/config/EidasCentralAuthRequestBuilderConfiguration.java new file mode 100644 index 000000000..8376f3aad --- /dev/null +++ b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/config/EidasCentralAuthRequestBuilderConfiguration.java @@ -0,0 +1,272 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.eIDAScentralAuth.config; + +import java.util.List; + +import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml2.core.NameID; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.xml.security.credential.Credential; +import org.w3c.dom.Element; + +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.sp.api.IPVPAuthnRequestBuilderConfiguruation; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.EidasCentralAuthConstants; + +/** + * @author tlenz + * + */ +public class EidasCentralAuthRequestBuilderConfiguration implements IPVPAuthnRequestBuilderConfiguruation { + + private boolean isPassive; + private String SPEntityID; + private String QAA_Level; + private EntityDescriptor idpEntity; + private Credential signCred; + private String scopeRequesterId; + private String providerName; + private List<EAAFRequestedAttribute> requestedAttributes; + private String reqId; + + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#isPassivRequest() + */ + @Override + public Boolean isPassivRequest() { + return this.isPassive; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getAssertionConsumerServiceId() + */ + @Override + public Integer getAssertionConsumerServiceId() { + return 0; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getEntityID() + */ + @Override + public String getSPEntityID() { + return this.SPEntityID; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getNameIDPolicy() + */ + @Override + public String getNameIDPolicyFormat() { + return NameID.PERSISTENT; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getNameIDPolicy() + */ + @Override + public boolean getNameIDPolicyAllowCreation() { + return true; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getAuthnContextClassRef() + */ + @Override + public String getAuthnContextClassRef() { + return this.QAA_Level; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getAuthnContextComparison() + */ + @Override + public AuthnContextComparisonTypeEnumeration getAuthnContextComparison() { + return AuthnContextComparisonTypeEnumeration.MINIMUM; + } + + /** + * @param isPassive the isPassive to set + */ + public void setPassive(boolean isPassive) { + this.isPassive = isPassive; + } + + /** + * @param sPEntityID the sPEntityID to set + */ + public void setSPEntityID(String sPEntityID) { + SPEntityID = sPEntityID; + } + + /** + * @param qAA_Level the qAA_Level to set + */ + public void setQAA_Level(String qAA_Level) { + QAA_Level = qAA_Level; + } + + /** + * @param idpEntity the idpEntity to set + */ + public void setIdpEntity(EntityDescriptor idpEntity) { + this.idpEntity = idpEntity; + } + + /** + * @param signCred the signCred to set + */ + public void setSignCred(Credential signCred) { + this.signCred = signCred; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getAuthnRequestSigningCredential() + */ + @Override + public Credential getAuthnRequestSigningCredential() { + return this.signCred; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getIDPEntityDescriptor() + */ + @Override + public EntityDescriptor getIDPEntityDescriptor() { + return this.idpEntity; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getSubjectNameID() + */ + @Override + public String getSubjectNameID() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getSPNameForLogging() + */ + @Override + public String getSPNameForLogging() { + return EidasCentralAuthConstants.MODULE_NAME_FOR_LOGGING; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getSubjectNameIDFormat() + */ + @Override + public String getSubjectNameIDFormat() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getRequestID() + */ + @Override + public String getRequestID() { + return this.reqId; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getSubjectNameIDQualifier() + */ + @Override + public String getSubjectNameIDQualifier() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getSubjectConformationMethode() + */ + @Override + public String getSubjectConformationMethode() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getSubjectConformationDate() + */ + @Override + public Element getSubjectConformationDate() { + return null; + } + + @Override + public List<EAAFRequestedAttribute> getRequestedAttributes() { + return this.requestedAttributes; + + } + + @Override + public String getProviderName() { + return this.providerName; + } + + @Override + public String getScopeRequesterId() { + return this.scopeRequesterId; + } + + /** + * Set the entityId of the SP that requests the proxy for eIDAS authentication + * + * @param scopeRequesterId + */ + public void setScopeRequesterId(String scopeRequesterId) { + this.scopeRequesterId = scopeRequesterId; + } + + /** + * Set a friendlyName for the SP that requests the proxy for eIDAS authentication + * + * @param providerName + */ + public void setProviderName(String providerName) { + this.providerName = providerName; + } + + /** + * Set a Set of PVP attributes that a requested by using requested attributes + * + * @param requestedAttributes + */ + public void setRequestedAttributes(List<EAAFRequestedAttribute> requestedAttributes) { + this.requestedAttributes = requestedAttributes; + } + + /** + * Set a RequestId for this Authn. Request + * + * @param reqId + */ + public void setRequestId(String reqId) { + this.reqId = reqId; + } + + + + +} diff --git a/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/controller/EidasCentralAuthMetadataController.java b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/controller/EidasCentralAuthMetadataController.java new file mode 100644 index 000000000..4898c8f1e --- /dev/null +++ b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/controller/EidasCentralAuthMetadataController.java @@ -0,0 +1,133 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.eIDAScentralAuth.controller; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import com.google.common.net.MediaType; + +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractController; +import at.gv.egiz.eaaf.core.impl.utils.HTTPUtils; +import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; +import at.gv.egiz.eaaf.modules.pvp2.api.IPVP2BasicConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPMetadataBuilder; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.EidasCentralAuthConstants; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.config.EidasCentralAuthMetadataConfiguration; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.utils.EidasCentralAuthCredentialProvider; +import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * @author tlenz + * + */ +@Controller +public class EidasCentralAuthMetadataController extends AbstractController { + + @Autowired PVPMetadataBuilder metadatabuilder; + @Autowired AuthConfiguration authConfig; + @Autowired EidasCentralAuthCredentialProvider credentialProvider; + @Autowired IPVP2BasicConfiguration pvpConfiguration; + + public EidasCentralAuthMetadataController() { + super(); + Logger.debug("Registering servlet " + getClass().getName() + + " with mappings '" + EidasCentralAuthConstants.ENDPOINT_METADATA + + "'."); + + } + + @RequestMapping(value = EidasCentralAuthConstants.ENDPOINT_METADATA, + method = {RequestMethod.GET}) + public void getSPMetadata(HttpServletRequest req, HttpServletResponse resp) throws IOException { + //check PublicURL prefix + try { + String authURL = HTTPUtils.extractAuthURLFromRequest(req); + if (!authConfig.getPublicURLPrefix().contains(authURL)) { + resp.sendError(HttpServletResponse.SC_FORBIDDEN, "No valid request URL"); + return; + + } else { + //initialize metadata builder configuration + EidasCentralAuthMetadataConfiguration metadataConfig = + new EidasCentralAuthMetadataConfiguration(authURL, credentialProvider, pvpConfiguration); + metadataConfig.setAdditionalRequiredAttributes(getAdditonalRequiredAttributes()); + + + //build metadata + String xmlMetadata = metadatabuilder.buildPVPMetadata(metadataConfig); + + //write response + byte[] content = xmlMetadata.getBytes("UTF-8"); + resp.setStatus(HttpServletResponse.SC_OK); + resp.setContentLength(content.length); + resp.setContentType(MediaType.XML_UTF_8.toString()); + resp.getOutputStream().write(content); + + } + + } catch (Exception e) { + Logger.warn("Build federated-authentication PVP metadata FAILED.", e); + handleErrorNoRedirect(e, req, resp, false); + + } + + } + + private List<Pair<String, Boolean>> getAdditonalRequiredAttributes() { + Map<String, String> addReqAttributes = authConfig.getBasicMOAIDConfigurationWithPrefix(EidasCentralAuthConstants.CONFIG_PROPS_REQUIRED_PVP_ATTRIBUTES_LIST); + if (addReqAttributes != null) { + List<Pair<String, Boolean>> result = new ArrayList<Pair<String, Boolean>>(); + for (String el : addReqAttributes.values()) { + if (MiscUtil.isNotEmpty(el)) { + Logger.trace("Parse additional attr. definition: " + el); + List<String> attr = KeyValueUtils.getListOfCSVValues(el.trim()); + if (attr.size() == 2) { + result.add(Pair.newInstance(attr.get(0), Boolean.parseBoolean(attr.get(1)))); + + } else + Logger.info("IGNORE additional attr. definition: " + el + + " Reason: Format not valid"); + } + } + + return result; + } + + return null; + } + +} diff --git a/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/controller/EidasCentralAuthSignalController.java b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/controller/EidasCentralAuthSignalController.java new file mode 100644 index 000000000..1486ef841 --- /dev/null +++ b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/controller/EidasCentralAuthSignalController.java @@ -0,0 +1,67 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.eIDAScentralAuth.controller; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.text.StringEscapeUtils; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractProcessEngineSignalController; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.EidasCentralAuthConstants; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +@Controller +public class EidasCentralAuthSignalController extends AbstractProcessEngineSignalController { + + public EidasCentralAuthSignalController() { + super(); + Logger.debug("Registering servlet " + getClass().getName() + + " with mappings '" + EidasCentralAuthConstants.ENDPOINT_POST + + "' and '" + EidasCentralAuthConstants.ENDPOINT_REDIRECT + "'."); + + } + + @RequestMapping(value = { EidasCentralAuthConstants.ENDPOINT_POST, + EidasCentralAuthConstants.ENDPOINT_REDIRECT + }, + method = {RequestMethod.POST, RequestMethod.GET}) + public void performCitizenCardAuthentication(HttpServletRequest req, HttpServletResponse resp) throws IOException { + signalProcessManagement(req, resp); + + } + + public String getPendingRequestId(HttpServletRequest request) { + return StringEscapeUtils.escapeHtml4(request.getParameter("RelayState")); + + } +} diff --git a/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/tasks/CreateAuthnRequestTask.java b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/tasks/CreateAuthnRequestTask.java new file mode 100644 index 000000000..c3c3331e1 --- /dev/null +++ b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/tasks/CreateAuthnRequestTask.java @@ -0,0 +1,210 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.eIDAScentralAuth.tasks; + +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.opensaml.common.impl.SecureRandomIdentifierGenerator; +import org.opensaml.saml2.core.Attribute; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.provider.MetadataProviderException; +import org.opensaml.ws.message.encoder.MessageEncodingException; +import org.opensaml.xml.security.SecurityException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import at.gv.egiz.eaaf.core.api.data.PVPAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; +import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPAttributeBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; +import at.gv.egiz.eaaf.modules.pvp2.sp.impl.PVPAuthnRequestBuilder; +import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.EidasCentralAuthConstants; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.config.EidasCentralAuthRequestBuilderConfiguration; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.utils.EidasCentralAuthCredentialProvider; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.utils.EidasCentralAuthMetadataProvider; +import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; +import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; +import at.gv.egovernment.moa.id.commons.config.MOAIDConfigurationConstants; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * @author tlenz + * + */ +@Component("CreateEidasCentrialAuthnRequestTask") +public class CreateAuthnRequestTask extends AbstractAuthServletTask { + + @Autowired PVPAuthnRequestBuilder authnReqBuilder; + @Autowired EidasCentralAuthCredentialProvider credential; + @Autowired EidasCentralAuthMetadataProvider metadataService; + + //@Autowired(required=true) ILoALevelMapper loaMapper; + //@Autowired(required=true) MOAMetadataProvider metadataProvider; + + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + try{ + revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_EIDAS_AT_CONNECTOR_SELECTED); + + //check if eIDAS authentication is enabled for this SP + if (!Boolean.parseBoolean(pendingReq.getServiceProviderConfiguration().getConfigurationValue(MOAIDConfigurationConstants.SERVICE_AUTH_STORK_ENABLED, String.valueOf(false)))) { + Logger.info("eIDAS authentication is NOT enabled for OA: " + pendingReq.getServiceProviderConfiguration().getUniqueIdentifier()); + throw new MOAIDException("eIDAS authentication is NOT enabled for OA: " + pendingReq.getServiceProviderConfiguration().getUniqueIdentifier(), null); + + } + + // get entityID for central ms-specific eIDAS node + String msNodeEntityID = getCentraleIDASNodeEntityId(pendingReq.getServiceProviderConfiguration()); + + + if (MiscUtil.isEmpty(msNodeEntityID)) { + Logger.info("eIDAS authentication not possible -> NO EntityID for central eIDAS node FOUND!"); + throw new MOAIDException("NO EntityID for central eIDAS node FOUND", null); + + } + + //load metadata with metadataURL, as backup + String metadataURL = authConfig.getBasicConfiguration(EidasCentralAuthConstants.CONFIG_PROPS_NODE_METADATAURL); + if (MiscUtil.isNotEmpty(metadataURL)) { + Logger.warn("Use not recommended metadata-provider initialization!" + + " SAML2 'Well-Known-Location' is the preferred methode."); + Logger.info("Initialize 'ms-specific eIDAS node' metadata-provider with URL:" + metadataURL); + metadataService.addMetadataWithMetadataURL(metadataURL); + + } + + //load IDP SAML2 entitydescriptor + EntityDescriptor entityDesc = metadataService.getEntityDescriptor(msNodeEntityID); + if (entityDesc == null) { + Logger.error("Requested 'ms-specific eIDAS node' " + entityDesc + + " has no valid metadata or metadata is not found"); + throw new MOAIDException("Requested 'ms-specific eIDAS node' " + entityDesc + + " has no valid metadata or metadata is not found", null); + + } + + //setup AuthnRequestBuilder configuration + EidasCentralAuthRequestBuilderConfiguration authnReqConfig = new EidasCentralAuthRequestBuilderConfiguration(); + SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); + authnReqConfig.setRequestId(gen.generateIdentifier()); + authnReqConfig.setIdpEntity(entityDesc); + authnReqConfig.setPassive(false); + authnReqConfig.setSignCred(credential.getIDPAssertionSigningCredential()); + authnReqConfig.setSPEntityID(pendingReq.getAuthURL() + EidasCentralAuthConstants.ENDPOINT_METADATA); + authnReqConfig.setQAA_Level( + pendingReq.getServiceProviderConfiguration().getConfigurationValue( + MOAIDConfigurationConstants.SERVICE_AUTH_STORK_MINQAALEVEL, + EidasCentralAuthConstants.CONFIG_DEFAULT_LOA_EIDAS_LEVEL)); + + authnReqConfig.setScopeRequesterId(pendingReq.getServiceProviderConfiguration().getUniqueIdentifier()); + authnReqConfig.setProviderName(pendingReq.getServiceProviderConfiguration().getFriendlyName()); + authnReqConfig.setRequestedAttributes(buildRequestedAttributes()); + + //build and transmit AuthnRequest + authnReqBuilder.buildAuthnRequest(pendingReq, authnReqConfig , response); + + revisionsLogger.logEvent(pendingReq, + MOAIDEventConstants.AUTHPROCESS_EIDAS_AT_CONNECTOR_REQUESTED, + authnReqConfig.getRequestID()); + + } catch (MOAIDException e) { + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } catch (MetadataProviderException e) { + throw new TaskExecutionException(pendingReq, "Build PVP2.1 AuthnRequest to connect 'ms-specific eIDAS node' FAILED.", e); + + } catch (MessageEncodingException | NoSuchAlgorithmException | SecurityException e) { + Logger.error("Build PVP2.1 AuthnRequest for SSO inderfederation FAILED", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } catch (Exception e) { + Logger.error("Build PVP2.1 AuthnRequest for SSO inderfederation FAILED", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } + } + + private String getCentraleIDASNodeEntityId(ISPConfiguration spConfiguration) { + //load from service-provider configuration + String msNodeEntityID = spConfiguration.getConfigurationValue(MOAIDConfigurationConstants.SERVICE_EXTERNAL_CENTRAL_EIDASNODE_SERVICE_URL); + + if (StringUtils.isEmpty(msNodeEntityID)) { + Logger.debug("No SP-specific central eIDAS-node URL. Switch to general configuration ... "); + if (authConfig instanceof AuthConfiguration) { + AuthConfiguration moaAuthConfig = (AuthConfiguration)authConfig; + List<String> configuratedEntityIDs = KeyValueUtils.getListOfCSVValues( + moaAuthConfig.getConfigurationWithKey(MOAIDConfigurationConstants.GENERAL_AUTH_SERVICES_CENTRAL_EIDASNODE_URL)); + + if (configuratedEntityIDs.size() > 0) + msNodeEntityID = configuratedEntityIDs.get(0); + else + Logger.info("No central eIDAS-node URL in IDP configuration. Switch to backup configuration ... "); + + } else + Logger.info("Basic configuration is NOT of type '" + AuthConfiguration.class.getName() + + "' Switch to generic Type ... "); + + + if (StringUtils.isEmpty(msNodeEntityID)) + msNodeEntityID = authConfig.getBasicConfiguration(EidasCentralAuthConstants.CONFIG_PROPS_NODE_ENTITYID); + + } + + return msNodeEntityID; + } + + private List<EAAFRequestedAttribute> buildRequestedAttributes() { + List<EAAFRequestedAttribute> attributs = new ArrayList<EAAFRequestedAttribute>(); + + //build EID sector for identification attribute + Attribute attr = PVPAttributeBuilder.buildEmptyAttribute(PVPAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME); + EAAFRequestedAttribute reqAttr = SAML2Utils.generateReqAuthnAttributeSimple( + attr , + true, + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); + attributs.add(reqAttr ); + + //TODO: add mandate information if mandates are used!!!! + + return attributs; + } + +} diff --git a/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/tasks/ReceiveAuthnResponseTask.java b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/tasks/ReceiveAuthnResponseTask.java new file mode 100644 index 000000000..c034dc95e --- /dev/null +++ b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/tasks/ReceiveAuthnResponseTask.java @@ -0,0 +1,251 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.eIDAScentralAuth.tasks; + +import java.io.IOException; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.transform.TransformerException; + +import org.opensaml.saml2.core.Response; +import org.opensaml.saml2.core.StatusCode; +import org.opensaml.ws.message.decoder.MessageDecodingException; +import org.opensaml.xml.io.MarshallingException; +import org.opensaml.xml.security.SecurityException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException; +import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; +import at.gv.egiz.eaaf.modules.pvp2.api.binding.IDecoder; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +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.message.InboundMessage; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileResponse; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EAAFURICompare; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; +import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AssertionValidationExeption; +import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AuthnResponseValidationException; +import at.gv.egiz.eaaf.modules.pvp2.sp.impl.utils.AssertionAttributeExtractor; +import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; +import at.gv.egovernment.moa.id.auth.exception.BuildException; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.EidasCentralAuthConstants; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.utils.EidasCentralAuthCredentialProvider; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.utils.EidasCentralAuthMetadataProvider; +import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; +import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException; +import at.gv.egovernment.moa.id.protocols.pvp2x.verification.SAMLVerificationEngineSP; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * @author tlenz + * + */ +@Component("ReceiveFederatedAuthnResponseTask") +public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { + + @Autowired private SAMLVerificationEngineSP samlVerificationEngine; + @Autowired private EidasCentralAuthCredentialProvider credentialProvider; + @Autowired(required=true) EidasCentralAuthMetadataProvider metadataProvider; + + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + InboundMessage msg = null; + + try { + + IDecoder decoder = null; + EAAFURICompare comperator = null; + //select Response Binding + if (request.getMethod().equalsIgnoreCase("POST")) { + decoder = new PostBinding(); + comperator = new EAAFURICompare(pendingReq.getAuthURL() + EidasCentralAuthConstants.ENDPOINT_POST); + Logger.trace("Receive PVP Response from 'ms-specific eIDAS node', by using POST-Binding."); + + } else if (request.getMethod().equalsIgnoreCase("GET")) { + decoder = new RedirectBinding(); + comperator = new EAAFURICompare(pendingReq.getAuthURL() + EidasCentralAuthConstants.ENDPOINT_REDIRECT); + Logger.trace("Receive PVP Response from 'ms-specific eIDAS node', by using Redirect-Binding."); + + } else { + Logger.warn("Receive PVP Response, but Binding (" + + request.getMethod() + ") is not supported."); + throw new AuthnResponseValidationException("sp.pvp2.03", new Object[] {EidasCentralAuthConstants.MODULE_NAME_FOR_LOGGING}); + + } + + //decode PVP response object + msg = (InboundMessage) decoder.decode( + request, response, metadataProvider, true, + comperator); + + if (MiscUtil.isEmpty(msg.getEntityID())) { + throw new InvalidProtocolRequestException("sp.pvp2.04", + new Object[] {EidasCentralAuthConstants.MODULE_NAME_FOR_LOGGING}); + + } + + //validate response signature + if(!msg.isVerified()) { + samlVerificationEngine.verify(msg, TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + msg.setVerified(true); + + } + + //validate assertion + PVPSProfileResponse processedMsg = preProcessAuthResponse((PVPSProfileResponse) msg); + + //validate entityId of response + String msNodeEntityID = authConfig.getBasicConfiguration(EidasCentralAuthConstants.CONFIG_PROPS_NODE_ENTITYID); + String respEntityId = msg.getEntityID(); + if (!msNodeEntityID.equals(respEntityId)) { + Logger.warn("Response Issuer is not a 'ms-specific eIDAS node'. Stopping eIDAS authentication ..."); + throw new AuthnResponseValidationException("sp.pvp2.08", + new Object[] {EidasCentralAuthConstants.MODULE_NAME_FOR_LOGGING, + msg.getEntityID()}); + + } + + //initialize Attribute extractor + AssertionAttributeExtractor extractor = + new AssertionAttributeExtractor((Response) processedMsg.getResponse()); + + getAuthDataFromInterfederation(extractor, pendingReq.getServiceProviderConfiguration(IOAAuthParameters.class)); + + //store pending-request + requestStoreage.storePendingRequest(pendingReq); + + //write log entries + revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_EIDAS_AT_CONNECTOR_MDS_VALID); + Logger.info("Receive a valid assertion from IDP " + msg.getEntityID()); + + } catch (MessageDecodingException | SecurityException e) { + String samlRequest = request.getParameter("SAMLRequest"); + Logger.warn("Receive INVALID PVP Response from 'ms-specific eIDAS node': " + samlRequest, e); + throw new TaskExecutionException(pendingReq, "Receive INVALID PVP Response from federated IDP", e); + + } catch (IOException | MarshallingException | TransformerException e) { + Logger.warn("Processing PVP response from 'ms-specific eIDAS node' FAILED.", e); + throw new TaskExecutionException(pendingReq, "Processing PVP response from 'ms-specific eIDAS node' FAILED.", e); + + } catch (CredentialsNotAvailableException e) { + Logger.error("PVP response decrytion FAILED. No credential found.", e); + throw new TaskExecutionException(pendingReq, "PVP response decrytion FAILED. No credential found.", e); + + } catch (AssertionValidationExeption | AuthnResponseValidationException e) { + Logger.info("PVP response validation FAILED. Msg:" + e.getMessage()); + throw new TaskExecutionException(pendingReq, "PVP response validation FAILED.", e); + + } catch (Exception e) { + Logger.warn("PVP response validation FAILED. Msg:" + e.getMessage(), e); + throw new TaskExecutionException(pendingReq, "PVP response validation FAILED.", e); + + } + + } + + private void getAuthDataFromInterfederation(AssertionAttributeExtractor extractor, IOAAuthParameters spConfig) throws BuildException, ConfigurationException{ + try { + //check if all attributes are include + if (!extractor.containsAllRequiredAttributes() + && !extractor.containsAllRequiredAttributes(EidasCentralAuthConstants.DEFAULT_REQUIRED_PVP_ATTRIBUTE_NAMES)) { + Logger.warn("PVP Response from federated IDP contains not all requested attributes."); + throw new AssertionValidationExeption("sp.pvp2.06", new Object[]{EidasCentralAuthConstants.MODULE_NAME_FOR_LOGGING}); + + } + + //copy attributes into MOASession + Set<String> includedAttrNames = extractor.getAllIncludeAttributeNames(); + for (String el : includedAttrNames) { + String value = extractor.getSingleAttributeValue(el); + pendingReq.setGenericDataToSession(el, value); + Logger.debug("Add PVP-attribute " + el + " into MOASession"); + + } + + } catch (AssertionValidationExeption e) { + throw new BuildException("builder.06", null, e); + + } catch (EAAFStorageException e) { + throw new BuildException("builder.06", null, e); + + } + } + + /** + * PreProcess AuthResponse and Assertion + * @param msg + * @throws TransformerException + * @throws MarshallingException + * @throws IOException + * @throws CredentialsNotAvailableException + * @throws AssertionValidationExeption + * @throws AuthnResponseValidationException + */ + private PVPSProfileResponse preProcessAuthResponse(PVPSProfileResponse msg) throws IOException, MarshallingException, TransformerException, AssertionValidationExeption, CredentialsNotAvailableException, AuthnResponseValidationException { + Logger.debug("Start PVP21 assertion processing... "); + Response samlResp = (Response) msg.getResponse(); + + // check SAML2 response status-code + if (samlResp.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) { + //validate PVP 2.1 assertion + samlVerificationEngine.validateAssertion(samlResp, true, + credentialProvider.getIDPAssertionEncryptionCredential(), + pendingReq.getAuthURL() + EidasCentralAuthConstants.ENDPOINT_METADATA, + EidasCentralAuthConstants.MODULE_NAME_FOR_LOGGING); + + msg.setSAMLMessage(SAML2Utils.asDOMDocument(samlResp).getDocumentElement()); + revisionsLogger.logEvent(pendingReq, + MOAIDEventConstants.AUTHPROCESS_EIDAS_AT_CONNECTOR_RECEIVED, + samlResp.getID()); + return msg; + + } else { + Logger.info("Receive StatusCode " + samlResp.getStatus().getStatusCode().getValue() + + " from 'ms-specific eIDAS node'."); + revisionsLogger.logEvent(pendingReq, + MOAIDEventConstants.AUTHPROCESS_EIDAS_AT_CONNECTOR_RECEIVED_ERROR); + throw new AuthnResponseValidationException("sp.pvp2.05", + new Object[]{EidasCentralAuthConstants.MODULE_NAME_FOR_LOGGING, + samlResp.getIssuer().getValue(), + samlResp.getStatus().getStatusCode().getValue(), + samlResp.getStatus().getStatusMessage().getMessage()}); + + } + + } + +} diff --git a/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/utils/EidasCentralAuthCredentialProvider.java b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/utils/EidasCentralAuthCredentialProvider.java new file mode 100644 index 000000000..f2f8530f6 --- /dev/null +++ b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/utils/EidasCentralAuthCredentialProvider.java @@ -0,0 +1,124 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.eIDAScentralAuth.utils; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.impl.utils.FileUtils; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.EidasCentralAuthConstants; +import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; +import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException; + +/** + * @author tlenz + * + */ +@Service("EidasCentralAuthCredentialProvider") +public class EidasCentralAuthCredentialProvider extends AbstractCredentialProvider { + + @Autowired AuthConfiguration authConfig; + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getKeyStoreFilePath() + */ + @Override + public String getKeyStoreFilePath() throws ConfigurationException { + return FileUtils.makeAbsoluteURL( + authConfig.getBasicConfiguration(EidasCentralAuthConstants.CONFIG_PROPS_KEYSTORE), + authConfig.getRootConfigFileDir()); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getKeyStorePassword() + */ + @Override + public String getKeyStorePassword() { + return authConfig.getBasicConfiguration(EidasCentralAuthConstants.CONFIG_PROPS_KEYSTOREPASSWORD).trim(); + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getMetadataKeyAlias() + */ + @Override + public String getMetadataKeyAlias() { + return authConfig.getBasicConfiguration( + EidasCentralAuthConstants.CONFIG_PROPS_SIGN_METADATA_ALIAS_PASSWORD).trim(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getMetadataKeyPassword() + */ + @Override + public String getMetadataKeyPassword() { + return authConfig.getBasicConfiguration( + EidasCentralAuthConstants.CONFIG_PROPS_SIGN_METADATA_KEY_PASSWORD).trim(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getSignatureKeyAlias() + */ + @Override + public String getSignatureKeyAlias() { + return authConfig.getBasicConfiguration( + EidasCentralAuthConstants.CONFIG_PROPS_SIGN_SIGNING_ALIAS_PASSWORD).trim(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getSignatureKeyPassword() + */ + @Override + public String getSignatureKeyPassword() { + return authConfig.getBasicConfiguration( + EidasCentralAuthConstants.CONFIG_PROPS_SIGN_SIGNING_KEY_PASSWORD).trim(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getEncryptionKeyAlias() + */ + @Override + public String getEncryptionKeyAlias() { + return authConfig.getBasicConfiguration( + EidasCentralAuthConstants.CONFIG_PROPS_ENCRYPTION_ALIAS_PASSWORD).trim(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getEncryptionKeyPassword() + */ + @Override + public String getEncryptionKeyPassword() { + return authConfig.getBasicConfiguration( + EidasCentralAuthConstants.CONFIG_PROPS_ENCRYPTION_KEY_PASSWORD).trim(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getCredentialName() + */ + @Override + public String getFriendlyName() { + return "eIDAS centrial authentication"; + } + +} diff --git a/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/utils/EidasCentralAuthMetadataProvider.java b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/utils/EidasCentralAuthMetadataProvider.java new file mode 100644 index 000000000..5cee90658 --- /dev/null +++ b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/java/at/gv/egovernment/moa/id/auth/modules/eIDAScentralAuth/utils/EidasCentralAuthMetadataProvider.java @@ -0,0 +1,345 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.eIDAScentralAuth.utils; + +import java.net.MalformedURLException; +import java.util.List; +import java.util.Timer; + +import javax.xml.namespace.QName; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.MOAHttpClient; +import org.apache.commons.httpclient.params.HttpClientParams; +import org.opensaml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.RoleDescriptor; +import org.opensaml.saml2.metadata.provider.ChainingMetadataProvider; +import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; +import org.opensaml.saml2.metadata.provider.MetadataFilter; +import org.opensaml.saml2.metadata.provider.MetadataProvider; +import org.opensaml.saml2.metadata.provider.MetadataProviderException; +import org.opensaml.xml.XMLObject; +import org.opensaml.xml.parse.BasicParserPool; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.api.IDestroyableObject; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.MetadataFilterChain; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.SimpleMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SchemaValidationFilter; +import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.EidasCentralAuthConstants; +import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; +import at.gv.egovernment.moa.id.commons.ex.MOAHttpProtocolSocketFactoryException; +import at.gv.egovernment.moa.id.commons.utils.MOAHttpProtocolSocketFactory; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; +import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.MOASPMetadataSignatureFilter; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * @author tlenz + * + */ + +@Service("EidasCentralAuthMetadataProvider") +public class EidasCentralAuthMetadataProvider extends SimpleMetadataProvider + implements IDestroyableObject { + @Autowired(required=true) AuthConfiguration moaAuthConfig; + + private ChainingMetadataProvider metadataProvider = new ChainingMetadataProvider(); + private Timer timer = null; + + + public EidasCentralAuthMetadataProvider() { + metadataProvider.setRequireValidMetadata(true); + + } + + public void addMetadataWithMetadataURL(String metadataURL) throws MetadataProviderException { + internalInitialize(metadataURL); + + } + + public void destroy() { + fullyDestroy(); + + } + + + + /* (non-Javadoc) + * @see org.opensaml.saml2.metadata.provider.MetadataProvider#requireValidMetadata() + */ + @Override + public boolean requireValidMetadata() { + return metadataProvider.requireValidMetadata(); + + } + + /* (non-Javadoc) + * @see org.opensaml.saml2.metadata.provider.MetadataProvider#setRequireValidMetadata(boolean) + */ + @Override + public void setRequireValidMetadata(boolean requireValidMetadata) { + metadataProvider.setRequireValidMetadata(requireValidMetadata); + + } + + /* (non-Javadoc) + * @see org.opensaml.saml2.metadata.provider.MetadataProvider#getMetadataFilter() + */ + @Override + public MetadataFilter getMetadataFilter() { + return metadataProvider.getMetadataFilter(); + + } + + /* (non-Javadoc) + * @see org.opensaml.saml2.metadata.provider.MetadataProvider#setMetadataFilter(org.opensaml.saml2.metadata.provider.MetadataFilter) + */ + @Override + public void setMetadataFilter(MetadataFilter newFilter) throws MetadataProviderException { + Logger.fatal("Set Metadata Filter is not implemented her!"); + + } + + /* (non-Javadoc) + * @see org.opensaml.saml2.metadata.provider.MetadataProvider#getMetadata() + */ + @Override + public XMLObject getMetadata() throws MetadataProviderException { + return metadataProvider.getMetadata(); + + } + + /* (non-Javadoc) + * @see org.opensaml.saml2.metadata.provider.MetadataProvider#getEntitiesDescriptor(java.lang.String) + */ + @Override + public EntitiesDescriptor getEntitiesDescriptor(String name) throws MetadataProviderException { + return metadataProvider.getEntitiesDescriptor(name); + + } + + /* (non-Javadoc) + * @see org.opensaml.saml2.metadata.provider.MetadataProvider#getEntityDescriptor(java.lang.String) + */ + @Override + public EntityDescriptor getEntityDescriptor(String entityID) throws MetadataProviderException { + try { + //search if metadata is already loaded + EntityDescriptor entityDesc = metadataProvider.getEntityDescriptor(entityID); + + if (entityDesc != null) + return entityDesc; + else + Logger.info("No ms-specific eIDAS node: " + entityID + " Starting refresh process ..."); + + } catch (MetadataProviderException e) { + Logger.info("Access ms-specific eIDAS node: " + entityID + " FAILED. Reason:" + e.getMessage() + " Starting refresh process ..."); + + } + + //(re)initialize ms-specific eIDAS node + internalInitialize(entityID); + + //search again after reload (re)initialization + try { + EntityDescriptor entityDesc = metadataProvider.getEntityDescriptor(entityID); + if (entityDesc == null) { + Logger.error("MS-specific eIDAS node Client ERROR: No EntityID with "+ entityID); + throw new MetadataProviderException("No EntityID with "+ entityID); + } + + return entityDesc; + + } catch (MetadataProviderException e) { + Logger.error("MS-specific eIDAS node Client ERROR: Metadata extraction FAILED.", e); + throw new MetadataProviderException("Metadata extraction FAILED", e); + + } + } + + /* (non-Javadoc) + * @see org.opensaml.saml2.metadata.provider.MetadataProvider#getRole(java.lang.String, javax.xml.namespace.QName) + */ + @Override + public List<RoleDescriptor> getRole(String entityID, QName roleName) throws MetadataProviderException { + try { + //search if metadata is already loaded + List<RoleDescriptor> role = metadataProvider.getRole(entityID, roleName); + + if (role != null) + return role; + else + Logger.info("No ms-specific eIDAS node: " + entityID + " Starting refresh process ..."); + + } catch (MetadataProviderException e) { + Logger.info("Access ms-specific eIDAS node: " + entityID + " FAILED. Reason:" + e.getMessage() + " Starting refresh process ..."); + + } + + //(re)initialize ms-specific eIDAS node + internalInitialize(entityID); + + //search again after reload (re)initialization + return metadataProvider.getRole(entityID, roleName); + } + + /* (non-Javadoc) + * @see org.opensaml.saml2.metadata.provider.MetadataProvider#getRole(java.lang.String, javax.xml.namespace.QName, java.lang.String) + */ + @Override + public RoleDescriptor getRole(String entityID, QName roleName, String supportedProtocol) + throws MetadataProviderException { + try { + //search if metadata is already loaded + RoleDescriptor role = metadataProvider.getRole(entityID, roleName, supportedProtocol); + + if (role != null) + return role; + else + Logger.info("No ms-specific eIDAS node: " + entityID + " Starting refresh process ..."); + + } catch (MetadataProviderException e) { + Logger.info("Access ms-specific eIDAS node: " + entityID + " FAILED. Reason:" + e.getMessage() + " Starting refresh process ..."); + + } + + //(re)initialize ms-specific eIDAS node + internalInitialize(entityID); + + //search again after reload (re)initialization + return metadataProvider.getRole(entityID, roleName, supportedProtocol); + } + + private synchronized void internalInitialize(String metdataURL) throws MetadataProviderException { + + //check if metadata with EntityID already exists in chaining metadata provider + boolean addNewMetadata = true; + try { + addNewMetadata = (metadataProvider.getEntityDescriptor(metdataURL) == null); + + } catch (MetadataProviderException e) {} + + //switch between metadata refresh and add new metadata + if (addNewMetadata) { + //Metadata provider seems not loaded --> Add new metadata provider + Logger.info("Initialize PVP MetadataProvider:" + metdataURL + " to connect ms-specific eIDAS node"); + + String trustProfileID = authConfig.getBasicConfiguration(EidasCentralAuthConstants.CONFIG_PROPS_NODE_TRUSTPROFILEID); + if (MiscUtil.isEmpty(trustProfileID)) { + Logger.error("Create ms-specific eIDAS node Client FAILED: No trustProfileID to verify PVP metadata." ); + throw new MetadataProviderException("No trustProfileID to verify PVP metadata."); + } + + //initialize Timer if it is null + if (timer == null) + timer = new Timer(true); + + //create metadata validation filter chain + MetadataFilterChain filter = new MetadataFilterChain(); + filter.addFilter(new SchemaValidationFilter(true)); + filter.addFilter(new MOASPMetadataSignatureFilter(trustProfileID)); + + MetadataProvider idpMetadataProvider = createNewSimpleMetadataProvider(metdataURL, + filter, + EidasCentralAuthConstants.MODULE_NAME_FOR_LOGGING, + timer, + new BasicParserPool(), + createHttpClient(metdataURL)); + + if (idpMetadataProvider == null) { + Logger.error("Create ms-specific eIDAS node Client FAILED."); + throw new MetadataProviderException("Can not initialize 'ms-specific eIDAS node' metadata provider."); + + } + + idpMetadataProvider.setRequireValidMetadata(true); + metadataProvider.addMetadataProvider(idpMetadataProvider); + + } else { + //Metadata provider seems already loaded --> start refresh process + List<MetadataProvider> loadedProvider = metadataProvider.getProviders(); + for (MetadataProvider el : loadedProvider) { + if (el instanceof HTTPMetadataProvider) { + HTTPMetadataProvider prov = (HTTPMetadataProvider)el; + if (prov.getMetadataURI().equals(metdataURL)) + prov.refresh(); + + } else + Logger.warn("'ms-specific eIDAS node' Metadata provider is not of Type 'HTTPMetadataProvider'! Something is suspect!!!!"); + + } + } + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.IDestroyableObject#fullyDestroy() + */ + @Override + public void fullyDestroy() { + Logger.info("Destroy 'ms-specific eIDAS node' PVP metadata pool ... "); + + if (metadataProvider != null) { + metadataProvider.destroy(); + + } + + if (timer != null) + timer.cancel(); + + } + + private HttpClient createHttpClient(String metadataURL) { + MOAHttpClient httpClient = new MOAHttpClient(); + HttpClientParams httpClientParams = new HttpClientParams(); + httpClientParams.setSoTimeout(AuthConfiguration.CONFIG_PROPS_METADATA_SOCKED_TIMEOUT); + httpClient.setParams(httpClientParams); + + if (metadataURL.startsWith("https:")) { + try { + //FIX: change hostname validation default flag to true when httpClient is updated to > 4.4 + MOAHttpProtocolSocketFactory protoSocketFactory = new MOAHttpProtocolSocketFactory( + PVPConstants.SSLSOCKETFACTORYNAME, + moaAuthConfig.getTrustedCACertificates(), + null, + AuthConfiguration.DEFAULT_X509_CHAININGMODE, + moaAuthConfig.isTrustmanagerrevoationchecking(), + moaAuthConfig.getRevocationMethodOrder(), + moaAuthConfig.getBasicMOAIDConfigurationBoolean( + AuthConfiguration.PROP_KEY_SSL_HOSTNAME_VALIDATION, false)); + + httpClient.setCustomSSLTrustStore(metadataURL, protoSocketFactory); + + } catch (MOAHttpProtocolSocketFactoryException | MalformedURLException e) { + Logger.warn("MOA SSL-TrustStore can not initialized. Use default Java TrustStore.", e); + + } + } + + return httpClient; + + } +} diff --git a/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider new file mode 100644 index 000000000..5954455a4 --- /dev/null +++ b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider @@ -0,0 +1 @@ +at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.EidasCentralAuthSpringResourceProvider
\ No newline at end of file diff --git a/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/resources/eIDAS_central_node_auth.process.xml b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/resources/eIDAS_central_node_auth.process.xml new file mode 100644 index 000000000..02bf7bcad --- /dev/null +++ b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/resources/eIDAS_central_node_auth.process.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<pd:ProcessDefinition id="centrialEidasAuthentication" xmlns:pd="http://reference.e-government.gv.at/namespace/moa/process/definition/v1"> + + <pd:Task id="createEidasAuthnRequest" class="CreateEidasCentrialAuthnRequestTask" /> + <pd:Task id="receiveEidasAuthnResponse" class="ReceiveEidasCentrialAuthnResponseTask" async="true" /> + <pd:Task id="finalizeAuthentication" class="FinalizeAuthenticationTask" /> + + <pd:StartEvent id="start" /> + + <pd:Transition from="start" to="createEidasAuthnRequest" /> + <pd:Transition from="createEidasAuthnRequest" to="receiveEidasAuthnResponse"/> + <pd:Transition from="receiveEidasAuthnResponse" to="finalizeAuthentication"/> + <pd:Transition from="finalizeAuthentication" to="end" /> + + <pd:EndEvent id="end" /> + +</pd:ProcessDefinition>
\ No newline at end of file diff --git a/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/resources/moaid_eIDAS_central_node_auth.beans.xml b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/resources/moaid_eIDAS_central_node_auth.beans.xml new file mode 100644 index 000000000..f57d4a94b --- /dev/null +++ b/id/server/modules/moa-id-module-AT_eIDAS_connector/src/main/resources/moaid_eIDAS_central_node_auth.beans.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + +<!-- Federated authentication services --> + <bean id="EidasCentralAuthCredentialProvider" + class="at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.utils.EidasCentralAuthCredentialProvider"/> + + <bean id="EidasCentralAuthMetadataController" + class="at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.controller.EidasCentralAuthMetadataController"/> + + <bean id="EidasCentralAuthModuleImpl" + class="at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.EidasCentralAuthModuleImpl"> + <property name="priority" value="2" /> + </bean> + + <bean id="EidasCentralAuthSignalController" + class="at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.controller.EidasCentralAuthSignalController"/> + + <bean id="EidasCentralAuthMetadataProvider" + class="at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.utils.EidasCentralAuthMetadataProvider" /> + + <bean id="pvpAuthnRequestBuilder" + class="at.gv.egiz.eaaf.modules.pvp2.sp.impl.PVPAuthnRequestBuilder" /> + +<!-- Federated Authentication Process Tasks --> + <bean id="CreateEidasCentrialAuthnRequestTask" + class="at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.tasks.CreateAuthnRequestTask" + scope="prototype"/> + + <bean id="ReceiveEidasCentrialAuthnResponseTask" + class="at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.tasks.ReceiveAuthnResponseTask" + scope="prototype"/> + +</beans>
\ No newline at end of file |