Create parser pool interface and move current pool to an implementation of this inter...
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / idp / provider / SSOHandler.java
1 /*
2  * Copyright [2005] [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.provider;
18
19 import java.text.ParseException;
20 import java.text.SimpleDateFormat;
21 import java.util.Date;
22 import java.util.List;
23
24 import javax.servlet.http.HttpServletRequest;
25
26 import org.apache.log4j.Logger;
27 import org.opensaml.SAMLException;
28 import org.opensaml.SAMLNameIdentifier;
29 import org.opensaml.saml2.metadata.EntityDescriptor;
30 import org.opensaml.saml2.metadata.NameIDFormat;
31 import org.opensaml.saml2.metadata.SPSSODescriptor;
32 import org.w3c.dom.Element;
33
34 import edu.internet2.middleware.shibboleth.common.LocalPrincipal;
35 import edu.internet2.middleware.shibboleth.common.NameIdentifierMapping;
36 import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException;
37 import edu.internet2.middleware.shibboleth.common.NameMapper;
38 import edu.internet2.middleware.shibboleth.common.RelyingParty;
39 import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
40 import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
41 import edu.internet2.middleware.shibboleth.idp.InvalidClientDataException;
42
43 /**
44  * @author Walter Hoehn
45  */
46 public abstract class SSOHandler extends BaseHandler implements IdPProtocolHandler {
47
48         private static Logger log = Logger.getLogger(BaseHandler.class.getName());
49
50         /**
51          * Required DOM-based constructor.
52          */
53         public SSOHandler(Element config) throws ShibbolethConfigurationException {
54
55                 super(config);
56
57         }
58
59         public static void validateEngineData(HttpServletRequest req) throws InvalidClientDataException {
60
61                 if ((req.getRemoteAddr() == null) || (req.getRemoteAddr().equals(""))) { throw new InvalidClientDataException(
62                                 "Unable to obtain client address."); }
63         }
64
65         protected Date getAuthNTime(HttpServletRequest request) throws SAMLException {
66
67                 // Determine, if possible, when the authentication actually happened
68                 String suppliedAuthNInstant = request.getHeader("SAMLAuthenticationInstant");
69                 if (suppliedAuthNInstant != null && !suppliedAuthNInstant.equals("")) {
70                         try {
71                                 return new SimpleDateFormat().parse(suppliedAuthNInstant);
72                         } catch (ParseException e) {
73                                 log.error("An error was encountered while receiving authentication "
74                                                 + "instant from authentication mechanism: " + e);
75                                 throw new SAMLException(SAMLException.RESPONDER, "General error processing request.");
76                         }
77                 } else {
78                         return new Date(System.currentTimeMillis());
79                 }
80         }
81
82         /**
83          * Constructs a SAML Name Identifier of a given principal that is most appropriate to the relying party.
84          * 
85          * @param mapper
86          *            name mapping facility
87          * @param principal
88          *            the principal represented by the name identifier
89          * @param relyingParty
90          *            the party that will consume the name identifier
91          * @param descriptor
92          *            metadata descriptor for the party that will consume the name identifier
93          * @return the SAML Name identifier
94          * @throws NameIdentifierMappingException
95          *             if a name identifier could not be created
96          */
97         protected SAMLNameIdentifier getNameIdentifier(NameMapper mapper, LocalPrincipal principal,
98                         RelyingParty relyingParty, EntityDescriptor descriptor) throws NameIdentifierMappingException {
99
100                 String[] availableMappings = relyingParty.getNameMapperIds();
101
102                 // If we have preferred Name Identifier formats from the metadata, see if the we can find one that is configured
103                 // for this relying party
104                 SPSSODescriptor role;
105                 if (descriptor != null && (role = descriptor.getSPSSODescriptor(org.opensaml.XML.SAML11_PROTOCOL_ENUM)) != null) {
106                         List<NameIDFormat> spPreferredFormats = role.getNameIDFormats();
107                         for (NameIDFormat preferredFormat : spPreferredFormats) {
108                                 for (int i = 0; availableMappings != null && i < availableMappings.length; i++) {
109                                         NameIdentifierMapping mapping = mapper.getNameIdentifierMappingById(availableMappings[i]);
110                                         if (mapping != null
111                                                         && preferredFormat.getFormat().equals(mapping.getNameIdentifierFormat().toString())) {
112                                                 log.debug("Found a supported name identifier format that "
113                                                                 + "matches the metadata for the relying party: ("
114                                                                 + mapping.getNameIdentifierFormat().toString() + ").");
115                                                 return mapping.getNameIdentifier(principal, relyingParty, relyingParty.getIdentityProvider());
116                                         }
117                                 }
118                         }
119                 }
120
121                 // If we didn't find any matches, then just use the default for the relying party
122                 String defaultNameMapping = null;
123                 if (availableMappings != null && availableMappings.length > 0) {
124                         defaultNameMapping = availableMappings[0];
125                 }
126                 SAMLNameIdentifier nameId = mapper.getNameIdentifier(defaultNameMapping, principal, relyingParty, relyingParty
127                                 .getIdentityProvider());
128                 log.debug("Using the default name identifier format for this relying party: (" + nameId.getFormat() + ").");
129                 return nameId;
130         }
131 }