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/01/19 03:34:53 UTC
Calling Realm.authenticate() doesn't register Principal in with the
Session??
Hi all,
I am able to access the current context's org.apache.catalina.Realm
object using Yoav Shapira's Tomcat-Realm example; however, when I call
Realm.authenticate(String user, String pass), the Principal object that
it returns is not being registered with the session..
In other words, subsequent requests (inside the same webapp / context
that I'm calling invoking Realm.authenticate from) just return null for
getRemoteUser() and getPrincipal()...
Shouldn't authenticate() register the Principal with the Session
automatically? Or do I need to call register() in interface Authenticator?
Thank,
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
Re: Calling Realm.authenticate() doesn't register Principal in with
the Session??
Posted by Ken Johanson <to...@kensystem.com>.
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 Mark Thomas <ma...@apache.org>.
Ken Johanson wrote:
> ...
>
>>> I'm trying to write a facade API that will call into whatever
>>> Realm/Authenticator that the user already has configured (though an
>>> abstract/overridden method)... the idea being that no changes to the
>>> user's existing auth config or modules are required, nor that the user
>>> should need to change out any custom realm/authenticator that they may
>>> have written, for mine. So the solution needs to transparently call into
>>> some existing method(s) in the 'Base' classes or interface impls..
>>
>> To do what? What user requirement are you trying to meet? Technically
>> I understand what you are trying to do but not the fundamental why.
>> Knowing your ultimate aim may enable people on this list to suggest an
>> alternative approach.
>>
>> Mark
>>
>
> The intent is that a simple library can be deployed into the (at
> server/lib or shared/lib), and from any webapp, calling into that
> wrapper class will allow the app to authenticate and register the user..
> irregardless of what specific authenticate/realm modules are being used.
>
> A very simple example, is that I would like for users to login on a html
> form, by entering not just their username - but maybe their email
> address (any number of them), or pub key (to be hypothetical)... then
> its it will be up to the webapp to search a database beforehand, to
> lookup the email address or pub key, and get the userid, then pass it to
> the auth module if, say, the account is current, the password age isn't
> expired, etc.
>
> All completely independent of what Realm/Authent. is config'd for any
> webapp. Only the username and password (and which webapp as implied by
> the context path contained in Request).: static boolean
> Tomcat5.authenticate(request, response, user, pass);
>
> Creating and deploying my own version of this class is not feasible,
> because :
>
> -users should have the option to write the account validation logic in JSP
>
> -Users may already have a custom impl, and should not have to extend or
> implement or compile anything in that impl. to support this lib. Be it
> their own impl or their choice-use of tomcat JDBC realm.
>
> Thanks,
> Ken
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
---------------------------------------------------------------------
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 write a facade API that will call into whatever
>> Realm/Authenticator that the user already has configured (though an
>> abstract/overridden method)... the idea being that no changes to the
>> user's existing auth config or modules are required, nor that the user
>> should need to change out any custom realm/authenticator that they may
>> have written, for mine. So the solution needs to transparently call into
>> some existing method(s) in the 'Base' classes or interface impls..
> To do what? What user requirement are you trying to meet? Technically
> I understand what you are trying to do but not the fundamental why.
> Knowing your ultimate aim may enable people on this list to suggest an
> alternative approach.
>
> Mark
>
The intent is that a simple library can be deployed into the (at
server/lib or shared/lib), and from any webapp, calling into that
wrapper class will allow the app to authenticate and register the user..
irregardless of what specific authenticate/realm modules are being used.
A very simple example, is that I would like for users to login on a html
form, by entering not just their username - but maybe their email
address (any number of them), or pub key (to be hypothetical)... then
its it will be up to the webapp to search a database beforehand, to
lookup the email address or pub key, and get the userid, then pass it to
the auth module if, say, the account is current, the password age isn't
expired, etc.
All completely independent of what Realm/Authent. is config'd for any
webapp. Only the username and password (and which webapp as implied by
the context path contained in Request).: static boolean
Tomcat5.authenticate(request, response, user, pass);
Creating and deploying my own version of this class is not feasible,
because :
-users should have the option to write the account validation logic in JSP
-Users may already have a custom impl, and should not have to extend or
implement or compile anything in that impl. to support this lib. Be it
their own impl or their choice-use of tomcat JDBC realm.
Thanks,
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 Thomas wrote:
>> Ken Johanson wrote:
>>> I am able to access the current context's org.apache.catalina.Realm
>>> object using Yoav Shapira's Tomcat-Realm example; however, when I call
>>> Realm.authenticate(String user, String pass), the Principal object that
>>> it returns is not being registered with the session..
<snip>
>>> Shouldn't authenticate() register the Principal with the Session
>>> automatically? Or do I need to call register() in interface
>>> Authenticator?
You would need to find a way to call register()
>> What are you trying to do? From the amount of access you seem to need
>> to Tomcat internals, you might be better off just writing a custom
>> realm and/or authenticator.
>>
>> Mark
>>
>>
>
> Mark,
>
> I'm trying to write a facade API that will call into whatever
> Realm/Authenticator that the user already has configured (though an
> abstract/overridden method)... the idea being that no changes to the
> user's existing auth config or modules are required, nor that the user
> should need to change out any custom realm/authenticator that they may
> have written, for mine. So the solution needs to transparently call into
> some existing method(s) in the 'Base' classes or interface impls..
To do what? What user requirement are you trying to meet? Technically
I understand what you are trying to do but not the fundamental why.
Knowing your ultimate aim may enable people on this list to suggest an
alternative approach.
Mark
---------------------------------------------------------------------
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:
>> Hi all,
>>
>> I am able to access the current context's org.apache.catalina.Realm
>> object using Yoav Shapira's Tomcat-Realm example; however, when I call
>> Realm.authenticate(String user, String pass), the Principal object that
>> it returns is not being registered with the session..
>>
>> In other words, subsequent requests (inside the same webapp / context
>> that I'm calling invoking Realm.authenticate from) just return null for
>> getRemoteUser() and getPrincipal()...
>>
>> Shouldn't authenticate() register the Principal with the Session
>> automatically? Or do I need to call register() in interface Authenticator?
>>
>> Thank,
>> ken
> What are you trying to do? From the amount of access you seem to need
> to Tomcat internals, you might be better off just writing a custom
> realm and/or authenticator.
>
> Mark
>
>
Mark,
I'm trying to write a facade API that will call into whatever
Realm/Authenticator that the user already has configured (though an
abstract/overridden method)... the idea being that no changes to the
user's existing auth config or modules are required, nor that the user
should need to change out any custom realm/authenticator that they may
have written, for mine. So the solution needs to transparently call into
some existing method(s) in the 'Base' classes or interface impls..
This would be exposed in something like: static boolean
Tomcat5.authenticate(request, response, user, pass); (Or an X509 chain)
Hope this makes sense,
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:
> Hi all,
>
> I am able to access the current context's org.apache.catalina.Realm
> object using Yoav Shapira's Tomcat-Realm example; however, when I call
> Realm.authenticate(String user, String pass), the Principal object that
> it returns is not being registered with the session..
>
> In other words, subsequent requests (inside the same webapp / context
> that I'm calling invoking Realm.authenticate from) just return null for
> getRemoteUser() and getPrincipal()...
>
> Shouldn't authenticate() register the Principal with the Session
> automatically? Or do I need to call register() in interface Authenticator?
>
> Thank,
> ken
What are you trying to do? From the amount of access you seem to need
to Tomcat internals, you might be better off just writing a custom
realm and/or authenticator.
Mark
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org