You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by ro...@apache.org on 2005/12/06 19:53:40 UTC

svn commit: r354497 - in /portals/jetspeed-2/trunk: components/sso/ components/sso/src/java/JETSPEED-INF/ojb/ components/sso/src/java/org/apache/jetspeed/portlet/ components/sso/src/java/org/apache/jetspeed/portlet/sso/ components/sso/src/java/org/apac...

Author: rogerrut
Date: Tue Dec  6 10:52:37 2005
New Revision: 354497

URL: http://svn.apache.org/viewcvs?rev=354497&view=rev
Log:
Refactored SSO feature:
--> resolved JS2-173, JS2-388

Creating cookies in the LoginModule for any SSO is feasible but cookies can't be directly injected (in pipeline) into an ongoing request.
Instead I introduced the SSOProxyPortlet that does the same functionality. The SSOProxyPortlet authenticates any SSO for the given principal before it redirects the request to the final destination. If the page has any links to SSO protected sites the user won't be prompted since it has already been authenticated.

Another advantage of this approach is that the SSO component is not bound to the portal infrastructure (LoginModule / pipeline) and therefore allows easier integration into other SSO frameworks like JOSSO.

Added:
    portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/portlet/
    portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/portlet/sso/
    portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/portlet/sso/SSOProxyPortlet.java
    portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOCookieImpl.java
    portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOCookie.java
Modified:
    portals/jetspeed-2/trunk/components/sso/project.xml
    portals/jetspeed-2/trunk/components/sso/src/java/JETSPEED-INF/ojb/sso_repository.xml
    portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/PersistenceBrokerSSOProvider.java
    portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOPrincipalImpl.java
    portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOSiteImpl.java
    portals/jetspeed-2/trunk/components/sso/src/test/org/apache/jetspeed/sso/TestSSOComponent.java
    portals/jetspeed-2/trunk/etc/schema/security-schema.xml
    portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOProvider.java
    portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOSite.java
    portals/jetspeed-2/trunk/src/webapp/WEB-INF/assembly/sso.xml

Modified: portals/jetspeed-2/trunk/components/sso/project.xml
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/sso/project.xml?rev=354497&r1=354496&r2=354497&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/sso/project.xml (original)
+++ portals/jetspeed-2/trunk/components/sso/project.xml Tue Dec  6 10:52:37 2005
@@ -70,6 +70,33 @@
                 <war.bundle>true</war.bundle>
             </properties>
         </dependency>
+        
+        <dependency>
+			<groupId>portals-bridges</groupId>
+			<artifactId>portals-bridges-common</artifactId>
+			<version>${portals.bridges.common.version}</version>
+			<type>jar</type>
+			<properties>
+				<war.bundle>true</war.bundle>
+			</properties>
+		</dependency>	
+	    <dependency>
+	      <groupId>portals-bridges</groupId>
+	      <artifactId>portals-bridges-velocity</artifactId>
+	      <version>${portals.bridges.velocity.version}</version>
+	      <properties>
+	        <war.bundle>true</war.bundle>
+	      </properties>
+	    </dependency>
+        <dependency>
+            <id>commons-httpclient</id>
+            <groupId>commons-httpclient</groupId>
+            <version>2.0.2</version>
+            <properties>
+                <war.bundle>true</war.bundle>
+            </properties>
+        </dependency>
+        
 
         <!-- Testing only -->
         <dependency>
@@ -88,7 +115,6 @@
                 <war.bundle>false</war.bundle>
             </properties>
         </dependency>
-
     </dependencies>
 
     <build>

Modified: portals/jetspeed-2/trunk/components/sso/src/java/JETSPEED-INF/ojb/sso_repository.xml
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/sso/src/java/JETSPEED-INF/ojb/sso_repository.xml?rev=354497&r1=354496&r2=354497&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/sso/src/java/JETSPEED-INF/ojb/sso_repository.xml (original)
+++ portals/jetspeed-2/trunk/components/sso/src/java/JETSPEED-INF/ojb/sso_repository.xml Tue Dec  6 10:52:37 2005
@@ -147,6 +147,47 @@
 	        nullable="false"
 	    >
 	    </field-descriptor>
+	    
+	    <field-descriptor
+	        name="isChallangeResponseAuthentication"
+	        column="CHALLENGE_RESPONSE_AUTH"
+	        jdbc-type="INTEGER"
+	        conversion="org.apache.ojb.broker.accesslayer.conversions.Boolean2IntFieldConversion"
+	        nullable="false"
+	    >
+	    </field-descriptor>
+	    <field-descriptor
+	        name="isFormAuthentication"
+	        column="FORM_AUTH"
+	        jdbc-type="INTEGER"
+	        conversion="org.apache.ojb.broker.accesslayer.conversions.Boolean2IntFieldConversion"
+	        nullable="false"
+	    >
+	    </field-descriptor>
+	    <field-descriptor
+	        name="formUserField"
+	        column="FORM_USER_FIELD"
+	        jdbc-type="VARCHAR"
+	        nullable="false"
+	        length="128"
+	    >
+	    </field-descriptor>
+	    <field-descriptor
+	        name="formPwdField"
+	        column="FORM_PWD_FIELD"
+	        jdbc-type="VARCHAR"
+	        nullable="false"
+	        length="128"
+	    >
+	    </field-descriptor>
+	    <field-descriptor
+	        name="realm"
+	        column="REALM"
+	        jdbc-type="VARCHAR"
+	        nullable="false"
+	        length="128"
+	    >
+	    </field-descriptor>
 	     <collection-descriptor
 	        name="principals"
 	        element-class-ref="org.apache.jetspeed.sso.impl.SSOPrincipalImpl"
@@ -176,5 +217,54 @@
 	        <fk-pointing-to-element-class column="PRINCIPAL_ID"/>
 	    </collection-descriptor>
 	</class-descriptor>
+	
+	<!-- SSO Cookie -->
+	
+	<class-descriptor
+	    class="org.apache.jetspeed.sso.impl.SSOCookieImpl"
+	    proxy="dynamic"
+	    table="SSO_COOKIE"
+	>
+	    <documentation>Represents the single sign on cookie</documentation>
+	    <field-descriptor
+	        name="cookieId"
+	        column="COOKIE_ID"
+	        jdbc-type="INTEGER"
+	        primarykey="true"
+	        indexed="true"
+	        autoincrement="true"
+	    >
+	    </field-descriptor>
+	    <field-descriptor
+	        name="cookie"
+	        column="COOKIE"
+	        jdbc-type="VARCHAR"
+	        nullable="false"
+	        length="1024"
+	    >
+	    </field-descriptor>
+	    <field-descriptor
+	        name="createDate"
+	        column="CREATE_DATE"
+	        jdbc-type="TIMESTAMP"
+	        nullable="false"
+	    >
+	    </field-descriptor>
+	    
+	    <collection-descriptor
+	        name="remotePrincipals"
+	        element-class-ref="org.apache.jetspeed.security.om.impl.InternalUserPrincipalImpl"
+	       proxy="true"
+	        refresh="true"
+	        auto-retrieve="true"
+	        auto-update="object"
+	        auto-delete="object"
+	        indirection-table="SSO_COOKIE_TO_REMOTE"
+	    >
+	        <documentation>This is the reference to principals for a cookie.</documentation>
+	        <fk-pointing-to-this-class column="COOKIE_ID"/>
+	        <fk-pointing-to-element-class column="REMOTE_PRINCIPAL_ID"/>
+	    </collection-descriptor>
+	    </class-descriptor>
 	
 </descriptor-repository>

