diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java
index 772c6531a7cdfc147731f570795620cbde4dd3c6..1d4af6cbc290703f8058d09a5f54c1562c17eaf1 100755
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java
@@ -77,7 +77,9 @@ import ca.nrc.cadc.ac.UserNotFoundException;
 import ca.nrc.cadc.ac.UserRequest;
 import ca.nrc.cadc.auth.AuthenticationUtil;
 import ca.nrc.cadc.auth.HttpPrincipal;
+import ca.nrc.cadc.auth.NumericPrincipal;
 import ca.nrc.cadc.net.TransientException;
+
 import com.unboundid.ldap.sdk.AddRequest;
 import com.unboundid.ldap.sdk.Attribute;
 import com.unboundid.ldap.sdk.BindRequest;
@@ -100,9 +102,11 @@ import com.unboundid.ldap.sdk.SimpleBindRequest;
 import com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV2RequestControl;
 import com.unboundid.ldap.sdk.extensions.PasswordModifyExtendedRequest;
 import com.unboundid.ldap.sdk.extensions.PasswordModifyExtendedResult;
+
 import org.apache.log4j.Logger;
 
 import javax.security.auth.x500.X500Principal;
+
 import java.security.AccessControlException;
 import java.security.Principal;
 import java.util.ArrayList;
@@ -459,7 +463,6 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
             SearchRequest searchRequest =
                     new SearchRequest(usersDN, SearchScope.SUB,
                                       searchField, userAttribs);
