Coverage report

  %line %branch
org.apache.jetspeed.portlet.SSOWebContentPortlet
0% 
0% 

 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.jetspeed.portlet;
 18  
 
 19  
 import java.io.IOException;
 20  
 import java.security.AccessControlContext;
 21  
 import java.security.AccessController;
 22  
 import java.util.HashMap;
 23  
 import java.util.StringTokenizer;
 24  
 
 25  
 import javax.portlet.ActionRequest;
 26  
 import javax.portlet.ActionResponse;
 27  
 import javax.portlet.PortletConfig;
 28  
 import javax.portlet.PortletContext;
 29  
 import javax.portlet.PortletException;
 30  
 import javax.portlet.PortletMode;
 31  
 import javax.portlet.PortletPreferences;
 32  
 import javax.portlet.RenderRequest;
 33  
 import javax.portlet.RenderResponse;
 34  
 import javax.security.auth.Subject;
 35  
 
 36  
 import org.apache.commons.codec.binary.Base64;
 37  
 import org.apache.commons.httpclient.HttpClient;
 38  
 import org.apache.commons.httpclient.HttpMethod;
 39  
 import org.apache.commons.httpclient.NameValuePair;
 40  
 import org.apache.commons.httpclient.UsernamePasswordCredentials;
 41  
 import org.apache.commons.httpclient.auth.AuthScope;
 42  
 import org.apache.commons.httpclient.auth.AuthState;
 43  
 import org.apache.commons.httpclient.auth.BasicScheme;
 44  
 import org.apache.commons.httpclient.methods.PostMethod;
 45  
 import org.apache.commons.logging.Log;
 46  
 import org.apache.commons.logging.LogFactory;
 47  
 import org.apache.jetspeed.rewriter.WebContentRewriter;
 48  
 import org.apache.jetspeed.security.JSSubject;
 49  
 import org.apache.jetspeed.sso.SSOContext;
 50  
 import org.apache.jetspeed.sso.SSOException;
 51  
 import org.apache.jetspeed.sso.SSOProvider;
 52  
 import org.apache.portals.messaging.PortletMessaging;
 53  
 
 54  
 
 55  
 /**
 56  
  * SSOWebContentPortlet
 57  
  * 
 58  
  * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
 59  
  * @version $Id: SSOWebContentPortlet.java 605431 2007-12-19 05:11:40Z taylor $
 60  
  */
 61  0
 public class SSOWebContentPortlet extends WebContentPortlet
 62  
 {
 63  
     // Constants
 64  
     
 65  
     // sso.type
 66  
     public static final String SSO_TYPE = "sso.type";
 67  
     
 68  
     public static final String SSO_TYPE_HTTP = "http";                          // BOZO - depricate in favor of 'basic'
 69  
     public static final String SSO_TYPE_BASIC = "basic";          
 70  
     public static final String SSO_TYPE_BASIC_PREEMPTIVE = "basic.preemptive";
 71  
     
 72  
     public static final String SSO_TYPE_FORM = "form";
 73  
     public static final String SSO_TYPE_FORM_GET = "form.get";
 74  
     public static final String SSO_TYPE_FORM_POST = "form.post";
 75  
     
 76  
     public static final String SSO_TYPE_URL = "url";
 77  
     public static final String SSO_TYPE_URL_BASE64 = "url.base64";
 78  
     
 79  
     public static final String SSO_TYPE_CERTIFICATE = "certificate";
 80  
     
 81  
     public static final String SSO_TYPE_DEFAULT = SSO_TYPE_BASIC;  // handled well even if nothing but credentials are set (see: doRequestedAuthentication)
 82  
     
 83  
     // ...standardized auth types
 84  
     
 85  0
     public static final String BASIC_AUTH_SCHEME_NAME = (new BasicScheme()).getSchemeName();
 86  
 
 87  
     // supporting parameters - for various sso types
 88  
     
 89  
     // ...names of query args for sso.type=url|url.base64
 90  
     
 91  
     public static final String SSO_TYPE_URL_USERNAME_PARAM = "sso.url.Principal";
 92  
     public static final String SSO_TYPE_URL_PASSWORD_PARAM = "sso.url.Credential";
 93  
     
 94  
     // ...names of fields for sso.type=form|form.get|form.post
 95  
     
 96  
     public static final String SSO_TYPE_FORM_ACTION_URL = "sso.form.Action";
 97  
     public static final String SSO_TYPE_FORM_ACTION_ARGS = "sso.form.Args";
 98  
     public static final String SSO_TYPE_FORM_USERNAME_FIELD = "sso.form.Principal";
 99  
     public static final String SSO_TYPE_FORM_PASSWORD_FIELD = "sso.form.Credential";
 100  
     
 101  
     // ...tags for passing creditials along on the current request object
 102  
     
 103  
     public static final String SSO_REQUEST_ATTRIBUTE_USERNAME = "sso.ra.username";
 104  
     public static final String SSO_REQUEST_ATTRIBUTE_PASSWORD = "sso.ra.password";
 105  
     
 106  
     // ...field names for EDIT mode
 107  
     
 108  
     public static final String SSO_EDIT_FIELD_PRINCIPAL = "ssoPrincipal";
 109  
     public static final String SSO_EDIT_FIELD_CREDENTIAL = "ssoCredential";
 110  
     
 111  
     // SSOWebContent session variables 
 112  
 
 113  
     public static final String FORM_AUTH_STATE = "ssowebcontent.form.authstate" ;
 114  
     
 115  
     
 116  
     // Class Data
 117  
     
 118  0
     protected final static Log log = LogFactory.getLog(SSOWebContentPortlet.class);
 119  
     
 120  
     
 121  
     // Data Members
 122  
     
 123  
     protected PortletContext context;
 124  
     protected SSOProvider sso;
 125  
     
 126  
     
 127  
     // Methods
 128  
 
 129  
     public void init(PortletConfig config) throws PortletException
 130  
     {
 131  0
         super.init(config);
 132  0
         context = getPortletContext();
 133  0
         sso = (SSOProvider)context.getAttribute("cps:SSO");
 134  0
         if (null == sso)
 135  
         {
 136  0
            throw new PortletException("Failed to find SSO Provider on portlet initialization");
 137  
         }        
 138  0
     }
 139  
     
 140  
     public void processAction(ActionRequest actionRequest, ActionResponse actionResponse)
 141  
     throws PortletException, IOException
 142  
     {
 143  
         // grab parameters - they will be cleared in processing of edit response
 144  0
         String webContentParameter = actionRequest.getParameter(WebContentRewriter.ACTION_PARAMETER_URL);
 145  0
         String ssoPrincipal = actionRequest.getParameter(SSO_EDIT_FIELD_PRINCIPAL);
 146  0
         String ssoCredential = actionRequest.getParameter(SSO_EDIT_FIELD_CREDENTIAL);        
 147  
 
 148  
         // save the prefs
 149  0
         super.processAction(actionRequest, actionResponse);
 150  
   
 151  
         // process credentials
 152  0
         if (webContentParameter == null || actionRequest.getPortletMode() == PortletMode.EDIT)            
 153  
         {
 154  
             // processPreferencesAction(request, actionResponse);
 155  
             // get the POST params -- requires HTML post params named above 
 156  0
             String site = actionRequest.getPreferences().getValue("SRC", "");
 157  
             
 158  
             try
 159  
             {
 160  0
                 Subject subject = getSubject();
 161  0
                 if (sso.hasSSOCredentials(subject, site))
 162  
                 {
 163  0
                     SSOContext context = sso.getCredentials(subject, site);
 164  0
                     if (!context.getRemotePrincipalName().equals(ssoPrincipal))
 165  
                     {
 166  0
                         sso.removeCredentialsForSite(subject, site);
 167  0
                         sso.addCredentialsForSite(subject, ssoPrincipal, site, ssoCredential);
 168  
                     }
 169  
                     else
 170  
                     {
 171  0
                         sso.updateCredentialsForSite(subject, ssoPrincipal, site, ssoCredential);
 172  
                     }
 173  0
                 }
 174  
                 else
 175  
                 {
 176  0
                     sso.addCredentialsForSite(subject, ssoPrincipal, site, ssoCredential);
 177  
                 }
 178  
             }
 179  0
             catch (SSOException e)
 180  
             {
 181  0
                 throw new PortletException(e);
 182  0
             }
 183  
         }
 184  0
     }
 185  
     
 186  
     public void doView(RenderRequest request, RenderResponse response)
 187  
     throws PortletException, IOException
 188  
     {
 189  0
         String site = request.getPreferences().getValue("SRC", null);
 190  
 
 191  0
         if (site == null)
 192  
         {
 193  
             // no SRC configured in prefs - switch to SSO Configure View
 194  0
             request.setAttribute(PARAM_VIEW_PAGE, this.getPortletConfig().getInitParameter(PARAM_EDIT_PAGE));
 195  0
             setupPreferencesEdit(request, response);
 196  
         }
 197  
         else try
 198  
         {
 199  0
             Subject subject = getSubject();                 
 200  0
             SSOContext context = sso.getCredentials(subject, site);
 201  0
             request.setAttribute(SSO_REQUEST_ATTRIBUTE_USERNAME, context.getRemotePrincipalName());
 202  0
             request.setAttribute(SSO_REQUEST_ATTRIBUTE_PASSWORD, context.getRemoteCredential());
 203  
         }
 204  0
         catch (SSOException e)
 205  
         {
 206  0
             if (e.getMessage().equals(SSOException.NO_CREDENTIALS_FOR_SITE))
 207  
             {
 208  
                 // no credentials configured in SSO store
 209  
                 // switch to SSO Configure View
 210  0
                 request.setAttribute(PARAM_VIEW_PAGE, this.getPortletConfig().getInitParameter(PARAM_EDIT_PAGE));
 211  0
                 setupPreferencesEdit(request, response);    
 212  
             }
 213  
             else
 214  
             {
 215  0
                 throw new PortletException(e);
 216  
             }
 217  0
         }        
 218  
         
 219  0
         super.doView(request, response);
 220  0
     }
 221  
     
 222  
 
 223  
     public void doEdit(RenderRequest request, RenderResponse response)
 224  
     throws PortletException, IOException
 225  
     {
 226  
         try
 227  
         {
 228  0
             Subject subject = getSubject();                 
 229  0
             String site = request.getPreferences().getValue("SRC", "");
 230  0
             SSOContext context = sso.getCredentials(subject, site);
 231  0
             getContext(request).put(SSO_EDIT_FIELD_PRINCIPAL, context.getRemotePrincipalName());
 232  0
             getContext(request).put(SSO_EDIT_FIELD_CREDENTIAL, context.getRemoteCredential());
 233  
         }
 234  0
         catch (SSOException e)
 235  
         {
 236  0
             if (e.getMessage().equals(SSOException.NO_CREDENTIALS_FOR_SITE))
 237  
             {
 238  
                 // no credentials configured in SSO store
 239  
                 // switch to SSO Configure View
 240  0
                 getContext(request).put(SSO_EDIT_FIELD_PRINCIPAL, "");
 241  0
                 getContext(request).put(SSO_EDIT_FIELD_CREDENTIAL, "");
 242  
             }
 243  
             else
 244  
             {
 245  0
                 throw new PortletException(e);
 246  
             }
 247  0
         }        
 248  
         
 249  0
         super.doEdit(request, response);
 250  0
     }
 251  
 
 252  
     private Subject getSubject()
 253  
     {
 254  0
         AccessControlContext context = AccessController.getContext();
 255  0
         return JSSubject.getSubject(context);         
 256  
     }
 257  
     
 258  
     protected byte[] doPreemptiveAuthentication(HttpClient client,HttpMethod method, RenderRequest request, RenderResponse response)
 259  
     {
 260  0
     	byte[] result = super.doPreemptiveAuthentication(client, method, request, response);
 261  0
         if ( result != null)
 262  
         {
 263  
             // already handled
 264  0
             return result ;
 265  
         }
 266  
         
 267  
         // System.out.println("SSOWebContentPortlet.doPreemptiveAuthentication...");
 268  
         
 269  0
         PortletPreferences prefs = request.getPreferences();
 270  0
         String type = getSingleSignOnAuthType(prefs);
 271  
 
 272  0
         if (type.equalsIgnoreCase(SSO_TYPE_BASIC_PREEMPTIVE))
 273  
         {
 274  
             // Preemptive, basic authentication
 275  0
             String userName = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_USERNAME);
 276  0
             if (userName == null) userName = "";
 277  0
             String password = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_PASSWORD);
 278  0
             if (password == null) password = "";
 279  
             
 280  
             // System.out.println("...performing preemptive basic authentication with userName: "+userName+", and password: "+password);
 281  0
             method.setDoAuthentication(true);
 282  0
             method.getHostAuthState().setPreemptive();
 283  0
             client.getState().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(userName, password));
 284  
             
 285  
             // handled!
 286  0
             return result ;
 287  
             
 288  
         }
 289  0
         else if (type.startsWith(SSO_TYPE_FORM))
 290  
         {
 291  
             try
 292  
             {
 293  0
                 Boolean formAuth = (Boolean)PortletMessaging.receive(request, FORM_AUTH_STATE);
 294  0
                 if (formAuth != null)
 295  
                 {
 296  
                     // already been here, done that
 297  0
                     return (formAuth.booleanValue() ? result : null);
 298  
                 }
 299  
                 else
 300  
                 {
 301  
                     // stop recursion, but assume failure, ...for now
 302  0
                     PortletMessaging.publish(request, FORM_AUTH_STATE, Boolean.FALSE);
 303  
                 }
 304  
 
 305  0
                 String formAction = prefs.getValue(SSO_TYPE_FORM_ACTION_URL, "");
 306  0
                 if (formAction == null || formAction.length() == 0)
 307  
                 {
 308  0
                     log.warn("sso.type specified as 'form', but no: "+SSO_TYPE_FORM_ACTION_URL+", action was specified - unable to preemptively authenticate by form.");
 309  0
                     return null ;
 310  
                 }
 311  0
                 String userNameField = prefs.getValue(SSO_TYPE_FORM_USERNAME_FIELD, "");
 312  0
                 if (userNameField == null || userNameField.length() == 0)
 313  
                 {
 314  0
                     log.warn("sso.type specified as 'form', but no: "+SSO_TYPE_FORM_USERNAME_FIELD+", username field was specified - unable to preemptively authenticate by form.");
 315  0
                     return null ;
 316  
                 }
 317  0
                 String passwordField = prefs.getValue(SSO_TYPE_FORM_PASSWORD_FIELD, "password");
 318  0
                 if (passwordField == null || passwordField.length() == 0)
 319  
                 {
 320  0
                     log.warn("sso.type specified as 'form', but no: "+SSO_TYPE_FORM_PASSWORD_FIELD+", password field was specified - unable to preemptively authenticate by form.");
 321  0
                     return null ;
 322  
                 }
 323  
                 
 324  0
                 String userName = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_USERNAME);
 325  0
                 if (userName == null) userName = "";
 326  0
                 String password = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_PASSWORD);
 327  0
                 if (password == null) password = "";
 328  
 
 329  
                 // get submit method
 330  0
                 int i = type.indexOf('.');
 331  0
                 boolean isPost = i > 0 ? type.substring(i+1).equalsIgnoreCase("post") : true ;    // default to post, since it is a form 
 332  
             
 333  
                 // get parameter map
 334  0
                 HashMap formParams = new HashMap();
 335  0
                 formParams.put(userNameField,new String[]{ userName });
 336  0
                 formParams.put(passwordField,new String[]{ password });
 337  0
                 String formArgs = prefs.getValue(SSO_TYPE_FORM_ACTION_ARGS, "");
 338  0
                 if (formArgs != null && formArgs.length() > 0)
 339  
                 {
 340  0
                     StringTokenizer iter = new StringTokenizer(formArgs, ";");
 341  0
                     while (iter.hasMoreTokens())
 342  
                     {
 343  0
                         String pair = iter.nextToken();
 344  0
                         i = pair.indexOf('=') ;
 345  0
                         if (i > 0)
 346  0
                             formParams.put(pair.substring(0,i), new String[]{pair.substring(i+1)});
 347  0
                     }
 348  
                 }
 349  
 
 350  
                 // resuse client - in case new cookies get set - but create a new method (for the formAction)
 351  0
                 String formMethod = (isPost) ? FORM_POST_METHOD : FORM_GET_METHOD;                
 352  0
                 method = getHttpMethod(client, getURLSource(formAction, formParams, request, response), formParams, formMethod, request);
 353  
                 // System.out.println("...posting credentials");
 354  0
                 result = doHttpWebContent(client, method, 0, request, response) ;
 355  
                 // System.out.println("Result of attempted authorization: "+success);
 356  0
                 PortletMessaging.publish(request, FORM_AUTH_STATE, Boolean.valueOf(result != null));
 357  0
                 return result ;
 358  
             }
 359  0
             catch (Exception ex)
 360  
             {
 361  
                 // bad
 362  0
                 log.error("Form-based authentication failed", ex);
 363  0
             }
 364  
         }
 365  0
         else if (type.equalsIgnoreCase(SSO_TYPE_URL) || type.equalsIgnoreCase(SSO_TYPE_URL_BASE64))
 366  
         {
 367  
             // set user name and password parameters in the HttpMethod
 368  0
             String userNameParam = prefs.getValue(SSO_TYPE_URL_USERNAME_PARAM, "");
 369  0
             if (userNameParam == null || userNameParam.length() == 0)
 370  
             {
 371  0
                 log.warn("sso.type specified as 'url', but no: "+SSO_TYPE_URL_USERNAME_PARAM+", username parameter was specified - unable to preemptively authenticate by URL.");
 372  0
                 return null ;
 373  
             }
 374  0
             String passwordParam = prefs.getValue(SSO_TYPE_URL_PASSWORD_PARAM, "");
 375  0
             if (passwordParam == null || passwordParam.length() == 0)
 376  
             {
 377  0
                 log.warn("sso.type specified as 'url', but no: "+SSO_TYPE_URL_PASSWORD_PARAM+", password parameter was specified - unable to preemptively authenticate by URL.");
 378  0
                 return null ;
 379  
             }
 380  0
             String userName = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_USERNAME);
 381  0
             if (userName == null) userName = "";
 382  0
             String password = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_PASSWORD);
 383  0
             if (password == null) password = "";
 384  0
             if (type.equalsIgnoreCase(SSO_TYPE_URL_BASE64))
 385  
             {
 386  0
                 Base64 encoder = new Base64() ;
 387  0
                 userName = new String(encoder.encode(userName.getBytes()));
 388  0
                 password = new String(encoder.encode(password.getBytes()));
 389  
             }
 390  
             
 391  
             // GET and POST accept args differently
 392  0
             if ( method instanceof PostMethod )
 393  
             {
 394  
                 // add POST data
 395  0
                 PostMethod postMethod = (PostMethod)method ;
 396  0
                 postMethod.addParameter(userNameParam, userName);
 397  0
                 postMethod.addParameter(passwordParam, password);
 398  0
             }
 399  
             else
 400  
             {
 401  
                 // augment GET query string
 402  0
                 NameValuePair[] authPairs = new NameValuePair[]{ class="keyword">new NameValuePair(userNameParam, userName), class="keyword">new NameValuePair(passwordParam, password) } ; 
 403  0
                 String existingQuery = method.getQueryString() ;
 404  0
                 method.setQueryString(authPairs);
 405  0
                 if (existingQuery != null && existingQuery.length() > 0)
 406  
                 {
 407  
                     // augment existing query with new auth query
 408  0
                     existingQuery = existingQuery + '&' + method.getQueryString();
 409  0
                     method.setQueryString(existingQuery);
 410  
                 }
 411  
             }
 412  
             
 413  0
             return result ;
 414  
         }
 415  
         // else System.out.println("...sso.type: "+type+", no pre-emptive authentication");
 416  
         
 417  
         // not handled
 418  0
         return null ;
 419  
     }
 420  
 
 421  
     protected boolean doRequestedAuthentication(HttpClient client,HttpMethod method, RenderRequest request, RenderResponse response)
 422  
     {
 423  0
         if ( super.doRequestedAuthentication(client, method, request, response))
 424  
         {
 425  
             // already handled
 426  0
             return true ;
 427  
         }
 428  
         
 429  
         // System.out.println("SSOWebContentPortlet.doRequestedAuthentication...");
 430  
         
 431  0
         if (method.getHostAuthState().getAuthScheme().getSchemeName().equals(BASIC_AUTH_SCHEME_NAME))
 432  
         {
 433  
             // Basic authentication being requested
 434  0
             String userName = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_USERNAME);
 435  0
             if (userName == null) userName = "";
 436  0
             String password = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_PASSWORD);
 437  0
             if (password == null) password = "";
 438  
             
 439  
             // System.out.println("...providing basic authentication with userName: "+userName+", and password: "+password);
 440  0
             method.setDoAuthentication(true);
 441  0
             AuthState state = method.getHostAuthState();
 442  0
             AuthScope scope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, state.getRealm(), state.getAuthScheme().getSchemeName()) ;
 443  0
             client.getState().setCredentials(scope, new UsernamePasswordCredentials(userName, password));
 444  
             
 445  
             // handled!
 446  0
             return true ;
 447  
         }
 448  
         else
 449  
         {
 450  0
             log.warn("SSOWebContentPortlent.doAuthenticate() - unexpected authentication scheme: "+method.getHostAuthState().getAuthScheme().getSchemeName());
 451  
         }
 452  
 
 453  
         // only know how to handle Basic authentication, in this context
 454  0
         return false;
 455  
     }
 456  
     
 457  
     protected String getSingleSignOnAuthType(PortletPreferences prefs)
 458  
     {
 459  0
         String type = prefs.getValue(SSO_TYPE,SSO_TYPE_DEFAULT);
 460  
         
 461  0
         if (type != null && type.equalsIgnoreCase(SSO_TYPE_HTTP))
 462  
         {
 463  0
             log.warn("sso.type: "+SSO_TYPE_HTTP+", has been deprecated - use: "+SSO_TYPE_BASIC+", or: "+SSO_TYPE_BASIC_PREEMPTIVE);
 464  0
             type = SSO_TYPE_BASIC ;
 465  
         }
 466  
         
 467  0
         return type ;
 468  
     }
 469  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.