001/*
002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Nelson Silva <nelson.silva@inevo.pt>
018 */
019package org.nuxeo.ecm.platform.auth.saml.binding;
020
021import org.opensaml.common.binding.decoding.BaseSAMLMessageDecoder;
022import org.opensaml.common.binding.decoding.URIComparator;
023import org.opensaml.util.SimpleURLCanonicalizer;
024import org.opensaml.ws.message.MessageContext;
025import org.opensaml.ws.message.decoder.MessageDecoder;
026import org.opensaml.ws.message.decoder.MessageDecodingException;
027import org.opensaml.ws.message.encoder.MessageEncoder;
028import org.opensaml.ws.message.encoder.MessageEncodingException;
029import org.opensaml.ws.transport.InTransport;
030import org.opensaml.ws.transport.OutTransport;
031
032/**
033 * Based class for SAML bindings, used for parsing messages.
034 *
035 * @since 6.0
036 */
037public abstract class SAMLBinding {
038
039    protected MessageDecoder decoder;
040
041    protected MessageEncoder encoder;
042
043    /**
044     * URIComparator that strips scheme to avoid issues with reverse proxies
045     */
046    public static final URIComparator uriComparator = new URIComparator() {
047        @Override
048        public boolean compare(String uri1, String uri2) {
049            if (uri1 == null && uri2 == null) {
050                return true;
051            } else if (uri1 == null || uri2 == null) {
052                return false;
053            } else {
054                String uri1Canon = SimpleURLCanonicalizer.canonicalize(uri1).replaceFirst("^(https:|http:)", "");
055                String uri2Canon = SimpleURLCanonicalizer.canonicalize(uri2).replaceFirst("^(https:|http:)", "");
056                return uri1Canon.equals(uri2Canon);
057            }
058        }
059    };
060
061    public SAMLBinding(MessageDecoder decoder, MessageEncoder encoder) {
062        this.decoder = decoder;
063        this.encoder = encoder;
064        // NXP-17044: strips scheme to fix validity check with reverse proxies
065        if (decoder != null) {
066            ((BaseSAMLMessageDecoder) decoder).setURIComparator(uriComparator);
067        }
068    }
069
070    /**
071     * Decodes the given message.
072     *
073     * @param context the message to decode
074     * @throws org.opensaml.xml.security.SecurityException
075     * @throws MessageDecodingException
076     */
077    public void decode(MessageContext context) throws org.opensaml.xml.security.SecurityException,
078            MessageDecodingException {
079        decoder.decode(context);
080    }
081
082    /**
083     * Encodes the given message.
084     *
085     * @param context the message to encode
086     * @throws MessageEncodingException
087     */
088    public void encode(MessageContext context) throws MessageEncodingException {
089        encoder.encode(context);
090    }
091
092    /**
093     * Returns the URI that identifies this binding.
094     *
095     * @return the URI
096     */
097    public abstract String getBindingURI();
098
099    /**
100     * Checks if this binding can be used to extract the message from the request.
101     *
102     * @param transport
103     * @return true if this binding supports the transport
104     */
105    public abstract boolean supports(InTransport transport);
106
107    /**
108     * Checks if this binding can use the given transport to send a message
109     *
110     * @param transport
111     * @return true if this binding supports the transport
112     */
113    public abstract boolean supports(OutTransport transport);
114}