package org.jboss.seam.security.external.saml.idp; import java.io.Reader; import java.io.Writer; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import javax.enterprise.inject.Instance; import javax.enterprise.inject.Typed; import javax.inject.Inject; import javax.servlet.http.HttpServletResponse; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import org.jboss.seam.security.external.SamlNameIdImpl; import org.jboss.seam.security.external.SamlPrincipalImpl; import org.jboss.seam.security.external.dialogues.api.Dialogued; import org.jboss.seam.security.external.jaxb.samlv2.assertion.AttributeType; import org.jboss.seam.security.external.jaxb.samlv2.metadata.EntityDescriptorType; import org.jboss.seam.security.external.jaxb.samlv2.metadata.IDPSSODescriptorType; import org.jboss.seam.security.external.jaxb.samlv2.metadata.IndexedEndpointType; import org.jboss.seam.security.external.jaxb.samlv2.metadata.ObjectFactory; import org.jboss.seam.security.external.jaxb.samlv2.metadata.SPSSODescriptorType; import org.jboss.seam.security.external.saml.SamlConstants; import org.jboss.seam.security.external.saml.SamlDialogue; import org.jboss.seam.security.external.saml.SamlEntityBean; import org.jboss.seam.security.external.saml.SamlExternalEntity; import org.jboss.seam.security.external.saml.SamlIdpOrSp; import org.jboss.seam.security.external.saml.SamlServiceType; import org.jboss.seam.security.external.saml.api.SamlIdpSession; import org.jboss.seam.security.external.saml.api.SamlNameId; import org.jboss.seam.security.external.saml.api.SamlPrincipal; /** * @author Marcel Kolsteren */ @Typed(SamlIdpBean.class) public class SamlIdpBean extends SamlEntityBean implements SamlIdpBeanApi { @Inject private SamlIdpSingleSignOnService samlIdpSingleSignOnService; @Inject private SamlIdpSingleLogoutService samlIdpSingleSignLogoutService; @Inject private SamlIdpSessions samlIdpSessions; private List<SamlExternalServiceProvider> serviceProviders = new LinkedList<SamlExternalServiceProvider>(); // No boolean assertionsSigned: the identity provider always signs the // assertions. private boolean wantAuthnRequestsSigned = false; @Inject private Instance<SamlDialogue> samlDialogue; public List<SamlExternalServiceProvider> getServiceProviders() { return serviceProviders; } public SamlExternalServiceProvider addExternalServiceProvider(String entityId, SPSSODescriptorType spSsoDescriptor) { SamlExternalServiceProvider samlServiceProvider = new SamlExternalServiceProvider(entityId, spSsoDescriptor); serviceProviders.add(samlServiceProvider); return samlServiceProvider; } public SamlExternalServiceProvider addExternalSamlEntity(Reader reader) { EntityDescriptorType entityDescriptor = readEntityDescriptor(reader); String entityId = entityDescriptor.getEntityID(); SPSSODescriptorType SPSSODescriptor = (SPSSODescriptorType) entityDescriptor.getRoleDescriptorOrIDPSSODescriptorOrSPSSODescriptor().get(0); return addExternalServiceProvider(entityId, SPSSODescriptor); } @Override public List<SamlExternalEntity> getExternalSamlEntities() { List<SamlExternalEntity> samlEntities = new LinkedList<SamlExternalEntity>(); for (SamlExternalServiceProvider sp : serviceProviders) { samlEntities.add(sp); } return samlEntities; } public boolean isWantAuthnRequestsSigned() { return wantAuthnRequestsSigned; } public void setWantAuthnRequestsSigned(boolean wantAuthnRequestsSigned) { this.wantAuthnRequestsSigned = wantAuthnRequestsSigned; } public SamlExternalServiceProvider getExternalSamlEntityByEntityId(String entityId) { for (SamlExternalServiceProvider serviceProvider : serviceProviders) { if (serviceProvider.getEntityId().equals(entityId)) { return serviceProvider; } } return null; } public void writeMetaData(Writer writer) { try { ObjectFactory metaDataFactory = new ObjectFactory(); IndexedEndpointType ssoRedirectEndpoint = metaDataFactory.createIndexedEndpointType(); ssoRedirectEndpoint.setBinding(SamlConstants.HTTP_REDIRECT_BINDING); ssoRedirectEndpoint.setLocation(getServiceURL(SamlServiceType.SAML_SINGLE_SIGN_ON_SERVICE)); IndexedEndpointType ssoPostEndpoint = metaDataFactory.createIndexedEndpointType(); ssoPostEndpoint.setBinding(SamlConstants.HTTP_POST_BINDING); ssoPostEndpoint.setLocation(getServiceURL(SamlServiceType.SAML_SINGLE_SIGN_ON_SERVICE)); IDPSSODescriptorType idpSsoDescriptor = metaDataFactory.createIDPSSODescriptorType(); idpSsoDescriptor.getSingleSignOnService().add(ssoRedirectEndpoint); idpSsoDescriptor.getSingleSignOnService().add(ssoPostEndpoint); addSloEndpointsToMetaData(idpSsoDescriptor); idpSsoDescriptor.setWantAuthnRequestsSigned(isWantAuthnRequestsSigned()); idpSsoDescriptor.getProtocolSupportEnumeration().add(SamlConstants.PROTOCOL_NSURI); addNameIDFormatsToMetaData(idpSsoDescriptor); addKeyDescriptorToMetaData(idpSsoDescriptor); EntityDescriptorType entityDescriptor = metaDataFactory.createEntityDescriptorType(); entityDescriptor.setEntityID(getEntityId()); entityDescriptor.getRoleDescriptorOrIDPSSODescriptorOrSPSSODescriptor().add(idpSsoDescriptor); Marshaller marshaller = metaDataJaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshaller.marshal(metaDataFactory.createEntityDescriptor(entityDescriptor), writer); } catch (JAXBException e) { throw new RuntimeException(e); } } @Dialogued(join = true) public void authenticationSucceeded(SamlIdpSession session, HttpServletResponse response) { session.getServiceProviders().add((SamlExternalServiceProvider) samlDialogue.get().getExternalProvider()); samlIdpSingleSignOnService.handleSucceededAuthentication(session, response); } @Dialogued(join = true) public void authenticationFailed(HttpServletResponse response) { samlIdpSingleSignOnService.handleFailedAuthentication(response); } public Set<SamlIdpSession> getSessions() { Set<SamlIdpSession> sessions = new HashSet<SamlIdpSession>(); sessions.addAll(samlIdpSessions.getSessions()); return sessions; } public SamlIdpSession localLogin(SamlNameId nameId, List<AttributeType> attributes) { return createSession(nameId, attributes); } public SamlNameId createNameId(String value, String format, String qualifier) { return new SamlNameIdImpl(value, format, qualifier); } private SamlIdpSession createSession(SamlNameId nameId, List<AttributeType> attributes) { SamlPrincipalImpl samlPrincipal = new SamlPrincipalImpl(); samlPrincipal.setNameId(nameId); if (attributes != null) { samlPrincipal.setAttributes(attributes); } else { samlPrincipal.setAttributes(new LinkedList<AttributeType>()); } return samlIdpSessions.addSession(samlPrincipal); } @Dialogued(join = true) public void remoteLogin(String spEntityId, SamlIdpSession session, String remoteUrl, HttpServletResponse response) { for (SamlExternalServiceProvider sp : session.getServiceProviders()) { if (sp.getEntityId().equals(spEntityId)) { throw new RuntimeException("Service provider " + spEntityId + " is already a session participant."); } } session.getServiceProviders().add(getExternalSamlEntityByEntityId(spEntityId)); samlIdpSingleSignOnService.remoteLogin(spEntityId, session, remoteUrl, response); } public void localLogout(SamlIdpSession session) { samlIdpSessions.removeSession((SamlIdpSessionImpl) session); } @Dialogued(join = true) public void globalLogout(SamlIdpSession session, HttpServletResponse response) { SamlPrincipal principal = session.getPrincipal(); samlIdpSingleSignLogoutService.handleIDPInitiatedSingleLogout(principal, Arrays.asList(((SamlIdpSessionImpl) session).getSessionIndex()), response); } @Override public SamlIdpOrSp getIdpOrSp() { return SamlIdpOrSp.IDP; } }