fixes for saml 2 authnreq
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / idp / profile / saml2 / AuthenticationRequestBrowserPost.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.saml2;
18
19 import javax.servlet.ServletRequest;
20 import javax.servlet.ServletResponse;
21 import javax.servlet.http.HttpServletRequest;
22 import javax.servlet.http.HttpServletResponse;
23 import javax.servlet.http.HttpSession;
24 import javax.servlet.ServletException;
25
26 import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
27 import edu.internet2.middleware.shibboleth.common.profile.ProfileRequest;
28 import edu.internet2.middleware.shibboleth.common.profile.ProfileResponse;
29 import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfiguration;
30 import edu.internet2.middleware.shibboleth.common.relyingparty.saml2.SSOConfiguration;
31
32 import org.apache.log4j.Logger;
33 import org.opensaml.common.SAMLObject;
34 import org.opensaml.common.binding.BindingException;
35 import org.opensaml.common.binding.MessageDecoder;
36 import org.opensaml.saml2.core.AuthnRequest;
37 import org.opensaml.saml2.core.Issuer;
38 import org.opensaml.saml2.core.Response;
39 import org.opensaml.saml2.binding.HTTPPostDecoder;
40 import org.opensaml.saml2.metadata.SPSSODescriptor;
41
42 /**
43  * Browser POST binding for SAML 2 AuthenticationRequest.
44  */
45 public class AuthenticationRequestBrowserPost extends
46                 AbstractAuthenticationRequest {
47
48         /** Class logger. */
49         private static final Logger log = Logger
50                         .getLogger(AuthenticationRequestBrowserPost.class);
51
52         /** Constructor. */
53         public AuthenticationRequestBrowserPost() {
54                 super();
55         }
56
57         /** {@inheritDoc} */
58         public void processRequest(final ProfileRequest<ServletRequest> request,
59                         final ProfileResponse<ServletResponse> response)
60                         throws ProfileException {
61
62                 // Only http servlets are supported for now.
63                 if (!(request.getRawRequest() instanceof HttpServletRequest)) {
64                         log.error("Received a non-HTTP request");
65                         throw new ServletException("Received a non-HTTP request");
66                 }
67
68                 HttpServletRequest httpReq = (HttpServletRequest) request
69                                 .getRawRequest();
70                 HttpServletResponse httpResp = (HttpServletResponse) response
71                                 .getRawResponse();
72                 HttpSession httpSession = httpReq.getSession();
73
74                 AuthnRequest authnRequest;
75                 Issuer issuer;
76                 RelyingPartyConfiguration relyingParty;
77                 SSOConfiguration ssoConfig;
78                 SPSSODescriptor spDescriptor;
79
80                 // If the user hasn't been authenticated, validate the AuthnRequest
81                 // and redirect to AuthenticationManager to authenticate the user.
82                 if (!hasUserAuthenticated(httpSession)) {
83
84                         try {
85                                 MessageDecoder decoder = new HTTPPostDecoder();
86                                 decoder
87                                                 .setMetadataProvider(getRelyingPartyConfigurationManager()
88                                                                 .getMetadataProvider());
89                                 // decoder.setSecurityPolicy(??);
90                                 // decoder.setTrustEngine(??);
91                                 decoder.setRequest(httpReq);
92                                 decoder.decode();
93                                 SAMLObject samlObject = decoder.getSAMLMessage();
94                                 if (!(samlObject instanceof AuthnRequest)) {
95                                         log
96                                                         .error("SAML 2 AuthnRequest: Received message is not a SAML 2 Authentication Request");
97                                         throw new ProfileException(
98                                                         "SAML 2 AuthnRequest: Received message is not a SAML 2 Authentication Request");
99                                 }
100
101                                 authnRequest = (AuthnRequest) samlObject;
102                                 issuer = decoder.getSecurityPolicy().getIssuer();
103
104                                 if (!findMetadataForSSORequest(issuer, relyingParty, ssoConfig,
105                                                 spDescriptor)) {
106                                         throw new ProfileException(
107                                                         "SAML 2 AuthnRequest: Unable to locate metadata for issuer: "
108                                                                         + issuer.getSPProvidedID());
109                                 }
110
111                                 verifyAuthnRequest(authnRequest, issuer, relyingParty,
112                                                 httpSession);
113                                 storeRequestData(httpSession, authnRequest, issuer,
114                                                 relyingParty, ssoConfig, spDescriptor);
115                                 authenticateUser(authnRequest, httpSession, httpReq, httpResp);
116
117                         } catch (BindingException ex) {
118                                 log
119                                                 .error(
120                                                                 "SAML 2 Authentication Request: Unable to decode SAML 2 Authenticaiton Request",
121                                                                 ex);
122                                 throw new ProfileException(
123                                                 "SAML 2 Authentication Request: Unable to decode SAML 2 Authenticaiton Request",
124                                                 ex);
125                         } catch (AuthenticationRequestException ex) {
126                                 // XXX: todo: generate and send the error, with a REQUEST_URI
127                                 // failure.
128                         }
129                 }
130
131                 // The user has already been authenticated,
132                 // so generate an AuthenticationStatement.
133                 retrieveRequestData(httpSession, authnRequest, issuer, relyingParty,
134                                 ssoConfig, spDescriptor);
135                 Response samlResponse = evaluateRequest(authnRequest, issuer,
136                                 httpSession, relyingParty, ssoConfig, spDescriptor);
137                 encodeResponse(response, samlResponse, relyingParty, ssoConfig,
138                                 spDescriptor);
139         }
140
141         protected void encodeResponse(final ProfileResponse response,
142                         final Response samlResponse,
143                         final RelyingPartyConfiguration relyingParty,
144                         final SSOConfiguration ssoConfig, final SPSSODescriptor spDescriptor) {
145                 // xxx: todo
146         }
147 }