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