-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

André,

On 3/30/17 3:41 PM, André Warnier (tomcat) wrote:
> On 30.03.2017 20:10, Christopher Schultz wrote:
>> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256
>> 
>> Konstantin,
>> 
>> On 3/30/17 4:19 AM, Konstantin Kolinko wrote:
>>> 2017-03-30 11:02 GMT+03:00 Jan Vávra <va...@602.cz>:
>>>> Hello, I have written a custom Realm and I need to access to
>>>> the request headers. The authentication should be computed
>>>> from client certificate + id from custom http header
>>>> X-IdUser. Can I somehow access to the HTTPServletRequest
>>>> instance  ?
>>> 
>>> Not possible, by design.
>>> 
>>> An Authenticator (a valve) can access request and its headers.
>>> A Realm cannot.
>> 
>> I've always been frustrated by this, and it's one reason I do not
>> use Tomcat's build-in authentication. I need to log
>> authentication failures and their sources (IP address) and this
>> information is simply not available through the Tomcat-provided
>> APIs.
>> 
>> I think there is definitely an opportunity here for improvement.
>> 
> 
> A naive question or three (I can't really ask any other kind in
> Java) :
> 
> 1) what is calling the following method ? 
> https://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/catalina/realm
/DataSourceRealm.html#authenticate%28java.lang.String,%20java.lang.Strin
g%29

Within
> 
Tomcat, one of the Authenticator classes is going to be calling
that method. (BasicAuthenticator, FormAuthenticator, etc.).

> 2) And (assuming that if you want to do non-standard things in the 
> Realm, it means that you are writing your own custom Realm), isn't
> there a possibility for any caller of (1) above, to pass anything
> it wants in the "credentials" argument ?
> 
> (such as a caller IP address, the content of a HTTP header, etc.) 
> (to be parsed out and used by the authenticate method, for logging
> e.g.)

Absolutely, you could do that.

But let's say that I want to write my own Realm implementation so I
can e.g. write the user's IP address to a table when they
authenticate. Okay, I write a Realm but the interface doesn't contain
any of that data.

So, I decide that I want to package the IP address into the username
field for authenticate(String username, String password). Sounds good,
but then I'd need to write my own Authenticator that knows that the
username is actually IP-address + username instead of just username
like usual.

And if I'm going to write my own Realm *and* Authenticator, why don't
I just write everything myself and skip the Tomcat-provided code?

> 3) and, still assuming much, might one then perhaps use this
> element to specify a class which would perform ditto parsing, prior
> to the authentication itself ? 
> http://tomcat.apache.org/tomcat-9.0-doc/config/credentialhandler.html

The
> 
CredentialHandler's job is to take the user's credential (the
password) and compare it to the value that was stored in the user
database. Providing a custom CredentialHandler only allows you to
support different types of password-munging.

Note that the CredentialHandler doesn't have access to any data
storage system (like the user database). The Realm is designed to
fetch the user's stored credential from the user database and then
delegate the comparison to the CredentialHandler. This allows someone
to support e.g. a hashing algorithm that Tomcat has never seen before.
But it doesn't allow the user database to store anything new.

Tomcat is attempting to separate the concerns of various things into
separate classes / interfaces. This allows a great deal of re-use of
code. For example, there are "authenticators" (which don't
authenticate) for the following: HTTP Basic, HTTP Digest, CLIENT-CERT,
FORM. And there are Realms (which actually authenticate) for the
following user databases: JDBC, DataStore(also JDBC), LDAP/JNDI, JAAS,
and "memory" (really "file").

If there was one class for each setup, you'd need an explosion of classe
s:

HttpBasicLDAPAuthenticator
HttpBasicJDBCAuthenticator
HttpBasicDataSourceAuthenticator
HttpBasicJAASAuthenticator
HttpDigestLDAPAuthenticator
HttpDigestJDBCAuthenticator
HttpDigestDataSourceAuthenticator
etc.

There are some authenticators that only make sense for some realm
methods. For example, the SSLAuthenticator is never going to call
Realm.authenticate(username, password). So in a way, these interfaces
are already a bit "impure".

But the idea for the Realm was "let's have a class/interface whose job
is simply to say yes/no to authentication requests and also to
determine if a user is authorized for a role-based permission".
There's really no reason to make that HTTP-specific. What does it mean
to have a username and password that match with or without an IP address
?

There is nothing HTTP-specific about a Realm, which is why this
complexity is left-out of the Realm interface.

But some people need their applications to use some information
available from the HTTP request as part of their authentication (or,
possibly their authentication-failure) processes.

So the solution currently requires programmers to step outside of
Tomcat's existing code and built a lot of their own things from scratch.

This used to be the case if you wanted to use a different hashing
algorithm (e.g. bcrypt): you'd have to write your own Realm mostly
from scratch and repeat a lot of code from the existing Realms. That's
why we introduced the CredentialHandler: so users could customize that
that /little/ piece of the puzzle. (It's also got some other goodies
in there like being able to access the CredentialHandler from
application code, so you can use the same configuration for
authentication as you do for changing user passwords within the
application.)

I think the same thing can be done for the authenticator-realm
relationship so that other information can be available for the Realm
to do its work. We just need to come up with a reasonable use-case and
a solution to it that doesn't require dozens of new
classes/interfaces. It is quite easy to over-design something in an OO
language :)

- -chris
-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBCAAGBQJY3pShAAoJEBzwKT+lPKRYA3IP/juTSFRqZ4DAfddadPPfykqI
ibcIIC85f2pI+WgAqnNPBs3sbfcmGlFA6uQwxuDKsYO70JSr9xROjMZUU+6Uk3s5
z1PA+hqxZKtsNh+Rg3y6I+jDNywG/3eP2rYrYmuDAtdp3Q67llsKsFQ8FN3SKdw8
mrvtJNqhIJCBhZMLctGjvMPVZiwkYQXhnhAB8z2eTwy/CjWmP28ciazguspqI2OX
xfcdILqK8ggwhgKhF/ANcjnNXZCo3kQ5KwMumySbp/iSGCBHa+v555kU2dm4go+D
H4GSuZMtvTPhIfSQVVRiIdS7V0AtF7De5qgsFIC4jbffoXCePp+Zgy2B8cvVDDcg
PIQs2HFlvb+I/EfSNiLZEfJ8YUzcNy9+u0MGGehFqnxblDOYeAHWCwDIvU6Uk/oo
UFQARuxWyG20PUdF7vbsOGrsoXxadqQdSBbecpRnCpefQrWtTFB9M49/gZy3u5mw
jG0kZ1k0sKggwGl14DovDad2gjitm/z2lj2YDEoNC4l8gxRp+G77i16x+ZH+PuW/
4/Cryo+ECruw++GVXmKmpWRjv/p1HVLnnL56ADxJRlNx9Gb05rM3d9tE1LkoVAqx
iR5TOueiDiH69CjWW1owFKaiVeVc1cIH+lFFI5MuNN2jsTCWYHblTvIzCm0J/7RS
pDW7cMnDxAwZerfpnt1W
=O8LD
-----END PGP SIGNATURE-----

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

Reply via email to