users@glassfish.java.net

Re: Security Credentials and Glassfish

From: <glassfish_at_javadesktop.org>
Date: Tue, 14 Aug 2007 14:58:42 PDT

We did something like this, but it is not straight forward, and, in fact, I'm not 100% positive it works all the way through. But I can share what we tried to do and how we did it.

The basics first.

The key to the entire process is an internal SecurityContext managed by Glassfish, and this is stored on a ThreadLocal to be handed about and leveraged within the code.

The basic problem, tho, is that as an application programmer, you basically have absolutely no visibility or accessibility to this. For example, you just can't set the username on the fly.

For our application, we had to implement a custom Glassfish Realm. The realm is the part that takes a user password and return a yay/nay for authentication as well as a list of Groups for Authorization.

When we ran in to the problem that you're encountering, we leveraged our realm.

Essentially, we wanted what you were talking about -- to be able to set up the security on an MDB to be that of the originating user (and the same thing for EJB Timer beans as well, same problem).

GlassFish has a non-portable mechanism for "logging in" to the the container. If you wanted to create a custom authentication filter or something, you'd leverage this service.

The class is called "ProgrammaticLogin". It takes a user name and password, verifies them and then populates the SecurityContext.

So, we leveraged that and, well, cheated.

To implement a realm you implement a realm class and a LoginModule.

What we did is we, to be blunt, put a back door in to our LoginModule. If the login module is called with a special password, we simply "log the user in". So, every user has two "passwords", their private password, and an internal global password.

Since we don't log in to our system anywhere save for the web tier, and we have our own login forms (vs using the container login), we basically ensure that noone can enter the "secret" password as a valid password from the web tier. So, that helps ensure that the backdoor won't be actually useful outside from the web tier, it's only an internal password.

As I said before, it's hack. A hack with an old, dull, rusty machete. But we couldn't find a better mechanism to restore a SecurityContext for a user programmatically. Oh, we pass along the user name as part of the information in the message or timer task when the job is submitted.

It's a nut of a problem. As, fundamentally, you need to be able to recover this SecurityContext through an application restart (future schedule EJB Timer tasks, or the app server failing after the message is submitted to the JMS queue, but has not yet been actually processed) and through potentially foreign JMS systems or serialization to a DB. So, you're toss about this blob of text that has, in theory, "free reign", an "authorized" blob of data. Ideally, you'd encrypt and sign the MDB message data, or the parameter to the EJB Timer so as someone couldn't go in through the external systems and change the user name from "Bob Jones" to "Administrator". We did not take it quite to that level.

So far in light testing and use it SEEMS to work, but I can't guarantee we won't bump in to some corner case in the future where it doesn't because of the shenanigans we're playing, and when and where we're playing them.

But the technique might help you, or perhaps we'll garner some developer interest with insight as to a better way.
[Message sent by forum member 'whartung' (whartung)]

http://forums.java.net/jive/thread.jspa?messageID=230895