You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Christopher Schultz <ch...@christopherschultz.net> on 2015/10/06 19:05:32 UTC

Using CredentialHandlers in application code

All,

We (somewhat) recently introduced the CredentialHandler to Tomcat in
order to make it easier to use different password-munging strategies
along with all the Realm implementations. A good example is using a hash
like SHA-256 in one case (using MessageDigest) and using PBKDF2 in
another case (using SecreyKey, etc.). In the past, we had been limited
to whatever the MessageDigest class could support, and we have a nice,
flexible system, now.

This is great for authentication against data already stored somewhere
e.g. a relational database. But it currently does not have an obviously
usable component for an application.

Yes, you can drop catalina.jar into your application's lib directory and
then you can do this:

        SecretKeyCredentialHandler ch = new SecretKeyCredentialHandler();

        ch.setAlgorithm(ALGORITHM);
        ch.setIterations(ITERATIONS);
        ch.setSaltLength(SALT_LENGTH);;
        ch.setKeyLength(KEY_LENGTH);

        hashedPassword = ch.mutate(user.getPassword());

... but there are two downsides to this:

1. The whole of catalina.jar is included in your application, possibly
   breaking a great many things
2. You have to make sure that all of the values match whatever you have
   configured in your <CredentialHandler> element in context.xml
   (or server.xml)

To solve the first problem, I'm wondering if we could produce an
artifact during the build that just contains the interfaces, etc. for
the CredentialHandlers. This would allow users to build against them and
even lazily deploy them with their code.

For the second issue, I don't see any opportunities at present.

It doesn't look like the application's Realms are available via JMX if
they are declared local to the application -- only the global Realms are
represented by MBeans. Also, it doesn't look like the Realms offer
access to the CredentialHandlers even if they were available.

I think these are two oversights that ought to be corrected: local
Realms ought to be locatable via JMX just as local DataSources are
available in e.g.
Catalina:type=DataSource,host=[host],context=/[context-path],class=javax.sql.DataSource,name="[name]"
and also Realms ought to expose information about their CredentialHandlers.

If those are available, then applications can simply grab the same
CredentialHandler that Tomcat is using for authentication and use it for
two obvious use-cases I can think of:

1. Preparing new credentials for saving to the user data store (e.g.
   registration, change-password, etc.)
2. Verifying existing credentials without Tomcat performing
   authentication (e.g. check-password required to update account
   info, inspect password history to prohibit repeats, etc.)

The only caveat is that the application definitely would not be able to
deploy either catalina.jar or catalina-only-credential-handlers.jar,
otherwise they'll get ClassCastExceptions when they try to use them. But
that's okay: documentation can take care of that to some degree.

Does anyone have any thoughts on any of those items? I'd really like for
applications to be able to re-use those components if possible.

Thanks,
-chris


Re: Using CredentialHandlers in application code

