You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Ken Johanson <to...@kensystem.com> on 2006/02/07 05:56:58 UTC

Re: Calling Realm.authenticate() doesn't register Principal in with the Session??

Mark Thomas wrote:
> 
> Given users are going to have to modify their app to use this library,
> not modifying the associated context.xml looks to be a nice to have
> requirement that is making things more difficult. Removing this
> requirement opens up a number of alternative implementation options
> including custom realms.
> 
> Mark
> 

Mark, are you saying that you agree, or disagree, with the usefulness of 
the idea?

Your point about 'users have to modify their app' is true, but a one 
time requirement, and thereafter their app will be compatible with 
whatever underlying realm impl is used, which I find enticing. Currently 
there is no mechanism (that I can see) to programtically perform login - 
say from an html form - this 'new' proposed method fills that. And by 
the same token, a user would already have to modify their app (to use a 
custom POST url or form names or redirect), with the built-in form based 
login (or subclass of it's impl), so that doesn't seem to be a drawback.

Sorry to be redundant of you're already agreeing with the idea.

Ken



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Calling Realm.authenticate() doesn't register Principal in with the Session??

Posted by Ken Johanson <to...@kensystem.com>.
I'm trying to re-word these two concepts in a more elegant way:

1) I'm looking for a way to use form based authentication - but unlike 
with the current form login Realm, I need a way to intercept the persons 
email address(s) (typed into the username field), so that I can convert 
that into its corresponding username *before* passing it to the Realm 
(this cannot be done with the current form based login).

For this method, I would *prefer* not to write an override to any 
existing Realm (Form or WWW-Authenticate) - because users may already 
have their own. In other words, I would like to be able to call into 
whatever Realm the user already has configured (provided it's a 
user/pass one).

2) As an alternative, being able to simply register a given username 
(void doLogin(Principal p)) with a session via the server API would also 
be very useful - one could perform their own password or X509 validation 
inside of a servlet/jsp (using rules that are much more strict than what 
the current impls support, e.g trust levels/rules for issuers, and 
revocation checks, and critical subject flags for x509 certs). One could 
also implement the simplest possible (yet highly customizable) login 
logic against say, a database:

ResultSet rs = ps.exec("SELECT pass FROM auth WHERE user = ?"
	,request.getParameter("user"));
if (Digest.sha1(request.getParameter("pass"))
	.equals(rs.getString("pwdSha"))
)
  Tomcat5.doLogin(session, new Principal(request.getParameter("user"));


I hope that these two (very different) concepts will be tantalizing 
enough that some highly simplified auth APIs/concepts will make their 
way into the server. I have tried to build the first one - but the 
protected request/response fields in CoyoteRequestFacade cannot be 
accessed from a external class, and reflection would be needed to 
cast/call the method. An 'expert' will do much better than I.

class Tomcat5:

public static boolean tryLogin(HttpServletRequest request, 
HttpServletRequest response, String user, String pass)
   throws Exception
{
   Server server = ServerFactory.getServer();
   Service service = server.findService("Catalina");
   if (service==null)
     throw new NullPointerException("login: Cannot load Service 
'Catalina'");
   Engine engine = (Engine) service.getContainer();
   if (engine==null)
     throw new NullPointerException("login: Cannot load Container for 
Service 'Catalina'");

   Host host = null;
   String hostname = Strings.norm(request.getHeader("Host"));
   Object[] o = engine.findChildren();
   for (int i=0; i<o.length; i++)
   {
     if (!(o[i] instanceof Host))
       continue;
     Host h = (Host)o[i];
     String[] list = h.findAliases();
     for (int j=0; j<list.length; j++)
       if (hostname.equalsIgnoreCase(list[j]))
       {
         host = h;
         break;
       }
   }
   if (host==null)
     throw new NullPointerException("login: Cannot load Host 
'"+hostname+"'");
   String reqbase  = Strings.norm(req.getContextPath())+"/";
   Context context = (Context) host.findChild(reqbase);
   if (context==null)
   {
     context = (Context) host.findChild(Strings.clip(reqbase,-1));
   }
   if (context==null)
     throw new NullPointerException("login: Cannot load Context 
'"+reqbase+"'");
   Manager manager = context.getManager();
   HttpSession hses = request.getSession(true);
   Session session = null;
   try {
     session = manager.findSession(hses.getId());
   } catch (IOException e) {}
   if (session==null)
     throw new NullPointerException("login: Cannot load Session 
'"+reqbase+"'");
   Realm realm = context.getRealm();
   LoginConfig config = context.getLoginConfig();
   FormAuthenticator auth = null;
   Pipeline pipe = context.getPipeline();
   Valve[] v = pipe.getValves();
   for (int i=0; i<v.length; i++)
   {
     if (v[i] instanceof Authenticator)
     {
       auth = (FormAuthenticator)v[i];
       //if (true)throw new NullPointerException(o[i].toString());
       break;
     }
   }
   if (auth==null)
     throw new NullPointerException("login: Cannot load Authenticator 
'"+reqbase+"'");
   Principal principal = realm.authenticate(user, pass);
   if (principal==null)
     return false;
   session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);
   session.setNote(Constants.SESS_USERNAME_NOTE, user);
   session.setNote(Constants.SESS_PASSWORD_NOTE, pass);
   if (true) throw new 
NullPointerException(request.getClass().toString()+" 
"+response.getClass().toString());
   auth.authenticate(((CoyoteRequestFacade)request).request, 
((CoyoteResponseFacade)response).response, config);
   return true;
}



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Calling Realm.authenticate() doesn't register Principal in with the Session??

Posted by Ken Johanson <to...@kensystem.com>.
Mark Thomas wrote:
> Ken Johanson wrote:
> 
>> Mark, are you saying that you agree, or disagree, with the usefulness of
>> the idea?
> I am -0 to the idea as a whole. I don't see the point but am happy to
> proivde pointers where I can.
> 
> Mark
> 

Okay - do you have any pointers for this need?: (please forgive me for 
possibly repeating what may have been mentioned earlier)

-A third party API (that I'm writing, just as could anyone else) must be 
'dropped in' to any recent Tomcat version; it must allow users of the 
API to authenticate (using only username and passwd) against whatever 
existing realm they have configured, without ANY changes to that realm's 
config or impl. This INSURES that any existing authentication code 
(form, jdbc) continues to work.

-OR- if there is a way already without using the third party API, what 
is it? Say, something along the lines of setting request-context 
attributes, or beans props (beans being less ideal)..

-Finally, the solution (existing or new) MUST allow code within a 
servlet, jsp, bean, or POJO, etc to pass ONLY a username + password, or 
alternatively only an X509Certificate, into some class who will simply 
return a true|false, or throw an exception on authentication failure.

Hence, the idea allows more flexibility when additional layers are 
REQUIRED atop the authentication pre-processing. An example, would be to 
perform a database lookup of an email address(s) (entered into a login 
form's username field) and translate it into a Principal, is then passed 
into the webapp's preconfigured Realm.

Ken



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Calling Realm.authenticate() doesn't register Principal in with the Session??

Posted by Mark Thomas <ma...@apache.org>.
Ken Johanson wrote:

> Mark, are you saying that you agree, or disagree, with the usefulness of
> the idea?
I am -0 to the idea as a whole. I don't see the point but am happy to
proivde pointers where I can.

Mark


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org