21-Jul-04 (Created: 21-Jul-04) | More in 'OSCON-2004'

Authentication Pattern: Code Examples

Idea of authentication


public interface IAuthentication 
{
   public boolean verifyPassword(final String userid, final String passwd ) 
      throws AuthorizationException;
      
   public boolean isAccessAllowed(final String userid, final String resource )
      throws AuthorizationException;
} 

Resource is not always a good idea.

Refactor authentication


public interface IAuthentication1 extends IAuthentication
{
   public boolean isAccessAllowed(final String userid
                                 , HttpServletRequest request
                                  ,HttpServletResponse response)
      throws AuthorizationException;
} 

See how the resource is replaced with request and response.

Userid is not available for public urls


public interface IAuthentication2 extends IAuthentication1
{
   public boolean isAPublicURL(HttpServletRequest request
                                  ,HttpServletResponse response)
      throws AuthorizationException;
}

Each interface gets increasingly capable and sophisticated.

A dummy implementation


public class DefaultAuthentication implements IAuthentication1,ICreator
{
  public Object executeRequest(String requestName, Object args)
     throws RequestExecutionException
  {
      return this;
  }
   public DefaultAuthentication()
   {
   }
   public boolean verifyPassword(String userid, final String passwd )
      throws AuthorizationException
   {
      return true;
   }
   public boolean isAccessAllowed(String userid, final String resource )
      throws AuthorizationException
   {
      return true;
   }
   public boolean isAccessAllowed(final String userid
                                 , HttpServletRequest request
                                  ,HttpServletResponse response)
      throws AuthorizationException
  {
    return true;
  }
}

A trivial implemenation


public class TrivialAccess implements DefaultAuthentication
{
   pricate String cachePassword = null;
   //Read the static password from a file
   public void initialize(String requestName)
   {
   		cachePassword = Config.getValue(requestName + ".password");
   }
   
   public boolean verifyPassword(String userid, String passwd )
      throws AuthorizationException
   {
      return (password.equals(passwd, cachePassword)); 
   }
}

A bit sophisticated public access authentication


public class PublicAccessAuthentication 
	extends DefaultAuthentication 
	implements IAuthentication2, IInitializable
{
   private String m_publicURLs = null;
   private String m_publicRequestNames = null;

   private Map m_publicURLMap;
   private Map m_publicRNMap;

   public PublicAccessAuthentication()
   {
   }

   public void initialize(String requestName)
   {
     m_publicURLs = 
	 	AppObjects.getValue(requestName + ".publicURLs","");
		
     m_publicRequestNames = 
	 	AppObjects.getValue(requestName + ".publicRequestNames","");
		
     m_publicURLMap = 
	 	Tokenizer.tokenizeAsAHashtable(m_publicURLs.toLowerCase(),",");
		
     m_publicRNMap = 
	 	Tokenizer.tokenizeAsAHashtable(
				m_publicRequestNames.toLowerCase(),",");
		
     AppObjects.log("Info: Public URLs:" + m_publicURLs);
  }

  public boolean isAPublicURL(HttpServletRequest request
                                 ,HttpServletResponse response)
     throws AuthorizationException
  {
   /*
   *
   * By default things are private
   */
   String aspireURL= request.getParameter("url");
   AppObjects.log("Info: aspireURL: " + aspireURL);
   String aspireRequestName = request.getParameter("request_name");

   if (aspireURL != null)
   {
     if (m_publicURLMap.get(aspireURL.toLowerCase()) != null)
     {
       return true;
     }
   }

   if (aspireRequestName != null)
   {
     if (m_publicRNMap.get(aspireRequestName.toLowerCase()) != null)
     {
       return true;
     }
   }

   return false;
  }
}

Using a database for authentication


 public class SimpleDBAuthentication1 
 		extends PublicAccessAuthentication
 {
   public SimpleDBAuthentication1()
   {
   }
   public boolean verifyPassword(String userid, String passwd )
      throws AuthorizationException
   {
      try
      {
         Hashtable args = new Hashtable();
         args.put("userid",userid);
         args.put("password",passwd);
         Object reply = 
		 	AppObjects
				.getIFactory()
				.getObject(AspireConstants.AUTHENTICATE_USER,args);
				
         return  FilterUtils.convertToBoolean(reply);
      }
      catch(com.ai.application.interfaces.RequestExecutionException x)
      {
         throw new AuthorizationException(
		 	AuthorizationException.CANNOT_ACCESS_AUTHORIZATION_SERVERS,x);
      }
      catch(com.ai.common.UnexpectedTypeException x)
      {
         throw new AuthorizationException(
		 	"auth: Authorization service returned a wrong object" ,x);
      }
   }
}

Specification


<request name="IAuthentication">
	<classname>SimpleDBAuthentication1</classname>
	<databaseRequest>AuthenticationDBRequest<databaseRequest>
</request>

<request name="AuthenticationDBRequest">
	<classname>com.ai.db.DBRequestExecutor2</classname>
	<db>my-database</db>
	<stmt>
      select 'true' as result             
      from users                     
      where user_id = '{userid}'     
      and password = '{password}'
	</stmt>
</request>

Revisiting Trivial Authentication


public class TrivialAuthentication 
	extends PublicAccessAuthentication 
	implements IAuthentication2, ICreator, IInitializable
{
   public boolean verifyPassword(String userid, String passwd )
      throws AuthorizationException
   {
      String password =
      AppObjects.getIConfig().getValue(AspireConstants.PASSWORD,null);
      if (password == null) {return true;}
      // password has been mentioned
      return passwd.equals(password);
   }
}

References

1. General Introduction to other Server side Patterns in this series

2. OSCON 2004 Summary page for Server side patterns session

3. Strategized Session Pattern: Code Examples