Remoted User Credentials

The ability to use a 3rd party system for managing user credentials, while retaining the full power of the Sheetster
storage system and ACL system is possible by creating and installing custom User and UserFactory classes that authenticate
against the 3rd party system, then pass control to Sheetster for user groups and ACLs based upon the Sheetster storage system

Installation is simple:

1. Compile the files in this folder and put the output classfiles anywhere in the Server classpath such as "<installdir>/lib/".
2. Restart the server

It is important to note that the RemoteAuthUser.java example code will fail to authenticate by default so as to disallow unanticipated access during development testing.

To use Sheetster in this mode, it is important to properly handle username/password authentication between Sheetster and the
3rd party credential system by implementing the following method:

/**
* TODO: Implement actual credential checking against 3rd party auth/cred backend
*
* Sep 7, 2011
* @param uname
* @param upass
* @return
* @throws FailedLoginException
*/
public boolean checkRemoteAuth(String uname, String upass) throws FailedLoginException{
throw new FailedLoginException("Authenticating user: " + userName + " against " + remoteAuthDescription + " failed.");
}

IMPORTANT: If this method returns "true" then the user is assumed to be authenticated and ACCESS WILL BE GRANTED to the username specified.

For each user of the 3rd party system, you will need to insert valid user into Sheetster using the same userName.

IMPORTANT: this username is considered a unique ID within Sheetster to map the user to the 3rd party system.
Use values (username, email) that will not change in either system for the lifetime of the user account.
IF the username changes in the 3rd party system it MUST be synchronized in the Sheetster web app database as well

RemoteAuthUsers
package Remoted_User_Credentials;
import javax.security.auth.login.FailedLoginException;
import com.extentech.security.User;
import com.extentech.toolkit.Logger;
/**
 * The ability to use a 3rd party system for managing user credentials, while retaining the full power of the Sheetster
 * storage system and ACL system is possible by creating and installing custom User and UserFactory classes that authenticate
 * against the 3rd party system, then pass control to Sheetster for user groups and ACLs based upon the Sheetster storage system
	
	Installation is simple:
	
	   1. Compile the files in this folder and put the output classfiles anywhere in the Server classpath such as "<installdir>/lib/".
	
	   2. Sheetster server configuration will require setting the auth to "remote:package.classname" to load your custom UserFactory
	 
		INSERT INTO LUMINET_CONFIG VALUES('pluggables',0,'session_mode','remote:Remoted_User_Credentials.RemoteAuthUserFactory',285,'If set to remote_auth then we will use the custom RemoteAuthUser class to authenticate Sheetster users from remote credential systems.  If set to stateless this field will allow all permissions and data to be handled by the associated Auth objects.  Do not add this value unless you are doing custom integration work','')
	
	   3. Restart the server
	
	It is important to note that the RemoteAuthUser.java example code will fail to authenticate by default so as to disallow unanticipated access during development testing.
	
	To use Sheetster in this mode, it is important to properly handle username/password authentication between Sheetster and the
	3rd party credential system by implementing the following method:
	
		public boolean checkRemoteAuth(String uname, String upass) throws FailedLoginException{
			throw new FailedLoginException("Authenticating user: " + userName + " against " + remoteAuthDescription + " failed.");
		}
	
	IMPORTANT: If this method returns "true" then the user is assumed to be authenticated and ACCESS WILL BE GRANTED to the username specified.
	
	For each user of the 3rd party system, you will need to insert valid user into Sheetster using the same userName. 
	
	IMPORTANT: this username is considered a unique ID within Sheetster to map the user to the 3rd party system.
		Use values (username, email) that will not change in either system for the lifetime of the user account.
		IF the username changes in the 3rd party system it MUST be synchronized in the Sheetster web app database as well
		
 * 
 * 
 * @author John McMahon :: [ September 7, 2011 ] :: Copyright &copy;2011<a href = "http://www.extentech.com">Extentech Inc.</a>
 *
 */