Added: portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/portlet/sso/SSOProxyPortlet.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/portlet/sso/SSOProxyPortlet.java?rev=354497&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/portlet/sso/SSOProxyPortlet.java (added)
+++ portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/portlet/sso/SSOProxyPortlet.java Tue Dec  6 10:52:37 2005
@@ -0,0 +1,264 @@
+/* Copyright 2004 Apache Software Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/*Created on: Dec 5, 2005 */
+
+package org.apache.jetspeed.portlet.sso;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.util.StringTokenizer;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.PortletConfig;
+import javax.portlet.PortletContext;
+import javax.portlet.PortletException;
+import javax.portlet.PortletURL;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.security.auth.Subject;
+
+import org.apache.jetspeed.sso.SSOException;
+import org.apache.jetspeed.sso.SSOProvider;
+import org.apache.portals.bridges.common.ScriptPostProcess;
+import org.apache.portals.bridges.velocity.GenericVelocityPortlet;
+
+/**
+ * SSOProxyPortlet
+ * This portlet can be used as a bridge to any URL.
+ * It acts as a http client and therefore it can store
+ * cookies.
+ * The main purpose is that the SSOProxy portlet authenticates
+ * any SSO credential for the principal user not knowing in advance
+ * what URL the user might select. No login prompt will appear for any url
+ * in the portlet for that an SSO entry exists and the principal user has permissions.
+ * 
+ * @author Roger Ruttimann <ro...@apache.org>
+ *
+ */
+public class SSOProxyPortlet extends GenericVelocityPortlet {
+    private PortletContext context;
+    private SSOProvider sso;
+    
+    /* Re-use Proxy client inside the SSO Component */
+    private boolean isAuthenticated = false;
+    
+    /** Default encoding UTF-8*/
+    public String defaultEncoding = "UTF-8";
+    
+    /** Block Size */
+    static final int BLOCK_SIZE = 4096;
+    
+    /** ACTION_PARAMETER_SSOPROXY*/
+    static final String ACTION_PARAMETER_SSOPROXY = "SSOProxy";
+
+    
+    /** Preference values */
+    /** DestinationURL */
+    static final String DESTINATION_URL = "DestinationURL";
+    
+    /** SSOSite */
+    static final String SSO_SITE = "SSOSite";
+    
+    /** ForceSSORefresh*/
+    static final String FORCE_SSO_REFRESH = "ForceSSORefresh";
+    
+    /** Encoding*/
+    static final String ENCODING = "Encoding";
+
+    public void init(PortletConfig config) throws PortletException
+    {
+        super.init(config);
+        context = getPortletContext();
+        sso = (SSOProvider)context.getAttribute("cps:SSO");
+        if (null == sso)
+        {
+           throw new PortletException("Failed to find SSO Provider on portlet initialization");
+        }        
+    }
+    
+    public void processAction(ActionRequest request, ActionResponse actionResponse)
+    throws PortletException, IOException
+    {
+        // save the prefs
+        super.processAction(request, actionResponse);
+    }
+    
+    public void doView(RenderRequest request, RenderResponse response)
+    throws PortletException, IOException
+    {
+        String destinationURL = request.getPreferences().getValue(DESTINATION_URL, "");
+        String ssoSite = request.getPreferences().getValue(SSO_SITE, "");
+        String forceRefresh = request.getPreferences().getValue(FORCE_SSO_REFRESH, "false");
+        String encoding = request.getPreferences().getValue(ENCODING, this.defaultEncoding);
+
+        if (destinationURL == null)
+        {
+            // No destination configured Switch to configure View
+             request.setAttribute(PARAM_VIEW_PAGE, this.getPortletConfig().getInitParameter(PARAM_EDIT_PAGE));
+            setupPreferencesEdit(request, response);
+            super.doView(request, response);
+            return;
+        }
+        
+        /*
+         * Call into the SSO Proxy and process the result page
+         */
+        boolean doRefresh = false;
+        BufferedInputStream bis = null;
+        
+        if ( (forceRefresh.compareToIgnoreCase("TRUE") == 0) || this.isAuthenticated == false)
+        	doRefresh = true;
+       
+        try
+        {
+            Subject subject = getSubject(); 
+            if (ssoSite == null || ssoSite.length() ==0)
+            	bis = sso.useSSO(subject, destinationURL,doRefresh);
+            else
+            	bis = sso.useSSO(subject, destinationURL,ssoSite, doRefresh);
+            
+            // Authentication done at least once
+            this.isAuthenticated = true;
+            
+            bis.mark(BLOCK_SIZE);
+            String pageEncoding = getContentCharSet(bis);
+            if (pageEncoding == null)
+            {
+            	pageEncoding = encoding;
+            }
+            
+            Reader read = new InputStreamReader(bis, encoding);
+            StringBuffer page= new StringBuffer();
+            
+			char[] bytes = new char[BLOCK_SIZE];
+			
+			int len = read.read(bytes, 0, BLOCK_SIZE);			
+			while (len > 0)
+			{
+				page.append(bytes, 0, len);
+				len = read.read(bytes, 0, BLOCK_SIZE);
+			}
+			
+            //Done
+            read.close();
+            
+            // Rewrite
+			// Post Process for generated page		
+			PortletURL actionURL = response.createActionURL();
+			ScriptPostProcess processor = new ScriptPostProcess();
+			processor.setInitalPage(page);
+			processor.postProcessPage(actionURL, ACTION_PARAMETER_SSOPROXY);
+			String finalPage = processor.getFinalizedPage();
+			
+			// Write the page
+			response.getWriter().println(finalPage);
+        
+        }
+        catch (SSOException e)
+        {
+            if (e.getMessage().equals(SSOException.NO_CREDENTIALS_FOR_SITE))
+            {
+                // no credentials configured in SSO store
+                // switch to SSO Configure View
+                request.setAttribute(PARAM_VIEW_PAGE, this.getPortletConfig().getInitParameter(PARAM_EDIT_PAGE));
+                setupPreferencesEdit(request, response);    
+            }
+            else
+            {
+                throw new PortletException(e);
+            }
+        }          
+    }
+    
+
+    public void doEdit(RenderRequest request, RenderResponse response)
+    throws PortletException, IOException
+    {
+         super.doEdit(request, response);
+    }
+
+    /*
+     * Helper methods
+     */
+    private Subject getSubject()
+    {
+        AccessControlContext context = AccessController.getContext();
+        return Subject.getSubject(context);         
+    }
+    
+    private String getContentCharSet(InputStream is) throws IOException
+    {
+        if (!is.markSupported())
+        {
+            return null;
+        }
+
+        byte[] buf = new byte[BLOCK_SIZE];
+        try
+        {
+            is.read(buf, 0, BLOCK_SIZE);
+            String content = new String(buf, "ISO-8859-1");
+            String lowerCaseContent = content.toLowerCase();
+            int startIndex = lowerCaseContent.indexOf("<head");
+            if (startIndex == -1)
+            {
+                startIndex = 0;
+            }
+            int endIndex = lowerCaseContent.indexOf("</head");
+            if (endIndex == -1)
+            {
+                endIndex = content.length();
+            }
+            content = content.substring(startIndex, endIndex);
+
+            StringTokenizer st = new StringTokenizer(content, "<>");
+            while (st.hasMoreTokens())
+            {
+                String element = st.nextToken();
+                String lowerCaseElement = element.toLowerCase();
+                if (lowerCaseElement.startsWith("meta") && lowerCaseElement.indexOf("content-type") > 0)
+                {
+                    StringTokenizer est = new StringTokenizer(element, " =\"\';");
+                    while (est.hasMoreTokens())
+                    {
+                        if (est.nextToken().equalsIgnoreCase("charset"))
+                        {
+                            if (est.hasMoreTokens())
+                            {
+                                is.reset();
+                                return est.nextToken();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        catch (IOException e)
+        {
+        }
+
+        is.reset();
+
+        return null;
+    }
+   
+}

Modified: portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/PersistenceBrokerSSOProvider.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/PersistenceBrokerSSOProvider.java?rev=354497&r1=354496&r2=354497&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/PersistenceBrokerSSOProvider.java (original)
+++ portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/PersistenceBrokerSSOProvider.java Tue Dec  6 10:52:37 2005
@@ -15,6 +15,10 @@
  */
 package org.apache.jetspeed.sso.impl;
 
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.security.Principal;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -24,6 +28,7 @@
 import java.util.List;
 import java.util.Set;
 import java.util.StringTokenizer;
+import java.util.Vector;
 
 import org.apache.jetspeed.security.UserPrincipal;
 
@@ -32,6 +37,7 @@
 import org.apache.jetspeed.components.dao.InitablePersistenceBrokerDaoSupport;
 
 import org.apache.jetspeed.sso.SSOContext;
+import org.apache.jetspeed.sso.SSOCookie;
 import org.apache.jetspeed.sso.SSOException;
 import org.apache.jetspeed.sso.SSOProvider;
 import org.apache.jetspeed.sso.SSOSite;
@@ -58,6 +64,22 @@
 import org.apache.ojb.broker.query.QueryByCriteria;
 import org.apache.ojb.broker.query.QueryFactory;
 
+// HTTPClient imports
+import org.apache.commons.httpclient.Cookie;
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpConnection;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.httpclient.auth.AuthScheme;
+import org.apache.commons.httpclient.auth.HttpAuthenticator;
+import org.apache.commons.httpclient.cookie.CookiePolicy;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.MultipartPostMethod;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
 /**
 * <p>Utility component to handle SSO requests</p>
 * 
@@ -66,7 +88,14 @@
 public class PersistenceBrokerSSOProvider extends
 		InitablePersistenceBrokerDaoSupport implements SSOProvider 
 {	
-	private Hashtable mapSite = new Hashtable();	
+	/* Logging */
+	private static final Log log = LogFactory.getLog(PersistenceBrokerSSOProvider.class);
+	
+	/*
+	 * Cache for sites and Proxy sites
+	 */
+	private Hashtable mapSite = new Hashtable();
+	private Hashtable clientProxy = new Hashtable();
 	
     private String USER_PATH = "/user/";
     private String GROUP_PATH = "/group/";
@@ -83,7 +112,191 @@
     {
        super(repositoryPath);
     }
+    
+    
+    /*
+     *  (non-Javadoc)
+     * @see org.apache.jetspeed.sso.SSOProvider#useSSO(java.lang.String, java.lang.String, java.lang.String)
+     */
+    public BufferedInputStream useSSO(Subject subject, String url, String SSOSite, boolean bRefresh) throws SSOException
+    {
+    	// Get the principal from the subject
+		BasePrincipal principal = (BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class);
+		String fullPath = principal.getFullPath();
+		
+    	String content = null;
+    	
+    	/* ProxyID is used for the cache. The http client object will be cached for a
+    	 * given user site url combination
+    	 */
+    	String proxyID = fullPath + "_" + SSOSite;
+    	
+    	// Get the site
+    	SSOSite ssoSite = getSSOSiteObject(SSOSite);
+		
+		if ( ssoSite != null)
+		{
+			SSOSite[] sites = new SSOSite[1];
+			sites[0] = ssoSite;
+			
+			return this.getContentFromURL(proxyID, url, sites, bRefresh);
+		}
+		else
+		{
+			// Site doesn't exist -- log an error but continue
+			String msg = "SSO component -- useSSO can't retrive SSO credential because SSOSite [" + SSOSite + "] doesn't exist";
+			log.error(msg);
+			SSOSite[] sites = new SSOSite[0];
+			return this.getContentFromURL(proxyID, url, sites, bRefresh);
+		}
+     }
+    
+    /*
+     *  (non-Javadoc)
+     * @see org.apache.jetspeed.sso.SSOProvider#useSSO(java.lang.String, java.lang.String)
+     */
+    public BufferedInputStream useSSO(Subject subject, String url, boolean bRefresh) throws SSOException
+    {
+    	String content = null;
+       	// Get the principal from the subject
+		BasePrincipal principal = (BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class);
+		String fullPath = principal.getFullPath();
+
+    	
+    	/* ProxyID is used for the cache. The http client object will be cached for a
+    	 * given user 
+    	 */
+    	String proxyID = fullPath;
+    	
+    	Collection sites = this.getSitesForPrincipal(fullPath);
+    	
+    	if (sites == null)
+    	{
+    		String msg = "SSO Component useSSO -- Couldn't find any SSO sites for user ["+fullPath+"]";
+    		log.error(msg);
+    		throw new SSOException(msg);
+    	}
+    	
+    	// Load all the sites
+    	int siteSize = sites.size();
+    	int siteIndex =0;
+    	SSOSite[] ssoSites = new SSOSite[siteSize];
+    	
+    	Iterator itSites = sites.iterator();
+    	while(itSites.hasNext())
+    	{
+    		SSOSite ssoSite = (SSOSite)itSites.next();
+    		if (ssoSite != null)
+    		{
+    			ssoSites[siteIndex] = ssoSite;
+    			siteIndex++;
+    		}
+    	}
+    	
+    	return this.getContentFromURL(proxyID, url, ssoSites, bRefresh);
+    }
+    
+     /**
+     * Retrive cookies for an user by User full path
+     * @param fullPath
+     * @return
+     */
+    public Collection getCookiesForUser(String fullPath)
+    {
+    	// Get the SSO user identified by the fullPath
+    	SSOPrincipal ssoPrincipal = this.getSSOPrincipal(fullPath);
+    	
+    	// For each remote user we'll get the cookie
+    	Criteria remoteUserFilter = new Criteria();
+    	Vector temp = new Vector();
+    	
+    	Iterator itRemotePrincipal = ssoPrincipal.getRemotePrincipals().iterator();
+    	while (itRemotePrincipal.hasNext())
+    	{
+    		InternalUserPrincipal rp  = (InternalUserPrincipal)itRemotePrincipal.next();
+    		if (rp != null)
+    		{
+    			temp.add(rp.getFullPath());
+    		}
+    	}
+    	
+    	if (temp.size() > 0)
+    	{
+    	
+	        Criteria filter = new Criteria();   
+	        filter.addIn("remotePrincipals.fullPath", temp);
+	         
+	        QueryByCriteria query = QueryFactory.newQuery(SSOCookieImpl.class, filter);
+	        return getPersistenceBrokerTemplate().getCollectionByQuery(query);
+    	}
+    	else
+    	{
+    		return null;
+    	}
+
+    }
+    
+    /**
+     * Retrive Cookies by Subject
+     * @param user
+     * @return
+     */
+    public Collection getCookiesForUser(Subject user)
+    {
+    	// Get the principal from the subject
+		BasePrincipal principal = (BasePrincipal)SecurityHelper.getBestPrincipal(user, UserPrincipal.class);
+		String fullPath = principal.getFullPath();
+		
+		// Call into API
+		return this.getCookiesForUser(fullPath);
+    }
+    
 
+    public void setRealmForSite(String site, String realm) throws SSOException
+    {
+    	SSOSite ssoSite = getSSOSiteObject(site);
+		
+		if ( ssoSite != null)
+		{
+			try
+			{
+				ssoSite.setRealm(realm);
+				getPersistenceBrokerTemplate().store(ssoSite);
+			}
+			catch (Exception e)
+			{
+				throw new SSOException("Failed to set the realm for site [" + site + "] Error" +e );
+			}
+		}
+    }
+    
+    public String getRealmForSite(String site) throws SSOException
+    {
+    	SSOSite ssoSite = getSSOSiteObject(site);
+		
+		if ( ssoSite != null)
+		{
+			return ssoSite.getRealm();
+		}
+		
+		return null;
+    }
+    
+    /**
+     * Get all SSOSites that the principal has access to
+     * @param userId
+     * @return
+     */
+    public Collection getSitesForPrincipal(String fullPath)
+    {
+   	
+    	Criteria filter = new Criteria();       
+        filter.addEqualTo("principals.fullPath", fullPath);
+        
+        QueryByCriteria query = QueryFactory.newQuery(SSOSiteImpl.class, filter);
+        return getPersistenceBrokerTemplate().getCollectionByQuery(query); 
+    }
+    
 	public Iterator getSites(String filter)
     {
         Criteria queryCriteria = new Criteria();
@@ -179,7 +392,7 @@
     {
         SSOSite ssoSite = getSSOSiteObject(site);
 		
-		if ( ssoSite == null)
+		if ( ssoSite != null)
 		{
 			return ssoSite.getName();
 		}
@@ -272,6 +485,20 @@
 			ssoSite.setName(site);
 			ssoSite.setCertificateRequired(false);
 			ssoSite.setAllowUserSet(true);
+			// By default we use ChallengeResponse Authentication
+			ssoSite.setChallengeResponseAuthentication(true);
+			ssoSite.setFormAuthentication(false);
+			
+			// Store the site so that we get a valid SSOSiteID
+			try
+	         {
+	             getPersistenceBrokerTemplate().store(ssoSite);
+	          }
+	         catch (Exception e)
+	         {
+	         	e.printStackTrace();
+	            throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
+	         }
 		}
 		
 		// Get the Principal information (logged in user)
@@ -321,7 +548,7 @@
 		    remotePrincipal.setFullPath("/sso/" + ssoSite.getSiteId() + "/group/"+  principalName + "/" + remoteUser);
 		else
 		    remotePrincipal.setFullPath("/sso/" + ssoSite.getSiteId() + "/user/"+ principalName + "/" + remoteUser);
-	
+		
 		// New credential object for remote principal
 		 InternalCredentialImpl credential = 
             new InternalCredentialImpl(remotePrincipal.getPrincipalId(),
@@ -334,20 +561,25 @@
 		
 		// Add it to Principals remotePrincipals list
 		principal.addRemotePrincipal(remotePrincipal);
-		
+
 		// Update the site remotePrincipals list
 		ssoSite.getRemotePrincipals().add(remotePrincipal);
+		
 		 	
 		// Update database and reset cache
 		 try
          {
              getPersistenceBrokerTemplate().store(ssoSite);
+             
+             // Persist Principal/Remote
+     		getPersistenceBrokerTemplate().store(principal);
           }
          catch (Exception e)
          {
          	e.printStackTrace();
             throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
          }
+         
          // Add to site
          this.mapSite.put(site, ssoSite);
 	}
@@ -392,14 +624,19 @@
 			{
 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
 			}
-			
+
 			// Update assocation tables
 			ssoSite.getRemotePrincipals().remove(remotePrincipal);
-			remoteForPrincipals.remove(remotePrincipal);
-		    
+			
+			if (remoteForPrincipals.remove(remotePrincipal) == true)
+			
+			// Update the site
+			getPersistenceBrokerTemplate().store(ssoSite);
+
 			// delete the remote Principal from the SECURITY_PRINCIPAL table
 		    getPersistenceBrokerTemplate().delete(remotePrincipal);
-			
+		    
+						
 		}
 		catch(SSOException ssoex)
 		{
@@ -471,7 +708,8 @@
 			}
 						
 			// Update principal information
-			remotePrincipal.setFullPath("/sso/user/"+ principalName + "/" + remoteUser);
+			//remotePrincipal.setFullPath("/sso/" + ssoSite.getSiteId() + "/user/"+ principalName + "/" + remoteUser);
+			
 			InternalCredential credential = (InternalCredential)remotePrincipal.getCredentials().iterator().next();
 					
 			// New credential object
@@ -482,7 +720,7 @@
 			// Update database and reset cache
 			 try
 			 {
-			     getPersistenceBrokerTemplate().store(ssoSite);
+			     getPersistenceBrokerTemplate().store(credential);
 			  }
 			 catch (Exception e)
 			 {
@@ -923,4 +1161,181 @@
         return group;       
     }
     
+    private SSOSite getSiteForRemoteUser(String fullPath)
+    {
+    	// Get Site for remote user
+        Criteria filter = new Criteria();
+        filter.addEqualTo("remotePrincipals.fullPath", fullPath);
+        Query query = QueryFactory.newQuery(SSOSiteImpl.class, filter);
+        return  (SSOSite) getPersistenceBrokerTemplate().getObjectByQuery(query);
+    }
+    
+    private BufferedInputStream getContentFromURL(String proxyID, String destUrl, SSOSite[] sites, boolean bRefresh ) throws SSOException
+    {
+    	URL urlObj = null;
+    	
+    	// Result Buffer
+    	BufferedInputStream bis = null;
+    	
+    	String strErrorMessage = "SSO Component Error. Failed to get content for URL " + destUrl;
+    	
+    	try
+    	{
+    		urlObj = new URL(destUrl);
+    	}
+    	catch (MalformedURLException e)
+    	{
+    		String msg = ("Error -- Malformed URL [" + destUrl +"] for SSO authenticated destination");
+    		log.error(msg);
+    		throw new SSOException(msg, e);
+    	}
+    	
+    	/* 
+    	 * Setup HTTPClient
+    	 * Check if an HTTP Client already exists for the given /user/site
+    	 */
+    	HttpClient client = (HttpClient)this.clientProxy.get(proxyID);
+    	GetMethod get = null;
+    	
+    	if (bRefresh == true || client == null)
+    	{
+    		if (log.isInfoEnabled())
+    			log.info("SSO Component -- Create new HTTP Client object for Principal/URL [" + proxyID+ "]");
+    		
+	    	client = new HttpClient();
+	    	client.getState().setCookiePolicy(CookiePolicy.COMPATIBILITY);
+	    	
+	    	int numberOfSites = sites.length;
+	    	
+	    	// Do all the logins for the site
+	    	for (int i=0; i<numberOfSites; i++)
+	    	{
+	    		SSOSite site = sites[i];
+	    		
+	    		if (site != null)
+	    		{
+	    			Iterator itRemotePrincipals = site.getRemotePrincipals().iterator();
+	    			while (itRemotePrincipals.hasNext() )
+	    			{
+	    				InternalUserPrincipal remotePrincipal = (InternalUserPrincipal)itRemotePrincipals.next();
+	            		if (remotePrincipal != null)
+	            		{
+	            			InternalCredential credential = null;
+	            			if ( remotePrincipal.getCredentials() != null)
+	            				credential = (InternalCredential)remotePrincipal.getCredentials().iterator().next();
+	            			
+	            			if (credential != null)
+	            			{
+	            				client.getState().setCredentials(
+	            		    			site.getRealm(),
+	            		                urlObj.getHost(),
+	            		                new UsernamePasswordCredentials(stripPrincipalName(remotePrincipal.getFullPath()),  credential.getValue())
+	            		            );
+	            				
+	            				// Build URL if it's Form authentication
+	            				StringBuffer siteURL = new StringBuffer(site.getSiteURL());
+		       					
+		        				// Check if it's form based or ChallengeResponse
+	        					if (site.isFormAuthentication())
+	        					{
+	        						siteURL.append("?").append(site.getFormUserField()).append("=").append(stripPrincipalName(remotePrincipal.getFullPath())).append("&").append(site.getFormPwdField()).append("=").append(credential.getValue());
+	        					}
+	            				
+	            				get = new GetMethod(siteURL.toString());
+	
+	            	            // Tell the GET method to automatically handle authentication. The
+	            	            // method will use any appropriate credentials to handle basic
+	            	            // authentication requests.  Setting this value to false will cause
+	            	            // any request for authentication to return with a status of 401.
+	            	            // It will then be up to the client to handle the authentication.
+	            	            get.setDoAuthentication( true );
+	            	            try {
+	            	                // execute the GET
+	            	                int status = client.executeMethod( get );
+	            	                
+	            	                if (log.isInfoEnabled() )
+	            	                		log.info("Accessing site [" + site.getSiteURL() + "]. HTTP Status [" +status+ "]" );
+	            	                
+	            	                /*
+	            	    	    	 * If the destination URL and the SSO url match
+	            	    	    	 * use the authentication process but return immediately
+	            	    	    	 * the result page.
+	            	    	    	 */
+	            	                if( destUrl.compareTo(site.getSiteURL()) == 0 && numberOfSites == 1)
+	            	                {
+	            	                	if (log.isInfoEnabled() )
+	            	                		log.info("SSO Component --SSO Site and destination URL match. Go and get the content." );
+	            	                	
+	            	                	try
+	            	            		{
+	            	            			bis = new BufferedInputStream(get.getResponseBodyAsStream());
+	            	            		}
+	            	            		catch(IOException ioe)
+	            	            		{
+	            	            			log.error(strErrorMessage, ioe);
+	            	            			throw new SSOException (strErrorMessage, ioe);	
+	            	            		}
+
+	            	            		get.releaseConnection();
+	            	            		
+	            	            		//	Add the client object to the cache
+	            	        	    	this.clientProxy.put(proxyID, client);
+	            	            		
+	            	            		return bis;
+	            	                }
+	            	        
+		            			} catch (Exception e) {
+		                        	log.error("Exception while authentication. Error: " +e);	                        
+		                        }
+		            			
+		            			get.releaseConnection();
+	             			}
+	            		}
+	    			}
+	    		}   		
+	    	}
+	    	
+	    	// Add the client object to the cache
+	    	this.clientProxy.put(proxyID, client);
+    	}
+    	else
+    	{
+    		if (log.isInfoEnabled())
+    			log.info("SSO Component -- Use cached HTTP Client object for Principal/URL [" + proxyID+ "]");
+    	}
+    	
+    	// All the SSO authentication done go to the destination url
+		get = new GetMethod(destUrl);
+		try {
+            // execute the GET
+            int status = client.executeMethod( get );
+            
+            log.info("Accessing site [" + destUrl + "]. HTTP Status [" +status+ "]" );
+    
+		} catch (Exception e) {
+        	log.error("Exception while authentication. Error: " +e);	                        
+        }
+		
+		
+		try
+		{
+			bis = new BufferedInputStream(get.getResponseBodyAsStream());
+		}
+		catch(IOException ioe)
+		{
+			log.error(strErrorMessage, ioe);
+			throw new SSOException (strErrorMessage, ioe);
+			
+		}
+		catch (Exception e)
+		{
+			log.error(strErrorMessage, e);
+			throw new SSOException (strErrorMessage, e);
+			
+		}
+		
+		get.releaseConnection();
+		
+		return bis;
+    }
 }

Added: portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOCookieImpl.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOCookieImpl.java?rev=354497&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOCookieImpl.java (added)
+++ portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOCookieImpl.java Tue Dec  6 10:52:37 2005
@@ -0,0 +1,102 @@
+/* Copyright 2004 Apache Software Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/*Created on: Nov 23, 2005 */
+
+package org.apache.jetspeed.sso.impl;
+
+import java.sql.Blob;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Collection;
+import java.util.Vector;
+
+import org.apache.jetspeed.sso.SSOCookie;
+
+/**
+ * @author Roger Ruttimann <ro...@apache.org>
+ *
+ */
+public class SSOCookieImpl implements SSOCookie {
+	
+	/**
+	 * Internal for storing object values
+	 */
+	
+	private int cookieId;
+	private String cookie;
+	private Timestamp createDate;
+	private Collection remotePrincipals = new Vector();
+
+	/* (non-Javadoc)
+	 * @see org.apache.jetspeed.sso.SSOCookie#setCookieId(int)
+	 */
+	public void setCookieId(int cookieId) {
+		this.cookieId = cookieId;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.jetspeed.sso.SSOCookie#getCookieId()
+	 */
+	public int getCookieId() {
+		return this.cookieId;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.jetspeed.sso.SSOCookie#setCookie(java.lang.String)
+	 */
+	public void setCookie(String cookieValue) {
+		this.cookie = cookieValue;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.jetspeed.sso.SSOCookie#getCookie()
+	 */
+	public String getCookie() {
+		return this.cookie;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.jetspeed.sso.SSOCookie#setCreateDate(java.sql.Timestamp)
+	 */
+	public void setCreateDate(Timestamp createDate) {
+		this.createDate = createDate;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.jetspeed.sso.SSOCookie#getCreateDate()
+	 */
+	public Timestamp getCreateDate() {
+		return this.createDate;
+	}
+	
+	/**
+	 * 
+	 * @return
+	 */
+	public Collection getRemotePrincipals()
+	{
+		return this.remotePrincipals;
+	}
+	
+	/**
+	 * 
+	 * @param remotePrincipals
+	 */
+	public void setRemotePrincipals(Collection remotePrincipals)
+	{
+		this.remotePrincipals = remotePrincipals;
+	}
+}

Modified: portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOPrincipalImpl.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOPrincipalImpl.java?rev=354497&r1=354496&r2=354497&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOPrincipalImpl.java (original)
+++ portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOPrincipalImpl.java Tue Dec  6 10:52:37 2005
@@ -18,6 +18,7 @@
 import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Vector;
 
 import org.apache.jetspeed.security.om.InternalUserPrincipal;
 import org.apache.jetspeed.sso.SSOPrincipal;
@@ -57,7 +58,7 @@
 	   private Collection permissions;
 	   
 	   /** Remote principals for Principal */
-	   private Collection remotePrincipals;
+	   private Collection remotePrincipals = new Vector();
 	   
 	   /** SIteID for Remote principal */
 	   private int siteID;
@@ -106,10 +107,11 @@
 	    */
 	   public void  addRemotePrincipal(InternalUserPrincipal principal)
 	   {
-	   		if (remotePrincipals == null)
+	   	/*	if (remotePrincipals == null)
 	   		{
 	   			remotePrincipals = new ArrayList(1);
 	   		}
+	   	*/
 	   		
 	   		remotePrincipals.add(principal);
 	   }

Modified: portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOSiteImpl.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOSiteImpl.java?rev=354497&r1=354496&r2=354497&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOSiteImpl.java (original)
+++ portals/jetspeed-2/trunk/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOSiteImpl.java Tue Dec  6 10:52:37 2005
@@ -42,6 +42,18 @@
 	private boolean	isAllowUserSet;
 	private boolean isCertificateRequired;
 	
+	private boolean	isChallangeResponseAuthentication;
+	
+	/* Realm used to do ChallengeResponse Authentication */
+	private String	realm;
+	
+	private boolean	isFormAuthentication;
+	
+	/* Names of fields for User and Password values. The names are up to the
+	 * application developer and therefore it must be configurable for SSO*/
+	private String	formUserField;
+	private String	formPwdField;
+	
 	private Collection	principals = new Vector();
 	private Collection	remotePrincipals = new Vector();
 	
@@ -207,4 +219,87 @@
         this.remotePrincipals = remotePrincipals;
     }
     
+    /**
+     * Define the Authentication methods. 
+     * Supported are: Challenge Response and From based
+     */
+    /**
+     * Form authentication requires two fields that hold the credential 
+     * information for the request.
+     */
+    public void setFormAuthentication(String formUserField, String formPwdField)
+    {
+    	// Set the fields for Form Authentication and clear other authentication methods
+    	
+    }
+    
+    /*
+     * Uses Challenge Response mechanism for authentication
+     */
+    public void setChallengeResponseAuthentication()
+    {
+    	// Set the fields for ChallengeResponse and clear other authentication methods
+    	
+    }
+
+    /* Setters/Getters for Authentication settings */
+	public String getFormPwdField() {
+		return formPwdField;
+	}
+
+	public void setFormPwdField(String formPwdField) {
+		this.formPwdField = formPwdField;
+	}
+
+	public String getFormUserField() {
+		return formUserField;
+	}
+
+	public void setFormUserField(String formUserField) {
+		this.formUserField = formUserField;
+	}
+
+	public boolean isChallangeResponseAuthentication() {
+		return isChallangeResponseAuthentication;
+	}
+
+	public void setChallengeResponseAuthentication(
+			boolean isChallangeResponseAuthentication) {
+		this.isChallangeResponseAuthentication = isChallangeResponseAuthentication;
+	}
+
+	public boolean isFormAuthentication() {
+		return isFormAuthentication;
+	}
+
+	public void setFormAuthentication(boolean isFormAuthentication) {
+		this.isFormAuthentication = isFormAuthentication;
+	}
+	
+	public void configFormAuthentication(String formUserField, String formPwdField)
+	{
+		this.isFormAuthentication = true;
+		this.setChallengeResponseAuthentication(false);
+		
+		this.formPwdField	=	formPwdField;
+		this.formUserField	=	formUserField;
+	}
+	
+	/*
+	 *  (non-Javadoc)
+	 * @see org.apache.jetspeed.sso.SSOSite#setRealm(java.lang.String)
+	 */
+	public void setRealm(String realm)
+	{
+		this.realm = realm;
+	}
+	
+	/*
+	 *  (non-Javadoc)
+	 * @see org.apache.jetspeed.sso.SSOSite#getRealm()
+	 */
+	public String getRealm()
+	{
+		return this.realm;
+	}    
 }

Modified: portals/jetspeed-2/trunk/components/sso/src/test/org/apache/jetspeed/sso/TestSSOComponent.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/sso/src/test/org/apache/jetspeed/sso/TestSSOComponent.java?rev=354497&r1=354496&r2=354497&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/sso/src/test/org/apache/jetspeed/sso/TestSSOComponent.java (original)
+++ portals/jetspeed-2/trunk/components/sso/src/test/org/apache/jetspeed/sso/TestSSOComponent.java Tue Dec  6 10:52:37 2005
@@ -49,17 +49,17 @@
      */
     static private String TEST_URL = "http://localhost/jetspeed";
 
-    static private String TEST_URL2 = "http://localhost/jetspeed-2";
+    static private String TEST_URL2 = "http://192.168.2.63/nagios/cgi-bin/status.cgi?hostgroup=all&style=hostdetail";
 
     static private String TEST_USER = "joe";
 
     static private String REMOTE_USER = "remoteJS";
 
-    static private String REMOTE_USER2 = "remoteJS-2";
+    static private String REMOTE_USER2 = "nagiosadmin";
 
     static private String REMOTE_PWD_1 = "remote_1";
 
-    static private String REMOTE_PWD_2 = "remote_2";
+    static private String REMOTE_PWD_2 = "nagiosadmin";
 
     static private String TEST_GROUP = "engineers";
 
@@ -291,7 +291,9 @@
             // Add credential
             try
             {
-                ssoBroker.addCredentialsForSite(subject, REMOTE_USER2, TEST_URL2, REMOTE_PWD_1);
+                ssoBroker.addCredentialsForSite(subject, REMOTE_USER2, TEST_URL2, REMOTE_PWD_2);
+                ssoBroker.setRealmForSite(TEST_URL2, "Nagios Access");
+                
                 System.out.println("SSO Credential added for user:" + TEST_USER + " site: " + TEST_URL2);
             }
             catch (SSOException ssoex)
@@ -309,13 +311,13 @@
         // Add the credentail again -- should get an error
         try
         {
-            ssoBroker.addCredentialsForSite(subject, REMOTE_USER2, TEST_URL2, REMOTE_PWD_1);
+            ssoBroker.addCredentialsForSite(subject, REMOTE_USER2, TEST_URL2, REMOTE_PWD_2);
             throw new Exception("Added same credentail twice -- API should prevent users from doing that.");
 
         }
         catch (SSOException ssoex)
         {
-            System.out.println("Adding same SSO Credentialtwice failed (as expected) Message :" + ssoex.getMessage());
+            System.out.println("Adding same SSO Credential twice failed (as expected) Message :" + ssoex.getMessage());
         }
         catch (Exception e)
         {
@@ -349,7 +351,10 @@
             System.out.println("SSO Credential update FAILED for user:" + TEST_USER + " site: " + TEST_URL);
             throw new Exception(ssoex.getMessage());
         }
-
+        
+        // Test login logout for given user
+        ssoBroker.useSSO(subject, TEST_URL2, false);
+ 
         /*
          * For hypersonic the cascading deletes are not generated by Torque and the remove credentials fails with a
          * constraint error. Comment test out for M1 release but the problem needs to be addressed for the upcoming
@@ -364,6 +369,18 @@
         {
             SSOSite site = (SSOSite) sites.next();
             System.out.println("Site = " + site.getName());
+        }
+        // Cleanup
+        try
+        {
+        	ssoBroker.removeCredentialsForSite(subject, TEST_URL);
+        	ssoBroker.removeCredentialsForSite(subject, TEST_URL2);
+        	System.out.println("SSO Credential removed for user:" + TEST_USER+ " sites: " + TEST_URL + " " + TEST_URL2); 
+        }
+        catch(SSOException ssoex) 
+        { 
+        	System.out.println("SSO Credential remove FAILED for user:" + TEST_USER+ " site: " + TEST_URL + " and " + TEST_URL2); 
+        	throw new Exception(ssoex.getMessage());
         }
 
     }

Modified: portals/jetspeed-2/trunk/etc/schema/security-schema.xml
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/etc/schema/security-schema.xml?rev=354497&r1=354496&r2=354497&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/etc/schema/security-schema.xml (original)
+++ portals/jetspeed-2/trunk/etc/schema/security-schema.xml Tue Dec  6 10:52:37 2005
@@ -101,11 +101,22 @@
         <column name="URL" required="true" size="254" type="VARCHAR"/>
         <column name="ALLOW_USER_SET" default="0" type="BOOLEANINT"/>
         <column name="REQUIRES_CERTIFICATE" default="0" type="BOOLEANINT"/>
+        <column name="CHALLENGE_RESPONSE_AUTH" default="0" type="BOOLEANINT"/>
+        <column name="FORM_AUTH" default="0" type="BOOLEANINT"/>
+        <column name="FORM_USER_FIELD" required="false" size="128" type="VARCHAR"/>
+        <column name="FORM_PWD_FIELD" required="false" size="128" type="VARCHAR"/>
+        <column name="REALM" required="false" size="128" type="VARCHAR"/>
+        
         <unique name="UIX_SITE_URL">
           <unique-column name="URL" />
         </unique>                
     </table>
-	
+    
+    <table name="SSO_COOKIE">
+        <column name="COOKIE_ID" primaryKey="true" required="true" type="INTEGER"/>
+        <column name="COOKIE" required="true" size="1024" type="VARCHAR"/> 
+        <column name="CREATE_DATE" required="true" type="TIMESTAMP"/>         
+    </table>
 	
     <table name="SSO_SITE_TO_PRINCIPALS">
     	<column name="SITE_ID" primaryKey="true" required="true" type="INTEGER"/>
@@ -136,11 +147,24 @@
     <table name="SSO_SITE_TO_REMOTE">
     	<column name="SITE_ID" primaryKey="true" required="true" type="INTEGER"/>
         <column name="PRINCIPAL_ID" primaryKey="true" required="true" type="INTEGER"/>
+           
          <foreign-key foreignTable="SSO_SITE" onDelete="cascade">
             <reference foreign="SITE_ID" local="SITE_ID"/>
         </foreign-key>
        <foreign-key foreignTable="SECURITY_PRINCIPAL" onDelete="cascade">
             <reference foreign="PRINCIPAL_ID" local="PRINCIPAL_ID"/>
+        </foreign-key>
+    </table>
+    
+    <table name="SSO_COOKIE_TO_REMOTE">
+    	<column name="COOKIE_ID" primaryKey="true" required="true" type="INTEGER"/>
+        <column name="REMOTE_PRINCIPAL_ID" primaryKey="true" required="true" type="INTEGER"/>
+           
+         <foreign-key foreignTable="SSO_COOKIE" onDelete="cascade">
+            <reference foreign="COOKIE_ID" local="COOKIE_ID"/>
+        </foreign-key>
+       <foreign-key foreignTable="SECURITY_PRINCIPAL" onDelete="cascade">
+            <reference foreign="PRINCIPAL_ID" local="REMOTE_PRINCIPAL_ID"/>
         </foreign-key>
     </table>
          

Added: portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOCookie.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOCookie.java?rev=354497&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOCookie.java (added)
+++ portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOCookie.java Tue Dec  6 10:52:37 2005
@@ -0,0 +1,80 @@
+/* Copyright 2004 Apache Software Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/*Created on: Nov 23, 2005 */
+
+package org.apache.jetspeed.sso;
+
+import java.sql.Timestamp;
+import java.util.Collection;
+
+/**
+ * Interface SSOCookie
+ * 
+ * @author Roger Ruttimann <ro...@apache.org>
+ * 
+ * Class sthat handles the cookies created for SSO
+ * principals
+ *
+ */
+public interface SSOCookie {
+
+	/** Setters and getters for cookie properties */
+	
+	/**
+	 * 
+	 * @param cookieId
+	 */
+	void setCookieId(int cookieId);
+	/**
+	 * 
+	 * @return
+	 */
+	int	getCookieId();
+	
+	/**
+	 * 
+	 * @param cookieValue
+	 */
+	void setCookie(String cookieValue);
+	/**
+	 * 
+	 * @return
+	 */
+	String getCookie();
+	
+	/**
+	 * 
+	 * @param createDate
+	 */
+	void setCreateDate(Timestamp createDate);
+	/**
+	 * 
+	 * @return
+	 */
+	Timestamp getCreateDate();
+	
+	/**
+	 * 
+	 * @return
+	 */
+	Collection getRemotePrincipals();
+	
+	/**
+	 * 
+	 * @param remotePrincipals
+	 */
+	void setRemotePrincipals(Collection remotePrincipals);
+}

Modified: portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOProvider.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOProvider.java?rev=354497&r1=354496&r2=354497&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOProvider.java (original)
+++ portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOProvider.java Tue Dec  6 10:52:37 2005
@@ -14,6 +14,8 @@
 */
 package org.apache.jetspeed.sso;
 
+import java.io.BufferedInputStream;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 
@@ -35,6 +37,49 @@
    void init() throws Exception;
    
    /**
+    * This method first authenticates the the SSOSite and then forwards the request
+    * to the destination URL. The content will be returned as a string.
+    * If the SSOSite and the url match only one call will be executed since the
+    * authentication will be done while getting the result page.
+    * 
+    * @param userID
+    * @param url
+    * @param SSOSite
+    * @param bRefresh if true it refreshes the proxy connection if false a cached proxy will be used
+    * @return
+    * @throws SSOException
+    */
+   public BufferedInputStream useSSO(Subject subject, String url, String SSOSite, boolean bRefresh) throws SSOException;
+   
+   /**
+    * Same as the method above except that the user will be authenticated against all
+    * SSOSites defined for the user before going to the destination site.
+    * 
+    * @param userID
+    * @param url
+    * @param bRefresh if true it refreshes the proxy connection if false a cached proxy will be used
+    * @return
+    * @throws SSOException
+    */
+   public BufferedInputStream useSSO(Subject subject, String url, boolean bRefresh) throws SSOException;
+   
+    
+   /**
+    * Retrive cookies for an user by User full path
+    * @param fullPath
+    * @return
+    */
+   Collection getCookiesForUser(String fullPath);
+   
+   /**
+    * Retrive Cookies by Subject
+    * @param user
+    * @return
+    */
+   Collection getCookiesForUser(Subject user);
+   
+   
+   /**
     * Public API's for SSO functinality
     * @return
     */
@@ -92,5 +137,15 @@
     /* Retrive site information */
     String getSiteURL(String site);
     String getSiteName(String site); 
+    
+    void	setRealmForSite(String site, String realm) throws SSOException;
+    String	getRealmForSite(String site) throws SSOException;
+    
+    /**
+     * Get all SSOSites that the principal has access to
+     * @param userId
+     * @return
+     */
+    public Collection getSitesForPrincipal(String userId);
     
 }

Modified: portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOSite.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOSite.java?rev=354497&r1=354496&r2=354497&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOSite.java (original)
+++ portals/jetspeed-2/trunk/jetspeed-api/src/java/org/apache/jetspeed/sso/SSOSite.java Tue Dec  6 10:52:37 2005
@@ -1,16 +1,18 @@
-/*
- * Created on Nov 19, 2004
- *
- * Copyright 2003-2004 Groundwork Open Source Solution.
- * 
- *      http://www.itgroundwork.com
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+/* Copyright 2004 Apache Software Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
 package org.apache.jetspeed.sso;
 
 import java.util.Collection;
@@ -107,4 +109,34 @@
      * setRemotePrincipals 
      */
     public void setRemotePrincipals(Collection remotePrincipals);
+    
+    /**
+     * Define the Authentication methods. 
+     * Supported are: Challenge Response and From based
+     */
+    public void setFormAuthentication(boolean isFormAuthentication);
+   
+    /**
+     * Form authentication requires two fields that hold the credential 
+     * information for the request.
+     */
+   
+    public void configFormAuthentication(String formUserField, String formPwdField);
+    
+    /*
+     * Uses Challenge Response mechanism for authentication
+     */
+    public void setChallengeResponseAuthentication(boolean isChallengeResponseAuthentication);
+    
+    public boolean isChallangeResponseAuthentication();
+	public boolean isFormAuthentication();
+
+	public String getFormPwdField();
+	public void setFormPwdField(String formPwdField);
+
+	public String getFormUserField();
+	public void setFormUserField(String formUserField);
+	
+	public void setRealm(String realm);
+	public String getRealm();
 }

Modified: portals/jetspeed-2/trunk/src/webapp/WEB-INF/assembly/sso.xml
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/src/webapp/WEB-INF/assembly/sso.xml?rev=354497&r1=354496&r2=354497&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/src/webapp/WEB-INF/assembly/sso.xml (original)
+++ portals/jetspeed-2/trunk/src/webapp/WEB-INF/assembly/sso.xml Tue Dec  6 10:52:37 2005
@@ -38,6 +38,9 @@
                 <prop key="addCredentialsForSite">PROPAGATION_REQUIRED</prop>
                 <prop key="updateCredentialsForSite">PROPAGATION_REQUIRED</prop>
                 <prop key="removeCredentialsForSite">PROPAGATION_REQUIRED</prop>
+                <prop key="login">PROPAGATION_REQUIRED</prop>
+                <prop key="logout">PROPAGATION_REQUIRED</prop>
+                <prop key=" setRealmForSite">PROPAGATION_REQUIRED</prop>
                 <prop key="*">PROPAGATION_SUPPORTS</prop>
             </props>
         </property>



---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
For additional commands, e-mail: jetspeed-dev-help@portals.apache.org