-
             if (isSecure(usersDN))
             {
                 searchRequest.addControl(
@@ -480,10 +483,13 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
             logger.debug(msg);
             throw new UserNotFoundException(msg);
         }
+
         User<T> user = new User<T>(userID);
         user.getIdentities().add(new HttpPrincipal(searchResult.getAttributeValue(
             userLdapAttrib.get(HttpPrincipal.class))));
-
+        String dn = searchResult.getAttributeValue(LDAP_DISTINGUISHED_NAME);
+        user.getIdentities().add(new X500Principal(dn));
+        
         String fname = searchResult.getAttributeValue(LDAP_FIRST_NAME);
         String lname = searchResult.getAttributeValue(LDAP_LAST_NAME);
         PersonalDetails personaDetails = new PersonalDetails(fname, lname);
diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java
index 4793c719fb078488473eaca1bbb215c17a9a2aac..dfef465d1e458e08465df2ddf9952b15dfe15d34 100644
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java
@@ -137,7 +137,6 @@ public class GetUserAction extends AbstractUserAction
     
     protected boolean isServops()
     {
-    	log.debug("alinga-- isServops(): augmentUserDN = " + this.augmentUserDN);
     	boolean isServops = false;
         AccessControlContext acc = AccessController.getContext();
         Subject subject = Subject.getSubject(acc);
diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UserActionFactory.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UserActionFactory.java
index ae8ec41014d2f0ed8d67a7bc50a664c270de1542..6982a37b96dfbd72cb1cb513605aba727dc15221 100644
--- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UserActionFactory.java
+++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UserActionFactory.java
@@ -234,24 +234,24 @@ public abstract class UserActionFactory
         {
             throw new IllegalArgumentException("User endpoint missing idType parameter");
         }
-        else if (idType.equals(IdentityType.USERNAME.getValue()))
+        else if (idType.equalsIgnoreCase(IdentityType.USERNAME.getValue()))
         {
             return new User<HttpPrincipal>(new HttpPrincipal(userName));
         }
-        else if (idType.equals(IdentityType.X500.getValue()))
+        else if (idType.equalsIgnoreCase(IdentityType.X500.getValue()))
         {
             return new User<X500Principal>(new X500Principal(userName));
         }
-        else if (idType.equals(IdentityType.UID.getValue()))
+        else if (idType.equalsIgnoreCase(IdentityType.UID.getValue()))
         {
             return new User<NumericPrincipal>(new NumericPrincipal(
                     Long.parseLong(userName)));
         }
-        else if (idType.equals(IdentityType.OPENID.getValue()))
+        else if (idType.equalsIgnoreCase(IdentityType.OPENID.getValue()))
         {
             return new User<OpenIdPrincipal>(new OpenIdPrincipal(userName));
         }
-        else if (idType.equals(IdentityType.COOKIE.getValue()))
+        else if (idType.equalsIgnoreCase(IdentityType.COOKIE.getValue()))
         {
             return new User<CookiePrincipal>(new CookiePrincipal(userName));
         }
diff --git a/projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/UserClient.java b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/UserClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a6d8a416c704f3c08446722e5e60a3593a6d7d2
--- /dev/null
+++ b/projects/cadcAccessControl/src/ca/nrc/cadc/ac/client/UserClient.java
@@ -0,0 +1,354 @@
+/*
+ ************************************************************************
+ *******************  CANADIAN ASTRONOMY DATA CENTRE  *******************
+ **************  CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES  **************
+ *
+ *  (c) 2014.                            (c) 2014.
+ *  Government of Canada                 Gouvernement du Canada
+ *  National Research Council            Conseil national de recherches
+ *  Ottawa, Canada, K1A 0R6              Ottawa, Canada, K1A 0R6
+ *  All rights reserved                  Tous droits réservés
+ *
+ *  NRC disclaims any warranties,        Le CNRC dénie toute garantie
+ *  expressed, implied, or               énoncée, implicite ou légale,
+ *  statutory, of any kind with          de quelque nature que ce
+ *  respect to the software,             soit, concernant le logiciel,
+ *  including without limitation         y compris sans restriction
+ *  any warranty of merchantability      toute garantie de valeur
+ *  or fitness for a particular          marchande ou de pertinence
+ *  purpose. NRC shall not be            pour un usage particulier.
+ *  liable in any event for any          Le CNRC ne pourra en aucun cas
+ *  damages, whether direct or           être tenu responsable de tout
+ *  indirect, special or general,        dommage, direct ou indirect,
+ *  consequential or incidental,         particulier ou général,
+ *  arising from the use of the          accessoire ou fortuit, résultant
+ *  software.  Neither the name          de l'utilisation du logiciel. Ni
+ *  of the National Research             le nom du Conseil National de
+ *  Council of Canada nor the            Recherches du Canada ni les noms
+ *  names of its contributors may        de ses  participants ne peuvent
+ *  be used to endorse or promote        être utilisés pour approuver ou
+ *  products derived from this           promouvoir les produits dérivés
+ *  software without specific prior      de ce logiciel sans autorisation
+ *  written permission.                  préalable et particulière
+ *                                       par écrit.
+ *
+ *  This file is part of the             Ce fichier fait partie du projet
+ *  OpenCADC project.                    OpenCADC.
+ *
+ *  OpenCADC is free software:           OpenCADC est un logiciel libre ;
+ *  you can redistribute it and/or       vous pouvez le redistribuer ou le
+ *  modify it under the terms of         modifier suivant les termes de
+ *  the GNU Affero General Public        la “GNU Affero General Public
+ *  License as published by the          License” telle que publiée
+ *  Free Software Foundation,            par la Free Software Foundation
+ *  either version 3 of the              : soit la version 3 de cette
+ *  License, or (at your option)         licence, soit (à votre gré)
+ *  any later version.                   toute version ultérieure.
+ *
+ *  OpenCADC is distributed in the       OpenCADC est distribué
+ *  hope that it will be useful,         dans l’espoir qu’il vous
+ *  but WITHOUT ANY WARRANTY;            sera utile, mais SANS AUCUNE
+ *  without even the implied             GARANTIE : sans même la garantie
+ *  warranty of MERCHANTABILITY          implicite de COMMERCIALISABILITÉ
+ *  or FITNESS FOR A PARTICULAR          ni d’ADÉQUATION À UN OBJECTIF
+ *  PURPOSE.  See the GNU Affero         PARTICULIER. Consultez la Licence
+ *  General Public License for           Générale Publique GNU Affero
+ *  more details.                        pour plus de détails.
+ *
+ *  You should have received             Vous devriez avoir reçu une
+ *  a copy of the GNU Affero             copie de la Licence Générale
+ *  General Public License along         Publique GNU Affero avec
+ *  with OpenCADC.  If not, see          OpenCADC ; si ce n’est
+ *  <http://www.gnu.org/licenses/>.      pas le cas, consultez :
+ *                                       <http://www.gnu.org/licenses/>.
+ *
+ *  $Revision: 4 $
+ *
+ ************************************************************************
+ */
+package ca.nrc.cadc.ac.client;
+
+import java.io.*;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Principal;
+import java.util.Set;
+
+import javax.net.ssl.SSLSocketFactory;
+import javax.security.auth.Subject;
+import javax.security.auth.x500.X500Principal;
+
+import ca.nrc.cadc.ac.*;
+import ca.nrc.cadc.auth.HttpPrincipal;
+
+import org.apache.log4j.Logger;
+
+import ca.nrc.cadc.ac.xml.UserReader;
+import ca.nrc.cadc.auth.CookiePrincipal;
+import ca.nrc.cadc.auth.NumericPrincipal;
+import ca.nrc.cadc.auth.SSLUtil;
+import ca.nrc.cadc.net.HttpDownload;
+
+
+/**
+ * Client class for performing user searching and user actions
+ * with the access control web service.
+ */
+public class UserClient
+{
+    private static final Logger log = Logger.getLogger(UserClient.class);
+
+    // socket factory to use when connecting
+    private SSLSocketFactory sslSocketFactory;
+    private SSLSocketFactory mySocketFactory;
+    private String baseURL;
+
+    /**
+     * Constructor.
+     *
+     * @param baseURL The URL of the supporting access control web service
+     *                obtained from the registry.
+     */
+    public UserClient(final String baseURL)
+            throws IllegalArgumentException
+    {
+        if (baseURL == null)
+        {
+            throw new IllegalArgumentException("baseURL is required");
+        }
+        try
+        {
+            new URL(baseURL);
+        }
+        catch (MalformedURLException e)
+        {
+            throw new IllegalArgumentException("URL is malformed: " +
+                                               e.getMessage());
+        }
+
+        if (baseURL.endsWith("/"))
+        {
+            this.baseURL = baseURL.substring(0, baseURL.length() - 1);
+        }
+        else
+        {
+            this.baseURL = baseURL;
+        }
+    }
+
+    /**
+     * This method takes a subject with at least one valid principal, 
+     * uses the ac user web service to get all the other 
+     * associated principals which are then added to the subject.
+     *
+     * @param subject           The Subject to pull Princials for.
+     */
+    public void augmentSubject(Subject subject)
+    {
+        URL url = this.getURL(subject);
+    	log.debug("augmentSubject request to " + url.toString());    	
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        HttpDownload download = new HttpDownload(url, out);
+
+        download.setSSLSocketFactory(getSSLSocketFactory());
+        download.run();
+     
+        this.handleThrowable(download);
+        this.augmentSubject(subject, this.getPrincipals(out));
+    }
+    
+    protected void augmentSubject(Subject subject, Set<Principal> principals)
+    {
+        if (principals.isEmpty())
+        {
+        	String name = subject.getPrincipals().iterator().next().getName();
+        	String msg = "No UserIdentity in LDAP server for principal: " + name;
+        	throw new IllegalStateException(msg);
+        }
+        
+    	for (Principal principal : principals)
+    	{
+    		if (principal instanceof HttpPrincipal)
+    		{
+    			subject.getPrincipals(HttpPrincipal.class)
+    				.add((HttpPrincipal)principal);
+    		}
+    		else if (principal instanceof X500Principal)
+    		{
+    			subject.getPrincipals(X500Principal.class)
+    				.add((X500Principal)principal);
+    		}
+    		else if (principal instanceof NumericPrincipal)
+    		{
+    			subject.getPrincipals(NumericPrincipal.class)
+    				.add((NumericPrincipal)principal);
+    		}
+    		else if (principal instanceof CookiePrincipal)
+    		{
+    			subject.getPrincipals(CookiePrincipal.class)
+    				.add((CookiePrincipal)principal);
+    		}
+            else
+            {
+        		final String msg = "Subject has unsupported principal " +
+        				principal.getName() + 
+        				", not one of (X500, Cookie, HTTP or Cadc).";
+		        throw new IllegalStateException(msg);
+            }
+    	}
+    }
+    
+    protected Set<Principal> getPrincipals(ByteArrayOutputStream out)
+    {
+    	try
+    	{
+	        String userXML = new String(out.toByteArray(), "UTF-8");
+	        log.debug("userXML Input to getPrinciplas(): " + userXML);
+	        
+	        User<Principal> user = new UserReader().read(userXML);
+	        return user.getIdentities();
+    	}
+    	catch (Exception e)
+    	{
+    		throw new RuntimeException(e);
+    	}
+    }
+    
+    protected void handleThrowable(HttpDownload download)
+    {
+    	Throwable throwable = download.getThrowable();
+        if (throwable != null)
+        {
+            log.debug("handleThrowable(): throwable (" + download
+                    .getResponseCode() + ")", throwable);
+            throw new IllegalStateException(throwable.getMessage());
+        }
+    }
+    
+    protected URL getURL(Subject subject)
+    {
+		try 
+		{
+		    String userID = subject.getPrincipals().iterator().next().getName();
+		    String encodedUserID = URLEncoder.encode(userID, "UTF-8");
+			URL url = new URL(this.baseURL + "/users/" + encodedUserID + 
+					"?idType=" + this.getIdType(subject) + "&detail=identity");
+			log.debug("getURL(): returned url ="
+					+ ""
+					+ " " + url.toString());
+			return url;
+		} 
+		catch (UnsupportedEncodingException e) 
+		{
+			throw new RuntimeException(e);
+		}
+		catch (MalformedURLException e)
+		{
+			throw new RuntimeException(e);
+		}
+    }
+    
+    protected String getIdType(Subject subject)
+    {
+    	Set<Principal> principals = subject.getPrincipals();
+    	if (principals.size() > 0)
+    	{
+        	String idTypeStr = null;
+    		Principal principal = principals.iterator().next();
+            if (principal instanceof HttpPrincipal)
+            {
+            	idTypeStr = IdentityType.USERNAME.getValue();
+            }
+            else if (principal instanceof X500Principal)
+            {
+            	idTypeStr = IdentityType.X500.getValue();
+            }
+            else if (principal instanceof NumericPrincipal)
+            {
+            	idTypeStr = IdentityType.UID.getValue();
+            }
+            else if (principal instanceof CookiePrincipal)
+            {
+            	idTypeStr = IdentityType.COOKIE.getValue();
+            }   		
+            else
+            {
+        		final String msg = "Subject has unsupported principal " +
+        				principal.getName() + 
+        				", not one of (X500, Cookie, HTTP or Cadc).";
+		        throw new IllegalArgumentException(msg);
+            }
+            
+            return idTypeStr;
+    	}
+    	else
+    	{
+    		final String msg = "Subject has no principal.";
+    		throw new IllegalArgumentException(msg);
+    	}
+    }
+
+    /**
+     * @param sslSocketFactory the sslSocketFactory to set
+     */
+    public void setSSLSocketFactory(SSLSocketFactory sslSocketFactory)
+    {
+        if (mySocketFactory != null)
+        {
+            throw new IllegalStateException(
+            		"Illegal use of GMSClient: cannot set SSLSocketFactory " +
+                    "after using one created from Subject");
+        }
+        this.sslSocketFactory = sslSocketFactory;
+        clearCache();
+    }
+
+    private int subjectHashCode = 0;
+
+    private SSLSocketFactory getSSLSocketFactory()
+    {
+        AccessControlContext ac = AccessController.getContext();
+        Subject s = Subject.getSubject(ac);
+
+        // no real Subject: can only use the one from setSSLSocketFactory
+        if (s == null || s.getPrincipals().isEmpty())
+        {
+            return sslSocketFactory;
+        }
+
+        // lazy init
+        if (this.mySocketFactory == null)
+        {
+            log.debug("getSSLSocketFactory: " + s);
+            this.mySocketFactory = SSLUtil.getSocketFactory(s);
+            this.subjectHashCode = s.hashCode();
+        }
+        else
+        {
+            int c = s.hashCode();
+            if (c != subjectHashCode)
+            {
+                throw new IllegalStateException(
+                		"Illegal use of " + this.getClass().getSimpleName() +
+                		": subject change not supported for internal " +
+                		"SSLSocketFactory");
+            }
+        }
+        return this.mySocketFactory;
+    }
+
+    protected void clearCache()
+    {
+        AccessControlContext acContext = AccessController.getContext();
+        Subject subject = Subject.getSubject(acContext);
+
+        if (subject != null)
+        {
+            log.debug("Clearing cache");
+            subject.getPrivateCredentials().clear();
+        }
+    }
+}