public class RemoteAuthUser extends User 
implements java.security.Principal, java.io.Serializable 
{
	private String remoteAuthDescription = "Remote Auth System";
	/**
	 * @param remoteAuthDescription The remoteAuthDescription to set.
	 */
	public void setRemoteAuthDescription(String r) {
		this.remoteAuthDescription = r;
	}
	/**
	 * TODO: Implement actual credential checking against 3rd party auth/cred backend
	 * 
	 * It is important that this is done properly.
	 * Any "true" return from this method will allow un-restricted access to the Sheetster local user's docs
	 * 
	 * Sep 7, 2011
	 * @param uname
	 * @param upass
	 * @return
	 * @throws FailedLoginException 
	 */
	public boolean checkRemoteAuth(String uname, String upass) throws FailedLoginException{
		if(true)
			return true;
		throw new FailedLoginException("Authenticating user: " + userName + " against " + remoteAuthDescription + " failed.");
	}
	
	
	/** 
	* serialVersionUID
	*/
	private static final long serialVersionUID = -1008508455858354570L;
	/** 
	 * Authenticate this user against the remote 3rd party system.
	 * 
	 * IF successful, run normal Sheetster Local Storage user init.
	 * 
	 * @throws FailedLoginException
	 */
    @Override
	public void login(String password)
    	throws FailedLoginException{
    	
    	if(!this.checkRemoteAuth(userName, password)){
    		throw new FailedLoginException("Authenticating user: " + userName + " from " + remoteAuthDescription + " failed.");
    	}
    	
    	checkDB();
     	
    	// Since we have already logged into the secure remote system, this will select
    	
        setSQL("SELECT * FROM contacts WHERE email = '"+userName+"'");
        
        try { // this one attempts a cleartext password
            super.load();
        }catch(Exception e) {
            valid=false;
            String errmsg = "RemoteAuthUser.login Error authenticating user: " + userName + " against Sheetster Local Storage while post-loading user from " + remoteAuthDescription + " failed." + e.toString();
            Logger.logWarn(errmsg);
            throw new FailedLoginException(errmsg);
        }
	    if(getNumRows()<1) {
	    	throw new FailedLoginException("Authentication Failed for " + userName);
	    }else if(getNumRows()>1) {
        	String errmsg = "RemoteAuthUser.login Sheetster Web Application contains duplicate record for user: "+ userName;
            Logger.logErr(errmsg);
            throw new FailedLoginException(errmsg);
        }
		
        valid = true;
        isAnon = false;
        
        // initialize permissions
    	initACL();
    	
    	// initialize owned item permissions
    	initOwnedACL();
    }
}
RemoteAuthUserFactory
package Remoted_User_Credentials;
import com.extentech.security.User;
import com.extentech.security.UserFactory;
/** This class instantiates a new User object and sets the connection information
 *  to allow for credentials stored in a remote 3rd party auth/credentials system
 * 
 * 
 * @author John McMahon -- Copyright &copy;2011<a href = "http://www.extentech.com">Extentech Inc.</a>
 * @version 
 * @since 
 * @see 
 */
public class RemoteAuthUserFactory extends UserFactory {
	/** connect or reconnect the factory to the remote auth/credentials backend
	 * 
     * @throws Exception
     */
    public void init() throws Exception{
    	super.init(); // inits Sheetster Database
    }
    
    /** Instantiates and returns a user object
     * 
     *  The returned User object needs to login after creation to instantiate permissions and data.
     * 
     * @return
     */
    public User getUser() {
        // initialize a user object from database using login credentials
        User thisUser = new RemoteAuthUser();
        thisUser.setUserField(userUserField);
        thisUser.setPasswordField(userPasswordField);
        thisUser.setTableName(userTableName);
        thisUser.setKeyCol(userIdeField);
        conn = this.getConn();
        // init from factory
        thisUser.setFactory(this);
        return thisUser;
    }
}