Forgot to actually create an instance of the security policy selector
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / idp / profile / AbstractSAMLProfileHandler.java
1 /*
2  * Copyright [2007] [University Corporation for Advanced Internet Development, Inc.]
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package edu.internet2.middleware.shibboleth.idp.profile;
18
19 import java.util.List;
20 import java.util.Map;
21
22 import javax.servlet.http.HttpServletRequest;
23
24 import org.opensaml.common.IdentifierGenerator;
25 import org.opensaml.common.binding.decoding.SAMLMessageDecoder;
26 import org.opensaml.common.binding.encoding.SAMLMessageEncoder;
27 import org.opensaml.saml2.metadata.Endpoint;
28 import org.opensaml.saml2.metadata.provider.MetadataProvider;
29 import org.opensaml.ws.message.encoder.MessageEncodingException;
30 import org.opensaml.ws.security.SecurityPolicyResolver;
31 import org.opensaml.ws.transport.InTransport;
32 import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import edu.internet2.middleware.shibboleth.common.log.AuditLogEntry;
37 import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
38 import edu.internet2.middleware.shibboleth.common.profile.provider.AbstractShibbolethProfileHandler;
39 import edu.internet2.middleware.shibboleth.common.profile.provider.BaseSAMLProfileRequestContext;
40 import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartySecurityPolicyResolver;
41 import edu.internet2.middleware.shibboleth.common.relyingparty.provider.SAMLMDRelyingPartyConfigurationManager;
42 import edu.internet2.middleware.shibboleth.idp.session.Session;
43
44 /**
45  * Base class for SAML profile handlers.
46  */
47 public abstract class AbstractSAMLProfileHandler extends
48         AbstractShibbolethProfileHandler<SAMLMDRelyingPartyConfigurationManager, Session> {
49
50     /** SAML message audit log. */
51     private final Logger auditLog = LoggerFactory.getLogger(AuditLogEntry.AUDIT_LOGGER_NAME);
52
53     /** Class logger. */
54     private final Logger log = LoggerFactory.getLogger(AbstractSAMLProfileHandler.class);
55
56     /** Generator of IDs which may be used for SAML assertions, requests, etc. */
57     private IdentifierGenerator idGenerator;
58
59     /** All the SAML message decoders configured for the IdP. */
60     private Map<String, SAMLMessageDecoder> messageDecoders;
61
62     /** All the SAML message encoders configured for the IdP. */
63     private Map<String, SAMLMessageEncoder> messageEncoders;
64
65     /** SAML message binding used by inbound messages. */
66     private String inboundBinding;
67
68     /** SAML message bindings that may be used by outbound messages. */
69     private List<String> supportedOutboundBindings;
70     
71     /** Resolver used to determine active security policy for an incoming request. */
72     private SecurityPolicyResolver securityPolicyResolver;
73
74     /** Constructor. */
75     protected AbstractSAMLProfileHandler() {
76         super();
77     }
78     
79     
80     /**
81      * Gets the resolver used to determine active security policy for an incoming request.
82      * 
83      * @return resolver used to determine active security policy for an incoming request
84      */
85     public SecurityPolicyResolver getSecurityPolicyResolver() {
86         if(securityPolicyResolver == null){
87             setSecurityPolicyResolver(new RelyingPartySecurityPolicyResolver(getRelyingPartyConfigurationManager()));
88         }
89         
90         return securityPolicyResolver;
91     }
92     
93     /**
94      * Sets the resolver used to determine active security policy for an incoming request.
95      * 
96      * @param resolver resolver used to determine active security policy for an incoming request
97      */
98     public void setSecurityPolicyResolver(SecurityPolicyResolver resolver) {
99         securityPolicyResolver = resolver;
100     }
101
102     /**
103      * Gets the audit log for this handler.
104      * 
105      * @return audit log for this handler
106      */
107     protected Logger getAduitLog() {
108         return auditLog;
109     }
110
111     /**
112      * Gets an ID generator which may be used for SAML assertions, requests, etc.
113      * 
114      * @return ID generator
115      */
116     public IdentifierGenerator getIdGenerator() {
117         return idGenerator;
118     }
119
120     /**
121      * Gets the SAML message binding used by inbound messages.
122      * 
123      * @return SAML message binding used by inbound messages
124      */
125     public String getInboundBinding() {
126         return inboundBinding;
127     }
128
129     /**
130      * Gets all the SAML message decoders configured for the IdP indexed by SAML binding URI.
131      * 
132      * @return SAML message decoders configured for the IdP indexed by SAML binding URI
133      */
134     public Map<String, SAMLMessageDecoder> getMessageDecoders() {
135         return messageDecoders;
136     }
137
138     /**
139      * Gets all the SAML message encoders configured for the IdP indexed by SAML binding URI.
140      * 
141      * @return SAML message encoders configured for the IdP indexed by SAML binding URI
142      */
143     public Map<String, SAMLMessageEncoder> getMessageEncoders() {
144         return messageEncoders;
145     }
146
147     /**
148      * A convenience method for retrieving the SAML metadata provider from the relying party manager.
149      * 
150      * @return the metadata provider or null
151      */
152     public MetadataProvider getMetadataProvider() {
153         SAMLMDRelyingPartyConfigurationManager rpcManager = getRelyingPartyConfigurationManager();
154         if (rpcManager != null) {
155             return rpcManager.getMetadataProvider();
156         }
157
158         return null;
159     }
160
161     /**
162      * Gets the SAML message bindings that may be used by outbound messages.
163      * 
164      * @return SAML message bindings that may be used by outbound messages
165      */
166     public List<String> getSupportedOutboundBindings() {
167         return supportedOutboundBindings;
168     }
169
170     /**
171      * Gets the user's session, if there is one.
172      * 
173      * @param inTransport current inbound transport
174      * 
175      * @return user's session
176      */
177     protected Session getUserSession(InTransport inTransport) {
178         String sessionId = getUserSessionId(inTransport);
179         return getSessionManager().getSession(sessionId);
180     }
181
182     /**
183      * Gets the user's session ID from the current request.
184      * 
185      * @param inTransport current inbound transport
186      * 
187      * @return user's session ID
188      */
189     protected String getUserSessionId(InTransport inTransport) {
190         HttpServletRequest rawRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
191
192         if (rawRequest != null) {
193             return (String) rawRequest.getSession().getAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE);
194         }
195
196         return null;
197     }
198
199     /**
200      * Gets an ID generator which may be used for SAML assertions, requests, etc.
201      * 
202      * @param generator an ID generator which may be used for SAML assertions, requests, etc
203      */
204     public void setIdGenerator(IdentifierGenerator generator) {
205         idGenerator = generator;
206     }
207
208     /**
209      * Sets the SAML message binding used by inbound messages.
210      * 
211      * @param binding SAML message binding used by inbound messages
212      */
213     public void setInboundBinding(String binding) {
214         inboundBinding = binding;
215     }
216
217     /**
218      * Sets all the SAML message decoders configured for the IdP indexed by SAML binding URI.
219      * 
220      * @param decoders SAML message decoders configured for the IdP indexed by SAML binding URI
221      */
222     public void setMessageDecoders(Map<String, SAMLMessageDecoder> decoders) {
223         messageDecoders = decoders;
224     }
225
226     /**
227      * Sets all the SAML message encoders configured for the IdP indexed by SAML binding URI.
228      * 
229      * @param encoders SAML message encoders configured for the IdP indexed by SAML binding URI
230      */
231     public void setMessageEncoders(Map<String, SAMLMessageEncoder> encoders) {
232         messageEncoders = encoders;
233     }
234
235     /**
236      * Sets the SAML message bindings that may be used by outbound messages.
237      * 
238      * @param bindings SAML message bindings that may be used by outbound messages
239      */
240     public void setSupportedOutboundBindings(List<String> bindings) {
241         supportedOutboundBindings = bindings;
242     }
243
244     /**
245      * Encodes the request's SAML response and writes it to the servlet response.
246      * 
247      * @param requestContext current request context
248      * 
249      * @throws ProfileException thrown if no message encoder is registered for this profiles binding
250      */
251     protected void encodeResponse(BaseSAMLProfileRequestContext requestContext) throws ProfileException {
252         try {
253             Endpoint peerEndpoint = requestContext.getPeerEntityEndpoint();
254             if (peerEndpoint == null) {
255                 log.error("No return endpoint available for relying party {}", requestContext
256                                 .getInboundMessageIssuer());
257                 throw new ProfileException("No peer endpoint available to which to send SAML response");
258             }
259
260             SAMLMessageEncoder encoder = getMessageEncoders().get(requestContext.getPeerEntityEndpoint().getBinding());
261             if (encoder == null) {
262                 log.error("No outbound message encoder configured for binding {}", requestContext
263                         .getPeerEntityEndpoint().getBinding());
264                 throw new ProfileException("No outbound message encoder configured for binding "
265                         + requestContext.getPeerEntityEndpoint().getBinding());
266             }
267             log.debug("Encoding response to SAML request {} from relying party {}", requestContext
268                     .getInboundSAMLMessageId(), requestContext.getInboundMessageIssuer());
269
270             requestContext.setMessageEncoder(encoder);
271             encoder.encode(requestContext);
272         } catch (MessageEncodingException e) {
273             throw new ProfileException("Unable to encode response to relying party: "
274                     + requestContext.getInboundMessageIssuer(), e);
275         }
276     }
277
278     /**
279      * Writes an aduit log entry indicating the successful response to the attribute request.
280      * 
281      * @param context current request context
282      */
283     protected void writeAuditLogEntry(BaseSAMLProfileRequestContext context) {
284         AuditLogEntry auditLogEntry = new AuditLogEntry();
285         auditLogEntry.setMessageProfile(getProfileId());
286         auditLogEntry.setPrincipalAuthenticationMethod(context.getPrincipalAuthenticationMethod());
287         auditLogEntry.setPrincipalName(context.getPrincipalName());
288         auditLogEntry.setAssertingPartyId(context.getLocalEntityId());
289         auditLogEntry.setRelyingPartyId(context.getInboundMessageIssuer());
290         auditLogEntry.setRequestBinding(context.getMessageDecoder().getBindingURI());
291         auditLogEntry.setRequestId(context.getInboundSAMLMessageId());
292         auditLogEntry.setResponseBinding(context.getMessageEncoder().getBindingURI());
293         auditLogEntry.setResponseId(context.getOutboundSAMLMessageId());
294         if (context.getReleasedAttributes() != null) {
295             auditLogEntry.getReleasedAttributes().addAll(context.getReleasedAttributes());
296         }
297
298         getAduitLog().info(auditLogEntry.toString());
299     }
300 }