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 = (uri1, uri2) -> { 047 if (uri1 == null && uri2 == null) { 048 return true; 049 } else if (uri1 == null || uri2 == null) { 050 return false; 051 } else { 052 String uri1Canon = SimpleURLCanonicalizer.canonicalize(uri1).replaceFirst("^(https:|http:)", ""); 053 String uri2Canon = SimpleURLCanonicalizer.canonicalize(uri2).replaceFirst("^(https:|http:)", ""); 054 return uri1Canon.equals(uri2Canon); 055 } 056 }; 057 058 public SAMLBinding(MessageDecoder decoder, MessageEncoder encoder) { 059 this.decoder = decoder; 060 this.encoder = encoder; 061 // NXP-17044: strips scheme to fix validity check with reverse proxies 062 if (decoder != null) { 063 ((BaseSAMLMessageDecoder) decoder).setURIComparator(uriComparator); 064 } 065 } 066 067 /** 068 * Decodes the given message. 069 * 070 * @param context the message to decode 071 */ 072 public void decode(MessageContext context) throws org.opensaml.xml.security.SecurityException, 073 MessageDecodingException { 074 decoder.decode(context); 075 } 076 077 /** 078 * Encodes the given message. 079 * 080 * @param context the message to encode 081 */ 082 public void encode(MessageContext context) throws MessageEncodingException { 083 encoder.encode(context); 084 } 085 086 /** 087 * Returns the URI that identifies this binding. 088 * 089 * @return the URI 090 */ 091 public abstract String getBindingURI(); 092 093 /** 094 * Checks if this binding can be used to extract the message from the request. 095 * 096 * @return true if this binding supports the transport 097 */ 098 public abstract boolean supports(InTransport transport); 099 100 /** 101 * Checks if this binding can use the given transport to send a message 102 * 103 * @return true if this binding supports the transport 104 */ 105 public abstract boolean supports(OutTransport transport); 106}