Posted by Mark Thomas <ma...@apache.org>.
On 07/10/2015 16:33, Christopher Schultz wrote:
> Mark,
> 
> On 10/6/15 2:44 PM, Mark Thomas wrote:
>> On 06/10/2015 18:05, Christopher Schultz wrote:
>>> All,
>>>
>>> We (somewhat) recently introduced the CredentialHandler to Tomcat in
>>> order to make it easier to use different password-munging strategies
>>> along with all the Realm implementations. A good example is using a hash
>>> like SHA-256 in one case (using MessageDigest) and using PBKDF2 in
>>> another case (using SecreyKey, etc.). In the past, we had been limited
>>> to whatever the MessageDigest class could support, and we have a nice,
>>> flexible system, now.
>>>
>>> This is great for authentication against data already stored somewhere
>>> e.g. a relational database. But it currently does not have an obviously
>>> usable component for an application.
>>>
>>> Yes, you can drop catalina.jar into your application's lib directory and
>>> then you can do this:
>>>
>>>         SecretKeyCredentialHandler ch = new SecretKeyCredentialHandler();
>>>
>>>         ch.setAlgorithm(ALGORITHM);
>>>         ch.setIterations(ITERATIONS);
>>>         ch.setSaltLength(SALT_LENGTH);;
>>>         ch.setKeyLength(KEY_LENGTH);
>>>
>>>         hashedPassword = ch.mutate(user.getPassword());
>>>
>>> ... but there are two downsides to this:
>>>
>>> 1. The whole of catalina.jar is included in your application, possibly
>>>    breaking a great many things
>>> 2. You have to make sure that all of the values match whatever you have
>>>    configured in your <CredentialHandler> element in context.xml
>>>    (or server.xml)
>>>
>>> To solve the first problem, I'm wondering if we could produce an
>>> artifact during the build that just contains the interfaces, etc. for
>>> the CredentialHandlers. This would allow users to build against them and
>>> even lazily deploy them with their code.
>>
>> It doesn't look to be that easy to extract the relevant classes and
>> their dependencies into a separate JAR. If folks want to interact with
>> the Tomcat internals I don't think it is unreasonable to expect them to
>> compile against the standard JARs.
> 
> What about an ant target to build just that JAR? It's pretty simple for
> us to add, and we could just leave it in the src package. So it's one
> more step for a dev to build a separate JAR (get the source package, or,
> alternatively, extract the classes).

Meh.

> Or we could just say "build against catalina.jar, but don't bundle it
> with your web app".

That works for me :).

>>> For the second issue, I don't see any opportunities at present.
>>>
>>> It doesn't look like the application's Realms are available via JMX if
>>> they are declared local to the application -- only the global Realms are
>>> represented by MBeans. Also, it doesn't look like the Realms offer
>>> access to the CredentialHandlers even if they were available.
>>>
>>> I think these are two oversights that ought to be corrected: local
>>> Realms ought to be locatable via JMX just as local DataSources are
>>> available in e.g.
>>> Catalina:type=DataSource,host=[host],context=/[context-path],class=javax.sql.DataSource,name="[name]"
>>> and also Realms ought to expose information about their CredentialHandlers.
>>
>> +1.
>>
>>> If those are available, then applications can simply grab the same
>>> CredentialHandler that Tomcat is using for authentication and use it for
>>> two obvious use-cases I can think of:
>>>
>>> 1. Preparing new credentials for saving to the user data store (e.g.
>>>    registration, change-password, etc.)
>>> 2. Verifying existing credentials without Tomcat performing
>>>    authentication (e.g. check-password required to update account
>>>    info, inspect password history to prohibit repeats, etc.)
>>>
>>> The only caveat is that the application definitely would not be able to
>>> deploy either catalina.jar or catalina-only-credential-handlers.jar,
>>> otherwise they'll get ClassCastExceptions when they try to use them. But
>>> that's okay: documentation can take care of that to some degree.
>>>
>>> Does anyone have any thoughts on any of those items? I'd really like for
>>> applications to be able to re-use those components if possible.
>>
>> Big +1 to the JMX.
> 
> I'll have a look at doing that. I'll start with making the CH available
> for a Realm since I think that will be slightly easier. Then I'll see
> about making local-realms visible. I'm not sure where all of that code
> is, so if someone wants to beat me to the punch, I'm happy to let them.

That should be as simple as ensuring the getters are available and
adding them to the MBean descriptors.

Accessing the CH will mean registering the CH. Probably best to do this
as part of the Realm registration.

>> No so sure about the separate JAR.
>>
>> How about a Realm option to expose the CredentialHandler via a customer
>> ServletContext attribute? That way users wouldn't have to jump through
>> JMX hoops including knowing the container names.
> 
> Oh, that would be way better. JMX is ... awful, but it gets the job done
> for remote-control and other similar use-cases.
> 
> I think it would be really great to have
> org.apache.catalina.realm.credentialHandler bound to the in-effect
> credential handler for the application. Is there a good way to protect
> servlet-context-scoped attributes so they can't be overwritten?

o.a.catalina.core.ApplicationContext.setAttributeReadOnly(String)

Mark

> 
> Thanks,
> -chris
> 


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


