1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.servlet.filters.sso.opensso;
24  
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.util.StringPool;
28  import com.liferay.portal.kernel.util.StringUtil;
29  import com.liferay.util.CookieUtil;
30  
31  import java.io.BufferedReader;
32  import java.io.IOException;
33  import java.io.InputStream;
34  import java.io.InputStreamReader;
35  import java.io.OutputStreamWriter;
36  
37  import java.net.HttpURLConnection;
38  import java.net.MalformedURLException;
39  import java.net.URL;
40  
41  import java.util.ArrayList;
42  import java.util.HashMap;
43  import java.util.List;
44  import java.util.Map;
45  import java.util.concurrent.ConcurrentHashMap;
46  
47  import javax.servlet.http.HttpServletRequest;
48  
49  /**
50   * <a href="OpenSSOUtil.java.html"><b><i>View Source</i></b></a>
51   *
52   * <p>
53   * See http://support.liferay.com/browse/LEP-5943.
54   * </p>
55   *
56   * @author Prashant Dighe
57   * @author Brian Wing Shun Chan
58   */
59  public class OpenSSOUtil {
60  
61      public static Map<String, String> getAttributes(
62          HttpServletRequest request, String serviceUrl) {
63  
64          return _instance._getAttributes(request, serviceUrl);
65      }
66  
67      public static String getSubjectId(
68          HttpServletRequest request, String serviceUrl) {
69  
70          return _instance._getSubjectId(request, serviceUrl);
71      }
72  
73      public static boolean isAuthenticated(
74              HttpServletRequest request, String serviceUrl)
75          throws IOException {
76  
77          return _instance._isAuthenticated(request, serviceUrl);
78      }
79  
80      private OpenSSOUtil() {
81      }
82  
83      private Map<String, String> _getAttributes(
84          HttpServletRequest request, String serviceUrl) {
85  
86          Map<String, String> nameValues = new HashMap<String, String>();
87  
88          String url = serviceUrl + _GET_ATTRIBUTES;
89  
90          try {
91              URL urlObj = new URL(url);
92  
93              HttpURLConnection urlc = (HttpURLConnection)urlObj.openConnection();
94  
95              urlc.setDoOutput(true);
96              urlc.setRequestMethod("POST");
97              urlc.setRequestProperty(
98                  "Content-type", "application/x-www-form-urlencoded");
99  
100             String[] cookieNames = _getCookieNames(serviceUrl);
101 
102             _setCookieProperty(request, urlc, cookieNames);
103 
104             OutputStreamWriter osw = new OutputStreamWriter(
105                 urlc.getOutputStream());
106 
107             osw.write("dummy");
108 
109             osw.flush();
110 
111             int responseCode = urlc.getResponseCode();
112 
113             if (responseCode == HttpURLConnection.HTTP_OK) {
114                 BufferedReader br = new BufferedReader(
115                     new InputStreamReader((InputStream)urlc.getContent()));
116 
117                 String line = null;
118 
119                 while ((line = br.readLine()) != null) {
120                     if (line.startsWith("userdetails.attribute.name=")) {
121                         String name = line.replaceFirst(
122                             "userdetails.attribute.name=", "");
123 
124                         line = br.readLine();
125 
126                         if (line.startsWith("userdetails.attribute.value=")) {
127                             String value = line.replaceFirst(
128                                 "userdetails.attribute.value=", "");
129 
130                             nameValues.put(name, value);
131                         }
132                     }
133                 }
134             }
135             else if (_log.isDebugEnabled()) {
136                 _log.debug("Attributes response code " + responseCode);
137             }
138         }
139         catch (MalformedURLException mfue) {
140             _log.error(mfue.getMessage());
141 
142             if (_log.isDebugEnabled()) {
143                 _log.debug(mfue, mfue);
144             }
145         }
146         catch (IOException ioe) {
147             _log.error(ioe.getMessage());
148 
149             if (_log.isDebugEnabled()) {
150                 _log.debug(ioe, ioe);
151             }
152         }
153 
154         return nameValues;
155     }
156 
157     private String[] _getCookieNames(String serviceUrl) {
158         String[] cookieNames = _cookieNamesMap.get(serviceUrl);
159 
160         if (cookieNames != null) {
161             return cookieNames;
162         }
163 
164         List<String> cookieNamesList = new ArrayList<String>();
165 
166         try {
167             String cookieName = null;
168 
169             String url = serviceUrl + _GET_COOKIE_NAME;
170 
171             URL urlObj = new URL(url);
172 
173             HttpURLConnection urlc = (HttpURLConnection)urlObj.openConnection();
174 
175             BufferedReader br = new BufferedReader(
176                 new InputStreamReader((InputStream)urlc.getContent()));
177 
178             int responseCode = urlc.getResponseCode();
179 
180             if (responseCode != HttpURLConnection.HTTP_OK) {
181                 if (_log.isDebugEnabled()) {
182                     _log.debug(url + " has response code " + responseCode);
183                 }
184             }
185             else {
186                 String line = null;
187 
188                 while ((line = br.readLine()) != null) {
189                     if (line.startsWith("string=")) {
190                         line = line.replaceFirst("string=", "");
191 
192                         cookieName = line;
193                     }
194                 }
195             }
196 
197             url = serviceUrl + _GET_COOKIE_NAMES;
198 
199             urlObj = new URL(url);
200 
201             urlc = (HttpURLConnection)urlObj.openConnection();
202 
203             br = new BufferedReader(
204                 new InputStreamReader((InputStream)urlc.getContent()));
205 
206             if (urlc.getResponseCode() != HttpURLConnection.HTTP_OK) {
207                 if (_log.isDebugEnabled()) {
208                     _log.debug(url + " has response code " + responseCode);
209                 }
210             }
211             else {
212                 String line = null;
213 
214                 while ((line = br.readLine()) != null) {
215                     if (line.startsWith("string=")) {
216                         line = line.replaceFirst("string=", "");
217 
218                         if (cookieName.equals(line)) {
219                             cookieNamesList.add(0, cookieName);
220                         }
221                         else {
222                             cookieNamesList.add(line);
223                         }
224                     }
225                 }
226             }
227         }
228         catch (IOException ioe) {
229             if (_log.isWarnEnabled()) {
230                 _log.warn(ioe, ioe);
231             }
232         }
233 
234         cookieNames = cookieNamesList.toArray(
235             new String[cookieNamesList.size()]);
236 
237         _cookieNamesMap.put(serviceUrl, cookieNames);
238 
239         return cookieNames;
240     }
241 
242     private String _getSubjectId(
243         HttpServletRequest request, String serviceUrl) {
244 
245         String cookieName = _getCookieNames(serviceUrl)[0];
246 
247         return CookieUtil.get(request, cookieName);
248     }
249 
250     private boolean _isAuthenticated(
251             HttpServletRequest request, String serviceUrl)
252         throws IOException {
253 
254         boolean authenticated = false;
255 
256         String url = serviceUrl + _VALIDATE_TOKEN;
257 
258         URL urlObj = new URL(url);
259 
260         HttpURLConnection urlc = (HttpURLConnection)urlObj.openConnection();
261 
262         urlc.setDoOutput(true);
263         urlc.setRequestMethod("POST");
264         urlc.setRequestProperty(
265             "Content-type", "application/x-www-form-urlencoded");
266 
267         String[] cookieNames = _getCookieNames(serviceUrl);
268 
269         _setCookieProperty(request, urlc, cookieNames);
270 
271         OutputStreamWriter osw = new OutputStreamWriter(urlc.getOutputStream());
272 
273         osw.write("dummy");
274 
275         osw.flush();
276 
277         int responseCode = urlc.getResponseCode();
278 
279         if (responseCode == HttpURLConnection.HTTP_OK) {
280             String data = StringUtil.read(urlc.getInputStream());
281 
282             if (data.toLowerCase().indexOf("boolean=true") != -1) {
283                 authenticated = true;
284             }
285         }
286         else if (_log.isDebugEnabled()) {
287             _log.debug("Authentication response code " + responseCode);
288         }
289 
290         return authenticated;
291     }
292 
293     private void _setCookieProperty(
294         HttpServletRequest request, HttpURLConnection urlc,
295         String[] cookieNames) {
296 
297         StringBuilder sb = new StringBuilder();
298 
299         for (String cookieName : cookieNames) {
300             String cookieValue = CookieUtil.get(request, cookieName);
301 
302             sb.append(cookieName);
303             sb.append(StringPool.EQUAL);
304             sb.append(cookieValue);
305             sb.append(StringPool.SEMICOLON);
306         }
307 
308         if (sb.length() > 0) {
309             urlc.setRequestProperty("Cookie", sb.toString());
310         }
311     }
312 
313     private static final String _GET_ATTRIBUTES = "/identity/attributes";
314 
315     private static final String _GET_COOKIE_NAME =
316         "/identity/getCookieNameForToken";
317 
318     private static final String _GET_COOKIE_NAMES =
319         "/identity/getCookieNamesToForward";
320 
321     private static final String _VALIDATE_TOKEN = "/identity/isTokenValid";
322 
323     private static Log _log = LogFactoryUtil.getLog(OpenSSOUtil.class);
324 
325     private static OpenSSOUtil _instance = new OpenSSOUtil();
326 
327     private Map<String, String[]> _cookieNamesMap =
328         new ConcurrentHashMap<String, String[]>();
329 
330 }