fr.mby.saml2.sp.impl.config.BasicIdpConfig.java Source code

Java tutorial

Introduction

Here is the source code for fr.mby.saml2.sp.impl.config.BasicIdpConfig.java

Source

/**
 * Copyright (C) 2012 RECIA http://www.recia.fr
 * @Author (C) 2012 Maxime Bossard <mxbossard@gmail.com>
 *
 * 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 fr.mby.saml2.sp.impl.config;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.opensaml.DefaultBootstrap;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.IDPSSODescriptor;
import org.opensaml.saml2.metadata.SingleLogoutService;
import org.opensaml.saml2.metadata.SingleSignOnService;
import org.opensaml.saml2.metadata.provider.MetadataProvider;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
import org.opensaml.security.MetadataCredentialResolver;
import org.opensaml.xml.Configuration;
import org.opensaml.xml.ConfigurationException;
import org.opensaml.xml.parse.XMLParserException;
import org.opensaml.xml.security.keyinfo.KeyInfoCredentialResolver;
import org.opensaml.xml.signature.SignatureTrustEngine;
import org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import fr.mby.saml2.sp.api.config.IIdpConfig;
import fr.mby.saml2.sp.api.config.IWayfConfig;
import fr.mby.saml2.sp.api.core.ISaml20IdpConnector;
import fr.mby.saml2.sp.api.core.SamlBindingEnum;
import fr.mby.saml2.sp.opensaml.helper.OpenSamlHelper;

/**
 * This implementation retrieve the current HTTP Request from Spring webflow context.
 * 
 * @author GIP RECIA 2012 - Maxime BOSSARD.
 * 
 */
public class BasicIdpConfig implements IIdpConfig, InitializingBean {

    /** Logger. */
    private static final Logger LOGGER = LoggerFactory.getLogger(BasicIdpConfig.class);

    /** SVUID. */
    private static final long serialVersionUID = -3392368326559269830L;

    /** IdP config id. */
    private String id;

    /** IdP connector. */
    private transient ISaml20IdpConnector saml20IdpConnector;

    /** IdP description. */
    private String description;

    /** IdP picture URL. */
    private String pictureUrl;

    /** Force IdP authentication. */
    private boolean forceAuthentication = true;

    /** Time window in ms durint which the request are valids (by default 300000ms means requests are valid +-300000ms). */
    private long timeValidityWindow = 300000;

    /** Response binding wanted. Default HTTP-POST. */
    private SamlBindingEnum responseBinding = SamlBindingEnum.SAML_20_HTTP_POST;

    /** Request binding wanted. Default HTTP-Redirect. */
    private SamlBindingEnum requestBinding = SamlBindingEnum.SAML_20_HTTP_REDIRECT;

    /** The index of Attribute consuming service wanted. */
    private Integer attributeConsumingServiceIndex = 1;

    /** IdP entity ID (same in metadata file). */
    private String idpEntityId;

    /** Used to verify signature responses and encrypt assertions. */
    private transient Resource idpMetadata;

    /** IdP metadata provider. */
    private transient MetadataProvider idpMetadataProvider;

    /** Verify the IdP Signatures via metadata. */
    private transient SignatureTrustEngine signatureTrustEngine;

    /** IdP Endpoints URL for SSO. */
    private final Map<SamlBindingEnum, String> idpSsoEndpointUrl = new HashMap<SamlBindingEnum, String>();

    /** Idp endpoints URL for Single Logout. */
    private final Map<SamlBindingEnum, String> idpSloEndpointUrl = new HashMap<SamlBindingEnum, String>();

    /** Global Wayf Config. */
    private IWayfConfig wayfConfig;

    @Override
    public String getIdpSsoEndpointUrl(final SamlBindingEnum binding) {
        return this.idpSsoEndpointUrl.get(binding);
    }

    @Override
    public String getIdpSloEndpointUrl(final SamlBindingEnum binding) {
        return this.idpSloEndpointUrl.get(binding);
    }

