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