Re: Using CredentialHandlers in application code

Posted by Christopher Schultz <ch...@christopherschultz.net>.
Mark,

On 10/6/15 2:44 PM, Mark Thomas wrote:
> On 06/10/2015 18:05, Christopher Schultz wrote:
>> All,
>>
>> We (somewhat) recently introduced the CredentialHandler to Tomcat in
>> order to make it easier to use different password-munging strategies
>> along with all the Realm implementations. A good example is using a hash
>> like SHA-256 in one case (using MessageDigest) and using PBKDF2 in
>> another case (using SecreyKey, etc.). In the past, we had been limited
>> to whatever the MessageDigest class could support, and we have a nice,
>> flexible system, now.
>>
>> This is great for authentication against data already stored somewhere
>> e.g. a relational database. But it currently does not have an obviously
>> usable component for an application.
>>
>> Yes, you can drop catalina.jar into your application's lib directory and
>> then you can do this:
>>
>>         SecretKeyCredentialHandler ch = new SecretKeyCredentialHandler();
>>
>>         ch.setAlgorithm(ALGORITHM);
>>         ch.setIterations(ITERATIONS);
>>         ch.setSaltLength(SALT_LENGTH);;
>>         ch.setKeyLength(KEY_LENGTH);
>>
>>         hashedPassword = ch.mutate(user.getPassword());
>>
>> ... but there are two downsides to this:
>>
>> 1. The whole of catalina.jar is included in your application, possibly
>>    breaking a great many things
>> 2. You have to make sure that all of the values match whatever you have
>>    configured in your <CredentialHandler> element in context.xml
>>    (or server.xml)
>>
>> To solve the first problem, I'm wondering if we could produce an
>> artifact during the build that just contains the interfaces, etc. for
>> the CredentialHandlers. This would allow users to build against them and
>> even lazily deploy them with their code.
> 
> It doesn't look to be that easy to extract the relevant classes and
> their dependencies into a separate JAR. If folks want to interact with
> the Tomcat internals I don't think it is unreasonable to expect them to
> compile against the standard JARs.

What about an ant target to build just that JAR? It's pretty simple for
us to add, and we could just leave it in the src package. So it's one
more step for a dev to build a separate JAR (get the source package, or,
alternatively, extract the classes).

Or we could just say "build against catalina.jar, but don't bundle it
with your web app".

>> For the second issue, I don't see any opportunities at present.
>>
>> It doesn't look like the application's Realms are available via JMX if
>> they are declared local to the application -- only the global Realms are
>> represented by MBeans. Also, it doesn't look like the Realms offer
>> access to the CredentialHandlers even if they were available.
>>
>> I think these are two oversights that ought to be corrected: local
>> Realms ought to be locatable via JMX just as local DataSources are
>> available in e.g.
>> Catalina:type=DataSource,host=[host],context=/[context-path],class=javax.sql.DataSource,name="[name]"
>> and also Realms ought to expose information about their CredentialHandlers.
> 
> +1.
> 
>> If those are available, then applications can simply grab the same
>> CredentialHandler that Tomcat is using for authentication and use it for
>> two obvious use-cases I can think of:
>>
>> 1. Preparing new credentials for saving to the user data store (e.g.
>>    registration, change-password, etc.)
>> 2. Verifying existing credentials without Tomcat performing
>>    authentication (e.g. check-password required to update account
>>    info, inspect password history to prohibit repeats, etc.)
>>
>> The only caveat is that the application definitely would not be able to
>> deploy either catalina.jar or catalina-only-credential-handlers.jar,
>> otherwise they'll get ClassCastExceptions when they try to use them. But
>> that's okay: documentation can take care of that to some degree.
>>
>> Does anyone have any thoughts on any of those items? I'd really like for
>> applications to be able to re-use those components if possible.
> 
> Big +1 to the JMX.

I'll have a look at doing that. I'll start with making the CH available
for a Realm since I think that will be slightly easier. Then I'll see
about making local-realms visible. I'm not sure where all of that code
is, so if someone wants to beat me to the punch, I'm happy to let them.