    /**
     * Build a signature trust engine based on a metadata provider.
     * 
     * @param metadataProvider
     *            the metadata provider
     * @return the signature trust engine
     */
    protected SignatureTrustEngine buildSignatureTrustEngine(final MetadataProvider metadataProvider) {
        SignatureTrustEngine signatureTrustEngine = null;

        if (metadataProvider != null) {
            final MetadataCredentialResolver mdCredResolver = new MetadataCredentialResolver(metadataProvider);
            final KeyInfoCredentialResolver keyInfoCredResolver = Configuration.getGlobalSecurityConfiguration()
                    .getDefaultKeyInfoCredentialResolver();
            signatureTrustEngine = new ExplicitKeySignatureTrustEngine(mdCredResolver, keyInfoCredResolver);
        }

        return signatureTrustEngine;
    }

    /**
     * Process IdP metadatas.
     * 
     * @throws MetadataProviderException
     * @throws XMLParserException
     * @throws ConfigurationException
     */
    protected void processIdpMetadata()
            throws MetadataProviderException, XMLParserException, ConfigurationException {
        BasicIdpConfig.LOGGER.debug("Precessing metadata of IdP with Id: [{}]...", this.id);

        DefaultBootstrap.bootstrap();

        this.idpMetadataProvider = OpenSamlHelper.buildMetadataProvider(this.idpMetadata);
        Assert.notNull(this.idpMetadataProvider, "IdP metadata provider wasn't build !");
        BasicIdpConfig.LOGGER.debug("IdP metadata provider ref: [{}].", this.idpMetadataProvider);

        this.signatureTrustEngine = this.buildSignatureTrustEngine(this.idpMetadataProvider);
        Assert.notNull(this.signatureTrustEngine, "Signature trust engine wasn't build !");
        BasicIdpConfig.LOGGER.debug("IdP signature trust engine ref: [{}].", this.signatureTrustEngine);

        final EntityDescriptor idpEntityDescriptor = this.idpMetadataProvider.getEntityDescriptor(this.idpEntityId);
        Assert.notNull(idpEntityDescriptor, String
                .format("No entity descriptor found in IdP metadata for IdP entityId [%s]", this.idpEntityId));
        BasicIdpConfig.LOGGER.debug("IdP entity descriptor ref: [{}].", idpEntityDescriptor);

        final IDPSSODescriptor ssoDescriptors = idpEntityDescriptor.getIDPSSODescriptor(SAMLConstants.SAML20P_NS);
        if (ssoDescriptors != null) {
            // Retrieve SSO endpoints URL.
            final List<SingleSignOnService> ssoServices = ssoDescriptors.getSingleSignOnServices();
            if (!CollectionUtils.isEmpty(ssoServices)) {
                for (final SingleSignOnService ssoService : ssoServices) {
                    if ((ssoService != null)) {
                        final SamlBindingEnum binding = SamlBindingEnum.fromSamlUri(ssoService.getBinding());
                        if (binding != null) {
                            this.idpSsoEndpointUrl.put(binding, ssoService.getLocation());
                        }
                    }
                }
            }

            // Retrieve Single Logout endpoints URL.
            final List<SingleLogoutService> slServices = ssoDescriptors.getSingleLogoutServices();
            if (!CollectionUtils.isEmpty(slServices)) {
                for (final SingleLogoutService slService : slServices) {
                    if ((slService != null)) {
                        final SamlBindingEnum binding = SamlBindingEnum.fromSamlUri(slService.getBinding());
                        if (binding != null) {
                            this.idpSloEndpointUrl.put(binding, slService.getLocation());
                        }
                    }
                }
            }
        }

        for (final SamlBindingEnum binding : SamlBindingEnum.values()) {
            if (!StringUtils.hasText(this.idpSsoEndpointUrl.get(binding))) {
                BasicIdpConfig.LOGGER
                        .warn(String.format("No SSO %s endpoint URL found in metadata for the [%s] IdP connector !",
                                binding.getDescription(), this.getIdpEntityId()));
            }
            ;
        }

        for (final SamlBindingEnum binding : SamlBindingEnum.values()) {
            if (!StringUtils.hasText(this.idpSloEndpointUrl.get(binding))) {
                BasicIdpConfig.LOGGER
                        .warn(String.format("No SLO %s endpoint URL found in metadata for the [%s] IdP connector !",
                                binding.getDescription(), this.getIdpEntityId()));
            }
        }

        BasicIdpConfig.LOGGER.debug("IdP registered SSO endpoint URL: [{}]", this.idpSsoEndpointUrl);
        BasicIdpConfig.LOGGER.debug("IdP registered SLO endpoint URL: [{}]", this.idpSloEndpointUrl);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(this.id, "No id provided for this IdP config !");
        Assert.isTrue(StringUtils.hasText(this.idpEntityId),
                String.format("No IdP EntityId provided for IdP config with id [%s] !", this.id));

        Assert.isTrue((this.idpMetadata != null) && this.idpMetadata.exists(),
                String.format("No IdP metadata provided for IdP config with id [%s]!", this.id));

        this.processIdpMetadata();
    }

