Hello BASE team!

Extending a little on our recent developments regarding external authentication in BASE [1], I am working now on a Web service interface to BASE that will authenticate users based on secure tokens issued by a trusted STS. The STS authenticates users with username and password, and issues a crypted token confirming their credentials. The token is valid for a limited time and can be used for authentication in applications and services that trust the STS.

The STS token does not contain a password, only a user id, so with current implementation of SessionControl I was unable to log in. I added one method to the SessionControl class (see attached diff), included a TokenAuthenticator interface (attached), and everything worked nice. The extra operation allows to log in using a single token object and a validator that can verify the token. The operation contains substantial parts of SessionControl.verifyUserExternal(), which can be extracted to a separate method. The TokenAuthenticator interface and original Authenticator interface are also quite similar, so they could maybe share a common ancestor.

I know that the change is in the heart of BASE, but it is little and would provide additional way of programmatic interaction with BASE. If they pass the tests, could you consider including the changes to the BASE codebase?

Best wishes,
Pawel Sztromwasser

[1] http://www.mail-archive.com/basedb-devel@lists.sourceforge.net/msg00433.html)
25a26,44
> import net.sf.basedb.core.authentication.TokenAuthenticator;	
2240a2243,2352
> 	
> 	
> 	/**
> 	 * Log in to BASE using a trusted authentication token. 
> 	 * The method delegates validation of the token to tokenAuthenticator.
> 	 * @param token
> 	 *            authentication token
> 	 * @param tokenAuthenticator
> 	 * 	      authenticator object that is able to verify the token and authenticate the user
> 	 * @throws ItemNotFoundException
> 	 *             If a user identified by the token is not found
> 	 * @throws InvalidPasswordException
> 	 *             If the token is invalid
> 	 * @throws PermissionDeniedException
> 	 *             If the user doesn't have {@link Permission#USE} permission
> 	 *             for the current client application or if a user is already
> 	 *             logged in
> 	 * @throws BaseException
> 	 *             If there is any other error
> 	 * @see #logout()
> 	 * @see #isLoggedIn()
> 	 * @see #getLoggedInUserId()
> 	 */
> 	public synchronized <T> void login(T token, TokenAuthenticator<T> tokenAuthenticator)
> 	throws ItemNotFoundException, PermissionDeniedException, InvalidPasswordException, BaseException {
> 		
> 		updateLastAccess();
> 		// Are we already logged in?
> 		if (isLoggedIn()) {
> 			throw new AlreadyLoggedInException(loginInfo.userLogin);
> 		}
> 		
> 		AuthenticationInformation authInfo = tokenAuthenticator.authenticate(token);
> 		String login = authInfo.login;
> 		
> 		if (login == null)
> 			throw new InvalidUseOfNullException("login");
> 		
> 		org.hibernate.Session session = null;
> 		org.hibernate.Transaction tx = null;
> 		try {
> 			session = HibernateUtil.newSession();
> 			tx = HibernateUtil.newTransaction(session);
> 			
> 			org.hibernate.Query query = HibernateUtil.getPredefinedQuery(session, "GET_USER_FOR_EXTERNAL_ID");
> 			/*
> 				SELECT usr 
> 				FROM UserData usr
> 				WHERE usr.externalId = :externalId
> 			*/
> 			query.setParameter("externalId", authInfo.id);
> 			UserData userData = HibernateUtil.loadData(UserData.class, query);
> 			if (userData == null) 
> 			{
> 				userData = new UserData();
> 				userData.setExternalId(authInfo.id);
> 				userData.setLogin(authInfo.login);
> 				userData.setName(authInfo.name == null ? authInfo.login : authInfo.name);
> 				userData.getPassword().setMd5Password("");
> 				userData.setQuota(HibernateUtil.loadData(session, QuotaData.class, SystemItems.getId(Quota.DEFAULT)));
> 				User.addDefultRolesAndGroups(session, userData);
> 			}
> 			if (tokenAuthenticator.supportsExtraInformation() &&
> 				(Config.getBoolean("auth.synchronize") || userData.getId() == 0))
> 			{
> 				userData.setName(authInfo.name == null ? authInfo.login : authInfo.name);
> 				userData.setOrganisation(authInfo.organisation);
> 				userData.setAddress(authInfo.address);
> 				userData.setPhone(authInfo.phone);
> 				userData.setFax(authInfo.fax);
> 				userData.setEmail(authInfo.email);
> 				userData.setUrl(authInfo.url);
> 				userData.setDescription(authInfo.description);
> 			}
> 			if (userData.getId() == 0)
> 			{
> 				HibernateUtil.saveData(session, userData);	
> 			}
> 			HibernateUtil.flush(session);
> 
> 			LoginInfo li = createLoginInfo(session, userData, "Logged in using an authentication token", false);
> 			HibernateUtil.commit(tx);
> 			currentContexts.clear();
> 			loginInfo = li;
> 		} catch (BaseException ex) {
> 			if (tx != null)
> 				HibernateUtil.rollback(tx);
> 			throw ex;
> 		} finally {
> 			if (session != null)
> 				HibernateUtil.close(session);
> 		}
> 		
> 	}
package net.sf.basedb.core.authentication;

public interface TokenAuthenticator<T> {

	public void init(String settings) throws AuthenticationException ;
	
	public boolean supportsExtraInformation() ;
	
	public AuthenticationInformation authenticate(T token) throws AuthenticationException;
	
}
------------------------------------------------------------------------------
Got Input?   Slashdot Needs You.
Take our quick survey online.  Come on, we don't ask for help often.
Plus, you'll get a chance to win $100 to spend on ThinkGeek.
http://p.sf.net/sfu/slashdot-survey
_______________________________________________
basedb-devel mailing list
basedb-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/basedb-devel

Reply via email to