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.io.unsync.UnsyncBufferedReader;
26  import com.liferay.portal.kernel.log.Log;
27  import com.liferay.portal.kernel.log.LogFactoryUtil;
28  import com.liferay.portal.kernel.util.StringPool;
29  import com.liferay.portal.kernel.util.StringUtil;
30  import com.liferay.util.CookieUtil;
31  
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                 UnsyncBufferedReader unsyncBufferedReader =
115                     new UnsyncBufferedReader(
116                         new InputStreamReader((InputStream)urlc.getContent()));
117 
118                 String line = null;
119 
120                 while ((line = unsyncBufferedReader.readLine()) != null) {
121                     if (line.startsWith("userdetails.attribute.name=")) {
122                         String name = line.replaceFirst(
123                             "userdetails.attribute.name=", "");
124 
125                         line = unsyncBufferedReader.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             UnsyncBufferedReader unsyncBufferedReader =
177                 new UnsyncBufferedReader(
178                     new InputStreamReader((InputStream)urlc.getContent()));
179 
180             int responseCode = urlc.getResponseCode();
181 
182             if (responseCode != HttpURLConnection.HTTP_OK) {
183                 if (_log.isDebugEnabled()) {
184                     _log.debug(url + " has response code " + responseCode);
185                 }
186             }
187             else {
188                 String line = null;
189 
190                 while ((line = unsyncBufferedReader.readLine()) != null) {
191                     if (line.startsWith("string=")) {
192                         line = line.replaceFirst("string=", "");
193 
194                         cookieName = line;
195                     }
196                 }
197             }
198 
199             url = serviceUrl + _GET_COOKIE_NAMES;
200 
201             urlObj = new URL(url);
202 
203             urlc = (HttpURLConnection)urlObj.openConnection();
204 
205             unsyncBufferedReader = new UnsyncBufferedReader(
206                 new InputStreamReader((InputStream)urlc.getContent()));
207 
208             if (urlc.getResponseCode() != HttpURLConnection.HTTP_OK) {
209                 if (_log.isDebugEnabled()) {
210                     _log.debug(url + " has response code " + responseCode);
211                 }
212             }
213             else {
214                 String line = null;
215 
216                 while ((line = unsyncBufferedReader.readLine()) != null) {
217                     if (line.startsWith("string=")) {
218                         line = line.replaceFirst("string=", "");
219 
220                         if (cookieName.equals(line)) {
221                             cookieNamesList.add(0, cookieName);
222                         }
223                         else {
224                             cookieNamesList.add(line);
225                         }
226                     }
227                 }
228             }
229         }
230         catch (IOException ioe) {
231             if (_log.isWarnEnabled()) {
232                 _log.warn(ioe, ioe);
233             }
234         }
235 
236         cookieNames = cookieNamesList.toArray(
237             new String[cookieNamesList.size()]);
238 
239         _cookieNamesMap.put(serviceUrl, cookieNames);
240 
241         return cookieNames;
242     }
243 
244     private String _getSubjectId(
245         HttpServletRequest request, String serviceUrl) {
246 
247         String cookieName = _getCookieNames(serviceUrl)[0];
248 
249         return CookieUtil.get(request, cookieName);
250     }
251 
252     private boolean _isAuthenticated(
253             HttpServletRequest request, String serviceUrl)
254         throws IOException {
255 
256         boolean authenticated = false;
257 
258         String url = serviceUrl + _VALIDATE_TOKEN;
259 
260         URL urlObj = new URL(url);
261 
262         HttpURLConnection urlc = (HttpURLConnection)urlObj.openConnection();
263 
264         urlc.setDoOutput(true);
265         urlc.setRequestMethod("POST");
266         urlc.setRequestProperty(
267             "Content-type", "application/x-www-form-urlencoded");
268 
269         String[] cookieNames = _getCookieNames(serviceUrl);
270 
271         _setCookieProperty(request, urlc, cookieNames);
272 
273         OutputStreamWriter osw = new OutputStreamWriter(urlc.getOutputStream());
274 
275         osw.write("dummy");
276 
277         osw.flush();
278 
279         int responseCode = urlc.getResponseCode();
280 
281         if (responseCode == HttpURLConnection.HTTP_OK) {
282             String data = StringUtil.read(urlc.getInputStream());
283 
284             if (data.toLowerCase().indexOf("boolean=true") != -1) {
285                 authenticated = true;
286             }
287         }
288         else if (_log.isDebugEnabled()) {
289             _log.debug("Authentication response code " + responseCode);
290         }
291 
292         return authenticated;
293     }
294 
295     private void _setCookieProperty(
296         HttpServletRequest request, HttpURLConnection urlc,
297         String[] cookieNames) {
298 
299         StringBuilder sb = new StringBuilder();
300 
301         for (String cookieName : cookieNames) {
302             String cookieValue = CookieUtil.get(request, cookieName);
303 
304             sb.append(cookieName);
305             sb.append(StringPool.EQUAL);
306             sb.append(cookieValue);
307             sb.append(StringPool.SEMICOLON);
308         }
309 
310         if (sb.length() > 0) {
311             urlc.setRequestProperty("Cookie", sb.toString());
312         }
313     }
314 
315     private static final String _GET_ATTRIBUTES = "/identity/attributes";
316 
317     private static final String _GET_COOKIE_NAME =
318         "/identity/getCookieNameForToken";
319 
320     private static final String _GET_COOKIE_NAMES =
321         "/identity/getCookieNamesToForward";
322 
323     private static final String _VALIDATE_TOKEN = "/identity/isTokenValid";
324 
325     private static Log _log = LogFactoryUtil.getLog(OpenSSOUtil.class);
326 
327     private static OpenSSOUtil _instance = new OpenSSOUtil();
328 
329     private Map<String, String[]> _cookieNamesMap =
330         new ConcurrentHashMap<String, String[]>();
331 
332 }