From e950948eb691581e58607e633847e6f4b93769f9 Mon Sep 17 00:00:00 2001 From: Andreas Fitzek Date: Wed, 12 Jun 2013 12:03:13 +0200 Subject: Metadata IDP generation fixes, Auth Response fixes --- .../moa/id/entrypoints/DispatcherServlet.java | 67 --------- .../protocols/pvp2x/ExternalPVPSessionStore.java | 28 ++++ .../moa/id/protocols/pvp2x/MetadataAction.java | 44 +++++- .../moa/id/protocols/pvp2x/PVP2XProtocol.java | 12 +- .../moa/id/protocols/pvp2x/PVPConstants.java | 6 + .../pvp2x/SAMLRequestNotSignedException.java | 17 --- .../protocols/pvp2x/SAMLRequestNotSupported.java | 16 --- .../builder/attributes/BaseAttributeBuilder.java | 3 + .../EIDCitizenQAALevelAttributeBuilder.java | 2 +- .../protocols/pvp2x/config/PVPConfiguration.java | 1 + .../InvalidAssertionConsumerServiceException.java | 16 +++ .../pvp2x/exceptions/NoAuthContextException.java | 14 ++ .../protocols/pvp2x/exceptions/PVP2Exception.java | 37 +++++ .../pvp2x/exceptions/ResponderErrorException.java | 22 +++ .../exceptions/SAMLRequestNotSignedException.java | 17 +++ .../pvp2x/exceptions/SAMLRequestNotSupported.java | 18 +++ .../UnprovideableAttributeException.java | 15 +++ .../pvp2x/requestHandler/AuthnRequestHandler.java | 150 +++++++++++++++++++-- .../pvp2x/requestHandler/RequestManager.java | 2 +- .../moa/id/protocols/pvp2x/utils/SAML2Utils.java | 13 ++ .../pvp2x/validation/SAMLSignatureValidator.java | 2 +- .../pvp2x/verification/EntityVerifier.java | 2 +- 22 files changed, 381 insertions(+), 123 deletions(-) create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/ExternalPVPSessionStore.java delete mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SAMLRequestNotSignedException.java delete mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SAMLRequestNotSupported.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/InvalidAssertionConsumerServiceException.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/NoAuthContextException.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/PVP2Exception.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/ResponderErrorException.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SAMLRequestNotSignedException.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SAMLRequestNotSupported.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/UnprovideableAttributeException.java (limited to 'id/server/idserverlib/src/main') diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java index c993290e9..5fa0dfcc3 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java @@ -33,64 +33,6 @@ public class DispatcherServlet extends AuthServlet { public static final String PARAM_TARGET_MODULE = "mod"; public static final String PARAM_TARGET_ACTION = "action"; - /* - * public static final String PARAM_DISPATCHER_TARGETS = - * "DispatcherTargets"; public static final String PARAM_DISPATCHER_TYPE = - * "DispatcherType"; public static final String PARAM_DISPATCHER_TYPE_UNAUTH - * = "UNAUTH"; public static final String PARAM_DISPATCHER_TYPE_AUTH = - * "AUTH"; public static String SYSTEM_NEWLINE = - * System.getProperty("line.separator"); - */ - /* - * private HashMap> endpointMap = new - * HashMap>(); - * - * private void registerModule(IModulInfo modulInfo) { - * - * HashMap tempMap = new HashMap(); - * - * try { - * - * String path = modulInfo.getPath(); - * - * if (path == null) { throw new Exception(String.format( - * "%s does not return a valid target path!", new Object[] { - * modulInfo.getClass().getName() })); } - * - * Logger.debug("Registering: " + modulInfo.getName() + " under " + path); - * - * List servletInfos = modulInfo.getServlets(); - * - * Iterator servletInfoIterator = servletInfos.iterator(); - * - * while (servletInfoIterator.hasNext()) { - * - * ServletInfo servletInfo = servletInfoIterator.next(); - * - * if (servletInfo.getType() == ServletType.UNAUTH) { HttpServlet servlet = - * servletInfo.getServletInstance(); String target = - * servletInfo.getTarget(); - * - * if (target == null) { throw new Exception( String.format( - * "%s does not return a valid target identifier!", new Object[] { - * servlet.getClass() .getName() })); } - * - * if (tempMap.containsKey(target)) { throw new Exception(String.format( - * "%s tried to overwrite %s/%s", new Object[] { - * servlet.getClass().getName(), path, target })); } - * - * tempMap.put(target, servlet); Logger.info("Registered Servlet class: " + - * servlet.getClass().getName() + " OK"); } - * - * } - * - * // when there was no error we register all servlets into the real // - * endpoint map ... if (!tempMap.isEmpty()) { endpointMap.put(path, - * tempMap); } } catch (Throwable e) { - * Logger.error("Registering Modul class: " + modulInfo.getClass().getName() - * + " FAILED!!", e); } } - */ @Override public void init(ServletConfig config) throws ServletException { try { @@ -105,15 +47,6 @@ public class DispatcherServlet extends AuthServlet { throw new ServletException(ex); } Logger.info("Dispatcher Servlet initialization"); - - /* - * List modules = ModulStorage.getAllModules(); - * Iterator it = modules.iterator(); while (it.hasNext()) { - * IModulInfo info = it.next(); String targetClass = - * info.getClass().getName(); try { registerModule(info); } catch - * (Throwable e) { Logger.error("Registering Class " + targetClass + - * " FAILED!!", e); } } - */ } protected void processRequest(HttpServletRequest req, diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/ExternalPVPSessionStore.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/ExternalPVPSessionStore.java new file mode 100644 index 000000000..1e3c6145f --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/ExternalPVPSessionStore.java @@ -0,0 +1,28 @@ +package at.gv.egovernment.moa.id.protocols.pvp2x; + +import java.util.HashMap; +import java.util.Map; + +import org.opensaml.saml2.metadata.SPSSODescriptor; +import org.opensaml.xml.io.MarshallingException; + +public class ExternalPVPSessionStore { + + private Map externalSessions = new HashMap(); + + public boolean contains(String sessionID) { + return externalSessions.containsKey(sessionID); + } + + public void put(String sessionID, SPSSODescriptor sso) throws MarshallingException { + externalSessions.put(sessionID, sso); + } + + public SPSSODescriptor get(String sessionID) { + return externalSessions.get(sessionID); + } + + public void remove(String sessionID) { + externalSessions.remove(sessionID); + } +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java index d9129165e..85d5c2a46 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java @@ -17,13 +17,17 @@ import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import org.joda.time.DateTime; import org.opensaml.Configuration; import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.core.NameIDType; import org.opensaml.saml2.metadata.ArtifactResolutionService; import org.opensaml.saml2.metadata.ContactPerson; +import org.opensaml.saml2.metadata.EntitiesDescriptor; import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.saml2.metadata.IDPSSODescriptor; import org.opensaml.saml2.metadata.KeyDescriptor; +import org.opensaml.saml2.metadata.NameIDFormat; import org.opensaml.saml2.metadata.SingleSignOnService; import org.opensaml.xml.io.Marshaller; import org.opensaml.xml.io.MarshallingException; @@ -52,9 +56,20 @@ public class MetadataAction implements IAction { HttpServletResponse httpResp) throws MOAIDException { try { + EntitiesDescriptor idpEntitiesDescriptor = + SAML2Utils.createSAMLObject(EntitiesDescriptor.class); + + idpEntitiesDescriptor.setName(PVPConfiguration.getInstance().getIDPIssuerName()); + + idpEntitiesDescriptor.setID(SAML2Utils.getSecureIdentifier()); + + idpEntitiesDescriptor.setValidUntil(new DateTime().plusWeeks(4)); + EntityDescriptor idpEntityDescriptor = SAML2Utils .createSAMLObject(EntityDescriptor.class); + idpEntitiesDescriptor.getEntityDescriptors().add(idpEntityDescriptor); + idpEntityDescriptor .setEntityID("https://localhost:8443/moa-id-auth"); @@ -83,13 +98,15 @@ public class MetadataAction implements IAction { Signature signature = CredentialProvider .getIDPSignature(credential); - idpEntityDescriptor.setSignature(signature); + idpEntitiesDescriptor.setSignature(signature); IDPSSODescriptor idpSSODescriptor = SAML2Utils .createSAMLObject(IDPSSODescriptor.class); - idpSSODescriptor.setWantAuthnRequestsSigned(true); - + idpSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); + + idpSSODescriptor.setWantAuthnRequestsSigned(true); + if (PVPConfiguration.getInstance().getIDPSSOPostService() != null) { SingleSignOnService postSingleSignOnService = SAML2Utils .createSAMLObject(SingleSignOnService.class); @@ -125,6 +142,8 @@ public class MetadataAction implements IAction { artifactResolutionService.setLocation(PVPConfiguration .getInstance().getIDPResolveSOAPService()); + artifactResolutionService.setIndex(0); + idpSSODescriptor.getArtifactResolutionServices().add( artifactResolutionService); } @@ -133,6 +152,21 @@ public class MetadataAction implements IAction { idpSSODescriptor.getAttributes().addAll(PVPAttributeBuilder.buildSupportedEmptyAttributes()); + NameIDFormat persistenNameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); + persistenNameIDFormat.setFormat(NameIDType.PERSISTENT); + + idpSSODescriptor.getNameIDFormats().add(persistenNameIDFormat); + + NameIDFormat transientNameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); + transientNameIDFormat.setFormat(NameIDType.TRANSIENT); + + idpSSODescriptor.getNameIDFormats().add(transientNameIDFormat); + + NameIDFormat unspecifiedNameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); + unspecifiedNameIDFormat.setFormat(NameIDType.UNSPECIFIED); + + idpSSODescriptor.getNameIDFormats().add(unspecifiedNameIDFormat); + idpEntityDescriptor.getRoleDescriptors().add(idpSSODescriptor); DocumentBuilder builder; @@ -142,8 +176,8 @@ public class MetadataAction implements IAction { builder = factory.newDocumentBuilder(); Document document = builder.newDocument(); Marshaller out = Configuration.getMarshallerFactory() - .getMarshaller(idpEntityDescriptor); - out.marshall(idpEntityDescriptor, document); + .getMarshaller(idpEntitiesDescriptor); + out.marshall(idpEntitiesDescriptor, document); Signer.signObject(signature); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java index 33c8af197..d2a3764cd 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java @@ -37,6 +37,7 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.binding.MOARequest; import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding; import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.SAMLVerificationEngine; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory; @@ -195,13 +196,22 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants { if(e instanceof NoPassivAuthenticationException) { statusCode.setValue(StatusCode.NO_PASSIVE_URI); statusMessage.setMessage(e.getLocalizedMessage()); + } else if(e instanceof PVP2Exception) { + PVP2Exception ex = (PVP2Exception) e; + statusCode.setValue(ex.getStatusCodeValue()); + String statusMessageValue = ex.getStatusMessageValue(); + if(statusMessageValue != null) { + statusMessage.setMessage(statusMessageValue); + } } else { statusCode.setValue(StatusCode.RESPONDER_URI); statusMessage.setMessage(e.getLocalizedMessage()); } status.setStatusCode(statusCode); - status.setStatusMessage(statusMessage); + if(statusMessage.getMessage() != null) { + status.setStatusMessage(statusMessage); + } samlResponse.setStatus(status); IEncoder encoder = new RedirectBinding(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java index b818a2d8a..5875a37c7 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java @@ -1,6 +1,12 @@ package at.gv.egovernment.moa.id.protocols.pvp2x; public interface PVPConstants { + + public static final String STORK_QAA_1_1 = "http://www.ref.gv.at/ns/names/agiz/stork/qaa/1"; + public static final String STORK_QAA_1_2 = "http://www.ref.gv.at/ns/names/agiz/stork/qaa/1-2"; + public static final String STORK_QAA_1_3 = "http://www.ref.gv.at/ns/names/agiz/stork/qaa/1-3"; + public static final String STORK_QAA_1_4 = "http://www.ref.gv.at/ns/names/agiz/stork/qaa/1-4"; + public static final String URN_OID_PREFIX = "urn:oid:"; public static final String PVP_VERSION_OID = "1.2.40.0.10.2.1.1.261.10"; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SAMLRequestNotSignedException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SAMLRequestNotSignedException.java deleted file mode 100644 index 40f5685ad..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SAMLRequestNotSignedException.java +++ /dev/null @@ -1,17 +0,0 @@ -package at.gv.egovernment.moa.id.protocols.pvp2x; - -import at.gv.egovernment.moa.id.MOAIDException; - -public class SAMLRequestNotSignedException extends MOAIDException { - - public SAMLRequestNotSignedException(String messageId, Object[] parameters) { - super(messageId, parameters); - // TODO Auto-generated constructor stub - } - - /** - * - */ - private static final long serialVersionUID = 1L; - -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SAMLRequestNotSupported.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SAMLRequestNotSupported.java deleted file mode 100644 index 16b388a09..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SAMLRequestNotSupported.java +++ /dev/null @@ -1,16 +0,0 @@ -package at.gv.egovernment.moa.id.protocols.pvp2x; - -import at.gv.egovernment.moa.id.MOAIDException; - -public class SAMLRequestNotSupported extends MOAIDException { - - public SAMLRequestNotSupported(String messageId, Object[] parameters) { - super(messageId, parameters); - } - - /** - * - */ - private static final long serialVersionUID = 1244883178458802767L; - -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/BaseAttributeBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/BaseAttributeBuilder.java index d62cf72b1..d3c79c939 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/BaseAttributeBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/BaseAttributeBuilder.java @@ -35,6 +35,7 @@ public abstract class BaseAttributeBuilder implements PVPConstants, IAttributeBu SAML2Utils.createSAMLObject(Attribute.class); attribute.setFriendlyName(friendlyName); attribute.setName(name); + attribute.setNameFormat(Attribute.URI_REFERENCE); attribute.getAttributeValues().add(buildAttributeStringValue(value)); return attribute; } @@ -45,6 +46,7 @@ public abstract class BaseAttributeBuilder implements PVPConstants, IAttributeBu SAML2Utils.createSAMLObject(Attribute.class); attribute.setFriendlyName(friendlyName); attribute.setName(name); + attribute.setNameFormat(Attribute.URI_REFERENCE); attribute.getAttributeValues().add(buildAttributeIntegerValue(value)); return attribute; } @@ -54,6 +56,7 @@ public abstract class BaseAttributeBuilder implements PVPConstants, IAttributeBu SAML2Utils.createSAMLObject(Attribute.class); attribute.setFriendlyName(friendlyName); attribute.setName(name); + attribute.setNameFormat(Attribute.URI_REFERENCE); return attribute; } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/EIDCitizenQAALevelAttributeBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/EIDCitizenQAALevelAttributeBuilder.java index 5524ed44d..d9c66e6f0 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/EIDCitizenQAALevelAttributeBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/EIDCitizenQAALevelAttributeBuilder.java @@ -12,7 +12,7 @@ public class EIDCitizenQAALevelAttributeBuilder extends BaseAttributeBuilder { public Attribute build(AuthenticationSession authSession) { return buildIntegerAttribute(EID_CITIZEN_QAA_LEVEL_FRIENDLY_NAME, - EID_CITIZEN_QAA_LEVEL_NAME, 2); + EID_CITIZEN_QAA_LEVEL_NAME, 4); } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java index d38c900bc..5a054b142 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java @@ -68,6 +68,7 @@ public class PVPConfiguration { public static final String IDP_REDIRECT_SSO_SERVICE = "idp.sso.redirect"; public static final String IDP_SOAP_RESOLVE_SERVICE = "idp.resolve.soap"; + public static final String IDP_TRUST_STORE = "idp.truststore"; public static final String SP_TARGET_PREFIX = "sp.target."; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/InvalidAssertionConsumerServiceException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/InvalidAssertionConsumerServiceException.java new file mode 100644 index 000000000..d8dd3729a --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/InvalidAssertionConsumerServiceException.java @@ -0,0 +1,16 @@ +package at.gv.egovernment.moa.id.protocols.pvp2x.exceptions; + +public class InvalidAssertionConsumerServiceException extends PVP2Exception { + + public InvalidAssertionConsumerServiceException(String messageId, + Object[] parameters) { + super(messageId, parameters); + // TODO Auto-generated constructor stub + } + + /** + * + */ + private static final long serialVersionUID = 7861790149343943091L; + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/NoAuthContextException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/NoAuthContextException.java new file mode 100644 index 000000000..0d464ccfa --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/NoAuthContextException.java @@ -0,0 +1,14 @@ +package at.gv.egovernment.moa.id.protocols.pvp2x.exceptions; + +public class NoAuthContextException extends PVP2Exception { + + /** + * + */ + private static final long serialVersionUID = 7040652043174500992L; + + public NoAuthContextException(String messageId, Object[] parameters) { + super(messageId, parameters); + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/PVP2Exception.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/PVP2Exception.java new file mode 100644 index 000000000..1e4cf15b8 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/PVP2Exception.java @@ -0,0 +1,37 @@ +package at.gv.egovernment.moa.id.protocols.pvp2x.exceptions; + +import org.opensaml.saml2.core.StatusCode; + +import at.gv.egovernment.moa.id.MOAIDException; + +public abstract class PVP2Exception extends MOAIDException { + + protected String statusCodeValue = StatusCode.RESPONDER_URI; + protected String statusMessageValue = null; + + public PVP2Exception(String messageId, Object[] parameters, + Throwable wrapped) { + super(messageId, parameters, wrapped); + } + + public PVP2Exception(String messageId, Object[] parameters) { + super(messageId, parameters); + } + + + public String getStatusCodeValue() { + return (this.statusCodeValue); + } + + public String getStatusMessageValue() { + return (this.statusMessageValue); + } + + /** + * + */ + private static final long serialVersionUID = 7669537952484421069L; + + + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/ResponderErrorException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/ResponderErrorException.java new file mode 100644 index 000000000..a24320cbc --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/ResponderErrorException.java @@ -0,0 +1,22 @@ +package at.gv.egovernment.moa.id.protocols.pvp2x.exceptions; + +import org.opensaml.saml2.core.StatusCode; + +public class ResponderErrorException extends PVP2Exception { + + /** + * + */ + private static final long serialVersionUID = -425416760138285446L; + + public ResponderErrorException(String messageId, Object[] parameters, + Throwable wrapped) { + super(messageId, parameters, wrapped); + this.statusCodeValue = StatusCode.RESPONDER_URI; + } + + public ResponderErrorException(String messageId, Object[] parameters) { + super(messageId, parameters); + this.statusCodeValue = StatusCode.RESPONDER_URI; + } +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SAMLRequestNotSignedException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SAMLRequestNotSignedException.java new file mode 100644 index 000000000..871c6f4bd --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SAMLRequestNotSignedException.java @@ -0,0 +1,17 @@ +package at.gv.egovernment.moa.id.protocols.pvp2x.exceptions; + +import org.opensaml.saml2.core.StatusCode; + +public class SAMLRequestNotSignedException extends PVP2Exception { + + public SAMLRequestNotSignedException(String messageId, Object[] parameters) { + super(messageId, parameters); + this.statusCodeValue = StatusCode.REQUESTER_URI; + } + + /** + * + */ + private static final long serialVersionUID = 1L; + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SAMLRequestNotSupported.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SAMLRequestNotSupported.java new file mode 100644 index 000000000..99940335b --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SAMLRequestNotSupported.java @@ -0,0 +1,18 @@ +package at.gv.egovernment.moa.id.protocols.pvp2x.exceptions; + +import org.opensaml.saml2.core.StatusCode; + + +public class SAMLRequestNotSupported extends PVP2Exception { + + public SAMLRequestNotSupported(String messageId, Object[] parameters) { + super(messageId, parameters); + this.statusCodeValue = StatusCode.REQUEST_UNSUPPORTED_URI; + } + + /** + * + */ + private static final long serialVersionUID = 1244883178458802767L; + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/UnprovideableAttributeException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/UnprovideableAttributeException.java new file mode 100644 index 000000000..6aeed47d7 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/UnprovideableAttributeException.java @@ -0,0 +1,15 @@ +package at.gv.egovernment.moa.id.protocols.pvp2x.exceptions; + +import org.opensaml.saml2.core.StatusCode; + +public class UnprovideableAttributeException extends PVP2Exception { + /** + * + */ + private static final long serialVersionUID = 3972197758163647157L; + + public UnprovideableAttributeException(String attributeName) { + super(attributeName, null); + this.statusCodeValue = StatusCode.UNKNOWN_ATTR_PROFILE_URI; + } +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/AuthnRequestHandler.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/AuthnRequestHandler.java index 964c19208..9e795c51c 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/AuthnRequestHandler.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/AuthnRequestHandler.java @@ -11,14 +11,23 @@ import org.opensaml.saml2.core.ArtifactResponse; import org.opensaml.saml2.core.Assertion; import org.opensaml.saml2.core.Attribute; import org.opensaml.saml2.core.AttributeStatement; +import org.opensaml.saml2.core.Audience; +import org.opensaml.saml2.core.AudienceRestriction; import org.opensaml.saml2.core.AuthnContext; import org.opensaml.saml2.core.AuthnContextClassRef; import org.opensaml.saml2.core.AuthnRequest; import org.opensaml.saml2.core.AuthnStatement; +import org.opensaml.saml2.core.Conditions; import org.opensaml.saml2.core.Issuer; import org.opensaml.saml2.core.NameID; +import org.opensaml.saml2.core.RequestedAuthnContext; import org.opensaml.saml2.core.Subject; +import org.opensaml.saml2.core.SubjectConfirmation; +import org.opensaml.saml2.core.SubjectConfirmationData; +import org.opensaml.saml2.metadata.AssertionConsumerService; import org.opensaml.saml2.metadata.AttributeConsumingService; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.NameIDFormat; import org.opensaml.saml2.metadata.RequestedAttribute; import org.opensaml.saml2.metadata.SPSSODescriptor; import org.opensaml.ws.message.encoder.MessageEncodingException; @@ -27,14 +36,21 @@ import org.opensaml.xml.security.SecurityException; import at.gv.egovernment.moa.id.MOAIDException; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; import at.gv.egovernment.moa.id.moduls.AuthenticationManager; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; +import at.gv.egovernment.moa.id.protocols.pvp2x.binding.ArtifactBinding; import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder; import at.gv.egovernment.moa.id.protocols.pvp2x.binding.MOARequest; import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding; +import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.PVPAttributeBuilder; import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.InvalidAssertionConsumerServiceException; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoAuthContextException; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SAMLRequestNotSupported; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.UnprovideableAttributeException; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; -public class AuthnRequestHandler implements IRequestHandler { +public class AuthnRequestHandler implements IRequestHandler, PVPConstants { public boolean handleObject(MOARequest obj) { return (obj.getSamlRequest() instanceof AuthnRequest); @@ -48,26 +64,75 @@ public class AuthnRequestHandler implements IRequestHandler { AuthnRequest authnRequest = (AuthnRequest)obj.getSamlRequest(); + RequestedAuthnContext reqAuthnContext = authnRequest.getRequestedAuthnContext(); + + if(reqAuthnContext == null) { + throw new NoAuthContextException("No Authn Context provided!", null); + } + + boolean stork_qaa_1_4_found = false; + + Iterator reqAuthnContextClassRefIt = reqAuthnContext.getAuthnContextClassRefs().iterator(); + + while(reqAuthnContextClassRefIt.hasNext()) { + AuthnContextClassRef authnClassRef = reqAuthnContextClassRefIt.next(); + String[] qaa_uris = authnClassRef.getAuthnContextClassRef().split("\\s+"); + for(int i = 0; i < qaa_uris.length; i++) { + if(qaa_uris[i].trim().equals(STORK_QAA_1_4)) { + stork_qaa_1_4_found = true; + break; + } + } + } + + if(!stork_qaa_1_4_found) { + throw new NoAuthContextException("QAA not available Only supported QAA: " + STORK_QAA_1_4, null); + } + Assertion assertion = SAML2Utils.createSAMLObject(Assertion.class); + reqAuthnContextClassRefIt = reqAuthnContext.getAuthnContextClassRefs().iterator(); + StringBuilder authContextsb = new StringBuilder(); + while(reqAuthnContextClassRefIt.hasNext()) { + AuthnContextClassRef authnClassRef = reqAuthnContextClassRefIt.next(); + String[] qaa_uris = authnClassRef.getAuthnContextClassRef().split("\\s+"); + for(int i = 0; i < qaa_uris.length; i++) { + if(qaa_uris[i].trim().equals(STORK_QAA_1_4) || + qaa_uris[i].trim().equals(STORK_QAA_1_3)|| + qaa_uris[i].trim().equals(STORK_QAA_1_2)|| + qaa_uris[i].trim().equals(STORK_QAA_1_1)) { + authContextsb.append(qaa_uris[i].trim()); + authContextsb.append(" "); + } + } + + } AuthnContextClassRef authnContextClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class); - authnContextClassRef.setAuthnContextClassRef(AuthnContext.SMARTCARD_PKI_AUTHN_CTX); - + authnContextClassRef.setAuthnContextClassRef(authContextsb.toString()); AuthnContext authnContext = SAML2Utils.createSAMLObject(AuthnContext.class); authnContext.setAuthnContextClassRef(authnContextClassRef); AuthnStatement authnStatement = SAML2Utils.createSAMLObject(AuthnStatement.class); - + String remoteSessionID = SAML2Utils.getSecureIdentifier(); authnStatement.setAuthnInstant(new DateTime()); + // currently dummy id ... + authnStatement.setSessionIndex(remoteSessionID); authnStatement.setAuthnContext(authnContext); assertion.getAuthnStatements().add(authnStatement); - - SPSSODescriptor spSSODescriptor = obj.getEntityMetadata(). + EntityDescriptor peerEntity = obj.getEntityMetadata(); + SPSSODescriptor spSSODescriptor = peerEntity. getSPSSODescriptor(SAMLConstants.SAML20P_NS); + Integer aIdx = authnRequest.getAttributeConsumingServiceIndex(); + int idx = 0; + + if(aIdx != null) { + idx = aIdx.intValue(); + } + AttributeConsumingService attributeConsumingService = - spSSODescriptor.getAttributeConsumingServices().iterator().next(); + spSSODescriptor.getAttributeConsumingServices().get(idx); AuthenticationSession authSession = @@ -81,7 +146,7 @@ public class AuthnRequestHandler implements IRequestHandler { Attribute attr = PVPAttributeBuilder.buildAttribute(reqAttribut.getName(), authSession); if(attr == null) { if(reqAttribut.isRequired()) { - throw new MOAIDException("Cannot provide requested attribute " + reqAttribut.getName(), null); + throw new UnprovideableAttributeException(reqAttribut.getName()); } } else { attributeStatement.getAttributes().add(attr); @@ -94,10 +159,47 @@ public class AuthnRequestHandler implements IRequestHandler { Subject subject = SAML2Utils.createSAMLObject(Subject.class); NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class); + boolean foundFormat = false; + Iterator formatIt = spSSODescriptor.getNameIDFormats().iterator(); + while(formatIt.hasNext()) { + if(formatIt.next().getFormat().equals(NameID.PERSISTENT)) { + foundFormat = true; + break; + } + } + if(!foundFormat) { + // TODO use correct exception + throw new SAMLRequestNotSupported(NameID.PERSISTENT + " not supported by SP", null); + } subjectNameID.setFormat(NameID.PERSISTENT); + subjectNameID.setNameQualifier(authSession.getIdentityLink().getIdentificationType()); subjectNameID.setValue(authSession.getAuthData().getIdentificationValue()); subject.setNameID(subjectNameID); + SubjectConfirmation subjectConfirmation = SAML2Utils.createSAMLObject(SubjectConfirmation.class); + subjectConfirmation.setMethod(SubjectConfirmation.METHOD_BEARER); + SubjectConfirmationData subjectConfirmationData = + SAML2Utils.createSAMLObject(SubjectConfirmationData.class); + subjectConfirmationData.setInResponseTo(authnRequest.getID()); + subjectConfirmationData.setNotOnOrAfter(new DateTime().plusMinutes(20)); + subjectConfirmationData.setRecipient(peerEntity.getEntityID()); + + subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData); + + subject.getSubjectConfirmations().add(subjectConfirmation); + + Conditions conditions = SAML2Utils.createSAMLObject(Conditions.class); + AudienceRestriction audienceRestriction = SAML2Utils.createSAMLObject(AudienceRestriction.class); + Audience audience = SAML2Utils.createSAMLObject(Audience.class); + + audience.setAudienceURI(peerEntity.getEntityID()); + audienceRestriction.getAudiences().add(audience); + conditions.setNotBefore(new DateTime()); + conditions.setNotOnOrAfter(new DateTime().plusMinutes(20)); + conditions.getAudienceRestrictions().add(audienceRestriction); + + assertion.setConditions(conditions); + //assertion.getAttributeStatements().add(CitizenTokenBuilder.buildCitizenToken(obj, authSession)); Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); @@ -105,6 +207,8 @@ public class AuthnRequestHandler implements IRequestHandler { issuer.setFormat(NameID.ENTITY); assertion.setIssuer(issuer); assertion.setSubject(subject); + assertion.setID(SAML2Utils.getSecureIdentifier()); + assertion.setIssueInstant(new DateTime()); ArtifactResponse authResponse = SAML2Utils.createSAMLObject(ArtifactResponse.class); @@ -116,21 +220,41 @@ public class AuthnRequestHandler implements IRequestHandler { authResponse.setMessage(assertion); authResponse.setStatus(SAML2Utils.getSuccessStatus()); - Integer aIdx = authnRequest.getAssertionConsumerServiceIndex(); - int idx = 0; + aIdx = authnRequest.getAssertionConsumerServiceIndex(); + idx = 0; if(aIdx != null) { idx = aIdx.intValue(); } + AssertionConsumerService consumerService = spSSODescriptor. + getAssertionConsumerServices().get(idx); + + if(consumerService == null) { + throw new InvalidAssertionConsumerServiceException("IDX " + idx + " is not a valid consumer service index!", null); + } + String oaURL = consumerService.getLocation(); + + IEncoder binding = null; - String oaURL = spSSODescriptor. - getAssertionConsumerServices().get(idx).getLocation(); + if(consumerService.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { + binding = new RedirectBinding(); + } else if(consumerService.getBinding().equals(SAMLConstants.SAML2_ARTIFACT_BINDING_URI)) { + // TODO: not supported YET!! + binding = new ArtifactBinding(); + } else if(consumerService.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { + binding = new PostBinding(); + } + + if(binding == null) { + throw new InvalidAssertionConsumerServiceException("Binding " + consumerService.getBinding() + " is not supported", null); + } - IEncoder binding = new PostBinding(); try { binding.encodeRespone(req, resp, authResponse, oaURL); + // TODO add remoteSessionID to AuthSession ExternalPVPSessionStore } catch (MessageEncodingException e) { + e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/RequestManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/RequestManager.java index 0e5fa9b1e..9496ecb31 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/RequestManager.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/RequestManager.java @@ -8,8 +8,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import at.gv.egovernment.moa.id.MOAIDException; -import at.gv.egovernment.moa.id.protocols.pvp2x.SAMLRequestNotSupported; import at.gv.egovernment.moa.id.protocols.pvp2x.binding.MOARequest; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SAMLRequestNotSupported; public class RequestManager { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/SAML2Utils.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/SAML2Utils.java index 0fa5a7193..7bb5b052f 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/SAML2Utils.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/SAML2Utils.java @@ -1,6 +1,7 @@ package at.gv.egovernment.moa.id.protocols.pvp2x.utils; import java.io.IOException; +import java.security.NoSuchAlgorithmException; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; @@ -9,6 +10,7 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import org.opensaml.Configuration; +import org.opensaml.common.impl.SecureRandomIdentifierGenerator; import org.opensaml.saml2.core.Status; import org.opensaml.saml2.core.StatusCode; import org.opensaml.xml.XMLObject; @@ -36,6 +38,12 @@ public class SAML2Utils { } } + public static String getSecureIdentifier() { + return idGenerator.generateIdentifier(); + } + + private static SecureRandomIdentifierGenerator idGenerator; + private static DocumentBuilder builder; static { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); @@ -46,6 +54,11 @@ public class SAML2Utils { // TODO Auto-generated catch block e.printStackTrace(); } + try { + idGenerator = new SecureRandomIdentifierGenerator(); + } catch(NoSuchAlgorithmException e) { + e.printStackTrace(); + } } public static Document asDOMDocument(XMLObject object) throws IOException, diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/SAMLSignatureValidator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/SAMLSignatureValidator.java index df0fec001..3a6d15ef6 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/SAMLSignatureValidator.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/SAMLSignatureValidator.java @@ -6,7 +6,7 @@ import org.opensaml.security.SAMLSignatureProfileValidator; import org.opensaml.xml.validation.ValidationException; import at.gv.egovernment.moa.id.MOAIDException; -import at.gv.egovernment.moa.id.protocols.pvp2x.SAMLRequestNotSignedException; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SAMLRequestNotSignedException; public class SAMLSignatureValidator implements ISAMLValidator { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/EntityVerifier.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/EntityVerifier.java index 41e9b70cf..1233d8dab 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/EntityVerifier.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/EntityVerifier.java @@ -8,7 +8,7 @@ import org.opensaml.xml.signature.SignatureValidator; import org.opensaml.xml.validation.ValidationException; import at.gv.egovernment.moa.id.MOAIDException; -import at.gv.egovernment.moa.id.protocols.pvp2x.SAMLRequestNotSignedException; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SAMLRequestNotSignedException; import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider; public class EntityVerifier { -- cgit v1.2.3