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 516448 2007-03-09 16:25:47Z ate $
 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  
     private PortletContext context;
 124  
     private 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
                     sso.updateCredentialsForSite(getSubject(), ssoPrincipal, site, ssoCredential);
 164  
                 }
 165  
                 else
 166  
                 {
 167  0
                     sso.addCredentialsForSite(getSubject(), ssoPrincipal, site, ssoCredential);
 168  
                 }
 169  
             }
 170  0
             catch (SSOException e)
 171  
             {
 172  0
                 throw new PortletException(e);
 173  0
             }
 174  
         }
 175  0
     }
 176  
     
 177  
     public void doView(RenderRequest request, RenderResponse response)
 178  
     throws PortletException, IOException
 179  
     {
 180  0
         String site = request.getPreferences().getValue("SRC", null);
 181  
 
 182  0
         if (site == null)
 183  
         {
 184  
             // no SRC configured in prefs - switch to SSO Configure View
 185  0
             request.setAttribute(PARAM_VIEW_PAGE, this.getPortletConfig().getInitParameter(PARAM_EDIT_PAGE));
 186  0
             setupPreferencesEdit(request, response);
 187  
         }
 188  
         else try
 189  
         {
 190  0
             Subject subject = getSubject();                 
 191  0
             SSOContext context = sso.getCredentials(subject, site);
 192  0
             request.setAttribute(SSO_REQUEST_ATTRIBUTE_USERNAME, context.getRemotePrincipalName());
 193  0
             request.setAttribute(SSO_REQUEST_ATTRIBUTE_PASSWORD, context.getRemoteCredential());
 194  
         }
 195  0
         catch (SSOException e)
 196  
         {
 197  0
             if (e.getMessage().equals(SSOException.NO_CREDENTIALS_FOR_SITE))
 198  
             {
 199  
                 // no credentials configured in SSO store
 200  
                 // switch to SSO Configure View
 201  0
                 request.setAttribute(PARAM_VIEW_PAGE, this.getPortletConfig().getInitParameter(PARAM_EDIT_PAGE));
 202  0
                 setupPreferencesEdit(request, response);    
 203  
             }
 204  
             else
 205  
             {
 206  0
                 throw new PortletException(e);
 207  
             }
 208  0
         }        
 209  
         
 210  0
         super.doView(request, response);
 211  0
     }
 212  
     
 213  
 
 214  
     public void doEdit(RenderRequest request, RenderResponse response)
 215  
     throws PortletException, IOException
 216  
     {
 217  
         try
 218  
         {
 219  0
             Subject subject = getSubject();                 
 220  0
             String site = request.getPreferences().getValue("SRC", "");
 221  0
             SSOContext context = sso.getCredentials(subject, site);
 222  0
             getContext(request).put(SSO_EDIT_FIELD_PRINCIPAL, context.getRemotePrincipalName());
 223  0
             getContext(request).put(SSO_EDIT_FIELD_CREDENTIAL, context.getRemoteCredential());
 224  
         }
 225  0
         catch (SSOException e)
 226  
         {
 227  0
             if (e.getMessage().equals(SSOException.NO_CREDENTIALS_FOR_SITE))
 228  
             {
 229  
                 // no credentials configured in SSO store
 230  
                 // switch to SSO Configure View
 231  0
                 getContext(request).put(SSO_EDIT_FIELD_PRINCIPAL, "");
 232  0
                 getContext(request).put(SSO_EDIT_FIELD_CREDENTIAL, "");
 233  
             }
 234  
             else
 235  
             {
 236  0
                 throw new PortletException(e);
 237  
             }
 238  0
         }        
 239  
         
 240  0
         super.doEdit(request, response);
 241  0
     }
 242  
 
 243  
     private Subject getSubject()
 244  
     {
 245  0
         AccessControlContext context = AccessController.getContext();
 246  0
         return JSSubject.getSubject(context);         
 247  
     }
 248  
     
 249  
     protected byte[] doPreemptiveAuthentication(HttpClient client,HttpMethod method, RenderRequest request, RenderResponse response)
 250  
     {
 251  0
     	byte[] result = super.doPreemptiveAuthentication(client, method, request, response);
 252  0
         if ( result != null)
 253  
         {
 254  
             // already handled
 255  0
             return result ;
 256  
         }
 257  
         
 258  
         // System.out.println("SSOWebContentPortlet.doPreemptiveAuthentication...");
 259  
         
 260  0
         PortletPreferences prefs = request.getPreferences();
 261  0
         String type = getSingleSignOnAuthType(prefs);
 262  
 
 263  0
         if (type.equalsIgnoreCase(SSO_TYPE_BASIC_PREEMPTIVE))
 264  
         {
 265  
             // Preemptive, basic authentication
 266  0
             String userName = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_USERNAME);
 267  0
             if (userName == null) userName = "";
 268  0
             String password = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_PASSWORD);
 269  0
             if (password == null) password = "";
 270  
             
 271  
             // System.out.println("...performing preemptive basic authentication with userName: "+userName+", and password: "+password);
 272  0
             method.setDoAuthentication(true);
 273  0
             method.getHostAuthState().setPreemptive();
 274  0
             client.getState().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(userName, password));
 275  
             
 276  
             // handled!
 277  0
             return result ;
 278  
             
 279  
         }
 280  0
         else if (type.startsWith(SSO_TYPE_FORM))
 281  
         {
 282  
             try
 283  
             {
 284  0
                 Boolean formAuth = (Boolean)PortletMessaging.receive(request, FORM_AUTH_STATE);
 285  0
                 if (formAuth != null)
 286  
                 {
 287  
                     // already been here, done that
 288  0
                     return (formAuth.booleanValue() ? result : null);
 289  
                 }
 290  
                 else
 291  
                 {
 292  
                     // stop recursion, but assume failure, ...for now
 293  0
                     PortletMessaging.publish(request, FORM_AUTH_STATE, Boolean.FALSE);
 294  
                 }
 295  
 
 296  0
                 String formAction = prefs.getValue(SSO_TYPE_FORM_ACTION_URL, "");
 297  0
                 if (formAction == null || formAction.length() == 0)
 298  
                 {
 299  0
                     log.warn("sso.type specified as 'form', but no: "+SSO_TYPE_FORM_ACTION_URL+", action was specified - unable to preemptively authenticate by form.");
 300  0
                     return null ;
 301  
                 }
 302  0
                 String userNameField = prefs.getValue(SSO_TYPE_FORM_USERNAME_FIELD, "");
 303  0
                 if (userNameField == null || userNameField.length() == 0)
 304  
                 {
 305  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.");
 306  0
                     return null ;
 307  
                 }
 308  0
                 String passwordField = prefs.getValue(SSO_TYPE_FORM_PASSWORD_FIELD, "password");
 309  0
                 if (passwordField == null || passwordField.length() == 0)
 310  
                 {
 311  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.");
 312  0
                     return null ;
 313  
                 }
 314  
                 
 315  0
                 String userName = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_USERNAME);
 316  0
                 if (userName == null) userName = "";
 317  0
                 String password = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_PASSWORD);
 318  0
                 if (password == null) password = "";
 319  
 
 320  
                 // get submit method
 321  0
                 int i = type.indexOf('.');
 322  0
                 boolean isPost = i > 0 ? type.substring(i+1).equalsIgnoreCase("post") : true ;    // default to post, since it is a form 
 323  
             
 324  
                 // get parameter map
 325  0
                 HashMap formParams = new HashMap();
 326  0
                 formParams.put(userNameField,new String[]{ userName });
 327  0
                 formParams.put(passwordField,new String[]{ password });
 328  0
                 String formArgs = prefs.getValue(SSO_TYPE_FORM_ACTION_ARGS, "");
 329  0
                 if (formArgs != null && formArgs.length() > 0)
 330  
                 {
 331  0
                     StringTokenizer iter = new StringTokenizer(formArgs, ";");
 332  0
                     while (iter.hasMoreTokens())
 333  
                     {
 334  0
                         String pair = iter.nextToken();
 335  0
                         i = pair.indexOf('=') ;
 336  0
                         if (i > 0)
 337  0
                             formParams.put(pair.substring(0,i), new String[]{pair.substring(i+1)});
 338  0
                     }
 339  
                 }
 340  
 
 341  
                 // resuse client - in case new cookies get set - but create a new method (for the formAction)
 342  0
                 method = getHttpMethod(client, getURLSource(formAction, formParams, request, response), formParams, isPost, request);
 343  
                 // System.out.println("...posting credentials");
 344  0
                 result = doHttpWebContent(client, method, 0, request, response) ;
 345  
                 // System.out.println("Result of attempted authorization: "+success);
 346  0
                 PortletMessaging.publish(request, FORM_AUTH_STATE, Boolean.valueOf(result != null));
 347  0
                 return result ;
 348  
             }
 349  0
             catch (Exception ex)
 350  
             {
 351  
                 // bad
 352  0
                 log.error("Form-based authentication failed", ex);
 353  0
             }
 354  
         }
 355  0
         else if (type.equalsIgnoreCase(SSO_TYPE_URL) || type.equalsIgnoreCase(SSO_TYPE_URL_BASE64))
 356  
         {
 357  
             // set user name and password parameters in the HttpMethod
 358  0
             String userNameParam = prefs.getValue(SSO_TYPE_URL_USERNAME_PARAM, "");
 359  0
             if (userNameParam == null || userNameParam.length() == 0)
 360  
             {
 361  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.");
 362  0
                 return null ;
 363  
             }
 364  0
             String passwordParam = prefs.getValue(SSO_TYPE_URL_PASSWORD_PARAM, "");
 365  0
             if (passwordParam == null || passwordParam.length() == 0)
 366  
             {
 367  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.");
 368  0
                 return null ;
 369  
             }
 370  0
             String userName = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_USERNAME);
 371  0
             if (userName == null) userName = "";
 372  0
             String password = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_PASSWORD);
 373  0
             if (password == null) password = "";
 374  0
             if (type.equalsIgnoreCase(SSO_TYPE_URL_BASE64))
 375  
             {
 376  0
                 Base64 encoder = new Base64() ;
 377  0
                 userName = new String(encoder.encode(userName.getBytes()));
 378  0
                 password = new String(encoder.encode(password.getBytes()));
 379  
             }
 380  
             
 381  
             // GET and POST accept args differently
 382  0
             if ( method instanceof PostMethod )
 383  
             {
 384  
                 // add POST data
 385  0
                 PostMethod postMethod = (PostMethod)method ;
 386  0
                 postMethod.addParameter(userNameParam, userName);
 387  0
                 postMethod.addParameter(passwordParam, password);
 388  0
             }
 389  
             else
 390  
             {
 391  
                 // augment GET query string
 392  0
                 NameValuePair[] authPairs = new NameValuePair[]{ class="keyword">new NameValuePair(userNameParam, userName), class="keyword">new NameValuePair(passwordParam, password) } ; 
 393  0
                 String existingQuery = method.getQueryString() ;
 394  0
                 method.setQueryString(authPairs);
 395  0
                 if (existingQuery != null && existingQuery.length() > 0)
 396  
                 {
 397  
                     // augment existing query with new auth query
 398  0
                     existingQuery = existingQuery + '&' + method.getQueryString();
 399  0
                     method.setQueryString(existingQuery);
 400  
                 }
 401  
             }
 402  
             
 403  0
             return result ;
 404  
         }
 405  
         // else System.out.println("...sso.type: "+type+", no pre-emptive authentication");
 406  
         
 407  
         // not handled
 408  0
         return null ;
 409  
     }
 410  
 
 411  
     protected boolean doRequestedAuthentication(HttpClient client,HttpMethod method, RenderRequest request, RenderResponse response)
 412  
     {
 413  0
         if ( super.doRequestedAuthentication(client, method, request, response))
 414  
         {
 415  
             // already handled
 416  0
             return true ;
 417  
         }
 418  
         
 419  
         // System.out.println("SSOWebContentPortlet.doRequestedAuthentication...");
 420  
         
 421  0
         if (method.getHostAuthState().getAuthScheme().getSchemeName().equals(BASIC_AUTH_SCHEME_NAME))
 422  
         {
 423  
             // Basic authentication being requested
 424  0
             String userName = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_USERNAME);
 425  0
             if (userName == null) userName = "";
 426  0
             String password = (String)request.getAttribute(SSO_REQUEST_ATTRIBUTE_PASSWORD);
 427  0
             if (password == null) password = "";
 428  
             
 429  
             // System.out.println("...providing basic authentication with userName: "+userName+", and password: "+password);
 430  0
             method.setDoAuthentication(true);
 431  0
             AuthState state = method.getHostAuthState();
 432  0
             AuthScope scope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, state.getRealm(), state.getAuthScheme().getSchemeName()) ;
 433  0
             client.getState().setCredentials(scope, new UsernamePasswordCredentials(userName, password));
 434  
             
 435  
             // handled!
 436  0
             return true ;
 437  
         }
 438  
         else
 439  
         {
 440  0
             log.warn("SSOWebContentPortlent.doAuthenticate() - unexpected authentication scheme: "+method.getHostAuthState().getAuthScheme().getSchemeName());
 441  
         }
 442  
 
 443  
         // only know how to handle Basic authentication, in this context
 444  0
         return false;
 445  
     }
 446  
     
 447  
     protected String getSingleSignOnAuthType(PortletPreferences prefs)
 448  
     {
 449  0
         String type = prefs.getValue(SSO_TYPE,SSO_TYPE_DEFAULT);
 450  
         
 451  0
         if (type != null && type.equalsIgnoreCase(SSO_TYPE_HTTP))
 452  
         {
 453  0
             log.warn("sso.type: "+SSO_TYPE_HTTP+", has been deprecated - use: "+SSO_TYPE_BASIC+", or: "+SSO_TYPE_BASIC_PREEMPTIVE);
 454  0
             type = SSO_TYPE_BASIC ;
 455  
         }
 456  
         
 457  0
         return type ;
 458  
     }
 459  
 }

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