/* * Copyright 2012 Juergen Groothues * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.groothues.mysaml.protocol.impl; import java.util.Map; import java.util.UUID; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.w3c.dom.Document; import org.w3c.dom.Node; import de.groothues.mysaml.SamlContext; import de.groothues.mysaml.impl.SamlContextAware; import de.groothues.mysaml.impl.DomHelper; import de.groothues.mysaml.protocol.ResponseBuilder; import de.groothues.mysaml.protocol.ResponseType; public class ResponseBuilderImpl extends SamlContextAware implements ResponseBuilder { public static final String PREFIX_XMLDSIG = "ds"; public static final String PREFIX_XMLENC = "xenc"; public static final String PREFIX_SAMLP = "samlp"; public ResponseBuilderImpl(SamlContext samlContext) { super(samlContext); } public Document build(Map<String, String> runtimeProperties) { ResponseType response = buildResponse(runtimeProperties); Document responseDoc = marshal(response); Document assertionDoc = buildAssertion(runtimeProperties); Node importedAssertion = responseDoc.importNode( assertionDoc.getDocumentElement(), true); responseDoc.getDocumentElement().appendChild(importedAssertion); return responseDoc; } @Override public Document marshal(ResponseType response) { try { Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.setProperty( Marshaller.JAXB_SCHEMA_LOCATION, "urn:oasis:names:tc:SAML:2.0:protocol saml-schema-protocol-2.0.xsd"); marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new com.sun.xml.bind.marshaller.NamespacePrefixMapper(){ public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) { if( "http://www.w3.org/2000/09/xmldsig#".equals(namespaceUri) ) { return PREFIX_XMLDSIG; } if( "http://www.w3.org/2001/04/xmlenc#".equals(namespaceUri) ) { return PREFIX_XMLENC; } if( "urn:oasis:names:tc:SAML:2.0:protocol".equals(namespaceUri) ) { return PREFIX_SAMLP; } return suggestion; } } ); JAXBElement<ResponseType> responseElement = getProtocolObjectFactory().createResponse(response); Document responseDoc = DomHelper.createNewDocument(); marshaller.marshal(responseElement, responseDoc); return responseDoc; } catch (Exception e) { throw new RuntimeException(e); } } @Override public ResponseType unmarshal(Document responseDoc) { try { Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); @SuppressWarnings("unchecked") JAXBElement<ResponseType> responseElement = (JAXBElement<ResponseType>)unmarshaller.unmarshal(responseDoc); return responseElement.getValue(); } catch (JAXBException e) { throw new RuntimeException(e); } } private ResponseType buildResponse(Map<String, String> runtimeProperties) { ResponseType response = getProtocolObjectFactory().createResponseType(); response.setVersion(getProperty(SAML_VERSION_KEY, runtimeProperties)); response.setID(UUID.randomUUID().toString()); response.setIssueInstant(createXmlCalendar()); return response; } private Document buildAssertion(Map<String, String> runtimeProperties) { return getSamlContext().getSignedAssertionBuilder().build(runtimeProperties); } }