> No so sure about the separate JAR.
> 
> How about a Realm option to expose the CredentialHandler via a customer
> ServletContext attribute? That way users wouldn't have to jump through
> JMX hoops including knowing the container names.

Oh, that would be way better. JMX is ... awful, but it gets the job done
for remote-control and other similar use-cases.

I think it would be really great to have
org.apache.catalina.realm.credentialHandler bound to the in-effect
credential handler for the application. Is there a good way to protect
servlet-context-scoped attributes so they can't be overwritten?

Thanks,
-chris


Re: Using CredentialHandlers in application code

Posted by Mark Thomas <ma...@apache.org>.
On 06/10/2015 18:05, Christopher Schultz wrote:
> All,
> 
> We (somewhat) recently introduced the CredentialHandler to Tomcat in
> order to make it easier to use different password-munging strategies
> along with all the Realm implementations. A good example is using a hash
> like SHA-256 in one case (using MessageDigest) and using PBKDF2 in
> another case (using SecreyKey, etc.). In the past, we had been limited
> to whatever the MessageDigest class could support, and we have a nice,
> flexible system, now.
> 
> This is great for authentication against data already stored somewhere
> e.g. a relational database. But it currently does not have an obviously
> usable component for an application.
> 
> Yes, you can drop catalina.jar into your application's lib directory and
> then you can do this:
> 
>         SecretKeyCredentialHandler ch = new SecretKeyCredentialHandler();
> 
>         ch.setAlgorithm(ALGORITHM);
>         ch.setIterations(ITERATIONS);
>         ch.setSaltLength(SALT_LENGTH);;
>         ch.setKeyLength(KEY_LENGTH);
> 
>         hashedPassword = ch.mutate(user.getPassword());
> 
> ... but there are two downsides to this:
> 
> 1. The whole of catalina.jar is included in your application, possibly
>    breaking a great many things
> 2. You have to make sure that all of the values match whatever you have
>    configured in your <CredentialHandler> element in context.xml
>    (or server.xml)
> 
> To solve the first problem, I'm wondering if we could produce an
> artifact during the build that just contains the interfaces, etc. for
> the CredentialHandlers. This would allow users to build against them and
> even lazily deploy them with their code.

It doesn't look to be that easy to extract the relevant classes and
their dependencies into a separate JAR. If folks want to interact with
the Tomcat internals I don't think it is unreasonable to expect them to
compile against the standard JARs.

> For the second issue, I don't see any opportunities at present.
> 
> It doesn't look like the application's Realms are available via JMX if
> they are declared local to the application -- only the global Realms are
> represented by MBeans. Also, it doesn't look like the Realms offer
> access to the CredentialHandlers even if they were available.
> 
> I think these are two oversights that ought to be corrected: local
> Realms ought to be locatable via JMX just as local DataSources are
> available in e.g.
> Catalina:type=DataSource,host=[host],context=/[context-path],class=javax.sql.DataSource,name="[name]"
> and also Realms ought to expose information about their CredentialHandlers.

+1.

> If those are available, then applications can simply grab the same
> CredentialHandler that Tomcat is using for authentication and use it for
> two obvious use-cases I can think of:
> 
> 1. Preparing new credentials for saving to the user data store (e.g.
>    registration, change-password, etc.)
> 2. Verifying existing credentials without Tomcat performing
>    authentication (e.g. check-password required to update account
>    info, inspect password history to prohibit repeats, etc.)
> 
> The only caveat is that the application definitely would not be able to
> deploy either catalina.jar or catalina-only-credential-handlers.jar,
> otherwise they'll get ClassCastExceptions when they try to use them. But
> that's okay: documentation can take care of that to some degree.
> 
> Does anyone have any thoughts on any of those items? I'd really like for
> applications to be able to re-use those components if possible.

Big +1 to the JMX.

No so sure about the separate JAR.

How about a Realm option to expose the CredentialHandler via a customer
ServletContext attribute? That way users wouldn't have to jump through
JMX hoops including knowing the container names.

Mark


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