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   */
60  public class OpenSSOUtil {
61  
62      public static Map<String, String> getAttributes(
63          HttpServletRequest request, String serviceUrl) {
64  
65          return _instance._getAttributes(request, serviceUrl);
66      }
67  
68      public static String getSubjectId(
69          HttpServletRequest request, String serviceUrl) {
70  
71          return _instance._getSubjectId(request, serviceUrl);
72      }
73  
74      public static boolean isAuthenticated(
75              HttpServletRequest request, String serviceUrl)
76          throws IOException {
77  
78          return _instance._isAuthenticated(request, serviceUrl);
79      }
80  
81      private OpenSSOUtil() {
82      }
83  
84      private Map<String, String> _getAttributes(
85          HttpServletRequest request, String serviceUrl) {
86  
87          Map<String, String> nameValues = new HashMap<String, String>();
88  
89          String url = serviceUrl + _GET_ATTRIBUTES;
90  
91          try {
92              URL urlObj = new URL(url);
93  
94              HttpURLConnection urlc = (HttpURLConnection)urlObj.openConnection();
95  
96              urlc.setDoOutput(true);
97              urlc.setRequestMethod("POST");
98              urlc.setRequestProperty(
99                  "Content-type", "application/x-www-form-urlencoded");
100 
101             String[] cookieNames = _getCookieNames(serviceUrl);
102 
103             _setCookieProperty(request, urlc, cookieNames);
104 
105             OutputStreamWriter osw = new OutputStreamWriter(
106                 urlc.getOutputStream());
107 
108             osw.write("dummy");
109 
110             osw.flush();
111 
112             int responseCode = urlc.getResponseCode();
113 
114             if (responseCode == HttpURLConnection.HTTP_OK) {
115                 BufferedReader br = new BufferedReader(
116                     new InputStreamReader((InputStream)urlc.getContent()));
117 
118                 String line = null;
119 
120                 while ((line = br.readLine()) != null) {
121                     if (line.startsWith("userdetails.attribute.name=")) {
122                         String name = line.replaceFirst(
123                             "userdetails.attribute.name=", "");
124 
125                         line = br.readLine();
126 
127                         if (line.startsWith("userdetails.attribute.value=")) {
128                             String value = line.replaceFirst(
129                                 "userdetails.attribute.value=", "");
130 
131                             nameValues.put(name, value);
132                         }
133                     }
134                 }
135             }
136             else if (_log.isDebugEnabled()) {
137                 _log.debug("Attributes response code " + responseCode);
138             }
139         }
140         catch (MalformedURLException mfue) {
141             _log.error(mfue.getMessage());
142 
143             if (_log.isDebugEnabled()) {
144                 _log.debug(mfue, mfue);
145             }
146         }
147         catch (IOException ioe) {
148             _log.error(ioe.getMessage());
149 
150             if (_log.isDebugEnabled()) {
151                 _log.debug(ioe, ioe);
152             }
153         }
154 
155         return nameValues;
156     }
157 
158     private String[] _getCookieNames(String serviceUrl) {
159         String[] cookieNames = _cookieNamesMap.get(serviceUrl);
160 
161         if (cookieNames != null) {
162             return cookieNames;
163         }
164 
165         List<String> cookieNamesList = new ArrayList<String>();
166 
167         try {
168             String cookieName = null;
169 
170             String url = serviceUrl + _GET_COOKIE_NAME;
171 
172             URL urlObj = new URL(url);
173 
174             HttpURLConnection urlc = (HttpURLConnection)urlObj.openConnection();
175 
176             BufferedReader br = new BufferedReader(
177                 new InputStreamReader((InputStream)urlc.getContent()));
178 
179             int responseCode = urlc.getResponseCode();
180 
181             if (responseCode != HttpURLConnection.HTTP_OK) {
182                 if (_log.isDebugEnabled()) {
183                     _log.debug(url + " has response code " + responseCode);
184                 }
185             }
186             else {
187                 String line = null;
188 
189                 while ((line = br.readLine()) != null) {
190                     if (line.startsWith("string=")) {
191                         line = line.replaceFirst("string=", "");
192 
193                         cookieName = line;
194                     }
195                 }
196             }
197 
198             url = serviceUrl + _GET_COOKIE_NAMES;
199 
200             urlObj = new URL(url);
201 
202             urlc = (HttpURLConnection)urlObj.openConnection();
203 
204             br = new BufferedReader(
205                 new InputStreamReader((InputStream)urlc.getContent()));
206 
207             if (urlc.getResponseCode() != HttpURLConnection.HTTP_OK) {
208                 if (_log.isDebugEnabled()) {
209                     _log.debug(url + " has response code " + responseCode);
210                 }
211             }
212             else {
213                 String line = null;
214 
215                 while ((line = br.readLine()) != null) {
216                     if (line.startsWith("string=")) {
217                         line = line.replaceFirst("string=", "");
218 
219                         if (cookieName.equals(line)) {
220                             cookieNamesList.add(0, cookieName);
221                         }
222                         else {
223                             cookieNamesList.add(line);
224                         }
225                     }
226                 }
227             }
228         }
229         catch (IOException ioe) {
230             if (_log.isWarnEnabled()) {
231                 _log.warn(ioe, ioe);
232             }
233         }
234 
235         cookieNames = cookieNamesList.toArray(
236             new String[cookieNamesList.size()]);
237 
238         _cookieNamesMap.put(serviceUrl, cookieNames);
239 
240         return cookieNames;
241     }
242 
243     private String _getSubjectId(
244         HttpServletRequest request, String serviceUrl) {
245 
246         String cookieName = _getCookieNames(serviceUrl)[0];
247 
248         return CookieUtil.get(request, cookieName);
249     }
250 
251     private boolean _isAuthenticated(
252             HttpServletRequest request, String serviceUrl)
253         throws IOException {
254 
255         boolean authenticated = false;
256 
257         String url = serviceUrl + _VALIDATE_TOKEN;
258 
259         URL urlObj = new URL(url);
260 
261         HttpURLConnection urlc = (HttpURLConnection)urlObj.openConnection();
262 
263         urlc.setDoOutput(true);
264         urlc.setRequestMethod("POST");
265         urlc.setRequestProperty(
266             "Content-type", "application/x-www-form-urlencoded");
267 
268         String[] cookieNames = _getCookieNames(serviceUrl);
269 
270         _setCookieProperty(request, urlc, cookieNames);
271 
272         OutputStreamWriter osw = new OutputStreamWriter(urlc.getOutputStream());
273 
274         osw.write("dummy");
275 
276         osw.flush();
277 
278         int responseCode = urlc.getResponseCode();
279 
280         if (responseCode == HttpURLConnection.HTTP_OK) {
281             String data = StringUtil.read(urlc.getInputStream());
282 
283             if (data.toLowerCase().indexOf("boolean=true") != -1) {
284                 authenticated = true;
285             }
286         }
287         else if (_log.isDebugEnabled()) {
288             _log.debug("Authentication response code " + responseCode);
289         }
290 
291         return authenticated;
292     }
293 
294     private void _setCookieProperty(
295         HttpServletRequest request, HttpURLConnection urlc,
296         String[] cookieNames) {
297 
298         StringBuilder sb = new StringBuilder();
299 
300         for (String cookieName : cookieNames) {
301             String cookieValue = CookieUtil.get(request, cookieName);
302 
303             sb.append(cookieName);
304             sb.append(StringPool.EQUAL);
305             sb.append(cookieValue);
306             sb.append(StringPool.SEMICOLON);
307         }
308 
309         if (sb.length() > 0) {
310             urlc.setRequestProperty("Cookie", sb.toString());
311         }
312     }
313 
314     private static final String _GET_ATTRIBUTES = "/identity/attributes";
315 
316     private static final String _GET_COOKIE_NAME =
317         "/identity/getCookieNameForToken";
318 
319     private static final String _GET_COOKIE_NAMES =
320         "/identity/getCookieNamesToForward";
321 
322     private static final String _VALIDATE_TOKEN = "/identity/isTokenValid";
323 
324     private static Log _log = LogFactoryUtil.getLog(OpenSSOUtil.class);
325 
326     private static OpenSSOUtil _instance = new OpenSSOUtil();
327 
328     private Map<String, String[]> _cookieNamesMap =
329         new ConcurrentHashMap<String, String[]>();
330 
331 }