    @Override
    public ISaml20IdpConnector getSaml20IdpConnector() {
        return this.saml20IdpConnector;
    }

    @Override
    public void registerSaml20IdpConnector(final ISaml20IdpConnector saml20IdpConnector) {
        this.saml20IdpConnector = saml20IdpConnector;
    }

    @Override
    public SignatureTrustEngine getSignatureTrustEngine() {
        return this.signatureTrustEngine;
    }

    @Override
    public String getId() {
        return this.id;
    }

    public void setId(final String id) {
        this.id = id;
    }

    @Override
    public String getDescription() {
        return this.description;
    }

    public void setDescription(final String description) {
        this.description = description;
    }

    @Override
    public String getPictureUrl() {
        return this.pictureUrl;
    }

    public void setPictureUrl(final String pictureUrl) {
        this.pictureUrl = pictureUrl;
    }

    @Override
    public IWayfConfig getWayfConfig() {
        return this.wayfConfig;
    }

    @Override
    public void registerWayfConfig(final IWayfConfig wayfConfig) {
        this.wayfConfig = wayfConfig;
    }

    @Override
    public Integer getAttributeConsumingServiceIndex() {
        return this.attributeConsumingServiceIndex;
    }

    public void setAttributeConsumingServiceIndex(final Integer attributeConsumingServiceIndex) {
        this.attributeConsumingServiceIndex = attributeConsumingServiceIndex;
    }

    @Override
    public boolean isForceAuthentication() {
        return this.forceAuthentication;
    }

    public void setForceAuthentication(final boolean forceAuthentication) {
        this.forceAuthentication = forceAuthentication;
    }

    @Override
    public SamlBindingEnum getResponseBinding() {
        return this.responseBinding;
    }

    public void setResponseBinding(final SamlBindingEnum responseBinding) {
        this.responseBinding = responseBinding;
    }

    @Override
    public SamlBindingEnum getRequestBinding() {
        return this.requestBinding;
    }

    public void setRequestBinding(final SamlBindingEnum requestBinding) {
        this.requestBinding = requestBinding;
    }

    @Override
    public long getTimeValidityWindow() {
        return this.timeValidityWindow;
    }

    /**
     * Time window in ms durint which the request are valids (by default 300000ms means requests are valid +-300000ms).
     * 
     * @param timeValidityWindow
     *            the time validity window
     */
    public void setTimeValidityWindow(final long timeValidityWindow) {
        this.timeValidityWindow = timeValidityWindow;
    }

    @Override
    public String getIdpEntityId() {
        return this.idpEntityId;
    }

    public void setIdpEntityId(final String idpEntityId) {
        this.idpEntityId = idpEntityId;
    }

    @Override
    public Resource getIdpMetadata() {
        return this.idpMetadata;
    }

    public void setIdpMetadata(final Resource idpMetadata) {
        this.idpMetadata = idpMetadata;
    }

}