(Originally miss-posted in the FAQ forum.)
OK, I've been trying to make an application's authorizing part for several days now and I don't even start to understand how to use JAAS with JBOSS. Either I'm too stupid (which could well be the case) or the docs are too brief, confusing and generally assuming that the user is already a seasoned expert in EJB's and JAAS. (I'm neither.) So far, it looks like it would have been less work (if also a lot less elegant) to just propagate the login data in each EJB method and be done with it.
The first thing is that it's NOT about servlets running in the same JVM. It's about client applications running not only in a different JVM, but likely on another machine and on another site.
It's also NOT about user names and passwords, but about authorizing the client applications, which in turn do their own user management. There's an application key data object (including application id, password, the application's own user id and whatever else needed) which needs to be hauled over RMI to the server, checked and (if correct) stored and a handle is issued as the principal.
So I start with the obvious: make a straightforward AppLoginModule and an AppLoginDataCallback and the corresponding callback handler. The AppLoginModule sends an array with just the AppLoginDataCallback, the handler sets the AppLoginData key in the callback and returns. The AppLoginModule would check and store the data, issue a unique key wrapped in a SimplePrincipal, and set the SecurityAssociation principal and credentials for it.
It works off-line (i.e., without JBOSS involved) with JAAS, or at least it gives me a principal all right...
Now let's get JBOSS involved.
First it doesn't even work at all. The same code seems to still login into the application's own JAAS library, instead of into the one in JBoss. Then it propagates that locally obtained Principal to JBOSS, which obviously never heard of it and rejects it.
I eventually run out of better ideas and make a huge wrapper EJB for one of the actual EJB's, with PrivilegedAction classes for each actual EJB call. Now my application calls this wrapper EJB, which itself tries to login inside JBOSS, before forwarding the call. I know it's inefficient, inelegant, and probably the Wrong Thing (TM), but hey...
Oops, now JBOSS can't find the AppLoginModule, even though it's right there in lib/ext. After a couple more hours of trying every stupid thing and muttering dark curses at the monitor, I find out that I need to use the org.jboss.security.auth.spi.ProxyLoginModule. Oh well...
Then I discover another cute problem. The login data was handled by an EJB, since it also needs to be manageable somehow. (And various services must be able to ask for details about an application calling them.) The AppLoginModule was really just calling the EJB to store the data and get the principal. Now I can't call the AppLoginEJB to get a principal, because I don't yet have a valid principal, but can't get a principal before I call the EJB. Catch 22.
OK, I take the whole checking code out for now, planning to just move it later somewhere else. (An MBean maybe, or make the AppLoginData object be a Principal itself.) So now the login module just issues a random principal itself, without calling the EJB or anything else.
Ok, so let's recap the chain so far: the client calls the wrapper EJB (which isn't in a security zone), which logs in, and then calls the original EJB (which is in a security zone) via a doAs().
Now the wrapper EJB does log in (finally), and I'm actually issued a principal. (The System.out.println's lavishly scattered all over the code say so.) Only when I actually forward the call to the original EJB, I get an exception. Apparently SecurityInterceptor.checkSecurityAssociation() doesn't like my shiny new Principal after all.
Anyone has any ideas what I'm doing so awfully wrong please?
Thanks in advance.
Are you using JBoss 2.4.X or 3.0 ? (I only know about 2.4)
You need to do something client-side, and server-side. If you forget the client-side part, then the JBoss context would not be set, perhaps this is your problem ? (to be honest, I'm having a hard time following your problem description; either it's too long or it's because I just had a couple of beers - probably the latter)
In any case, the best way to understand JBoss' JAAS integration in JBoss 2.4.x is to work through the following article
It did take me some time but gave me a good understanding and afterwards I had no trouble implementing what I wanted to do.
Basically to cut down that frustrated newbie experience story, my problem is: I don't authenticate with a name and password, but with a custom object. A key, if you will. That object contains all the data needed. How do I get authenticated on the server with that thing, please?
I don't need roles. (Those roles don't even start to cover the kind of situations we'll have to authorize.) I don't need method persmissions. (Ditto.) I don't need anything fancy. Just to get one big data object from an application to the server, and to get a working Principal back.
And I'm in JBoss 2.4.4.
And, well, I did guess I need to do something client side, too, but I'm completely out of clue as to what, where or how. Every tutorial I've read so far seemed to work on the assumption that "oh, just use the existing ClientLoginModule to get your name and password to JBoss", but noone seems to mention what to do when I don't authenticate with a username and password to start with, and as such the ClientLoginModule doesn't do anything at all for me. Or better yet, didn't even touch the part where you use a server.
Thanks for the link to that article. I'm reading through it right now.
Sounds like you are going to have to write your own custom login module to take your username and key, authenticate and construct a working Principal for you. Try reading the steps for creating a Custom Login Module at:
Hope this helps,
I did and I sort of have a login module which works off-line, but the problem was how to get that data to the server. I've just got the idea that I may be able to use the ClientLoginModule after all. I think I'll just take that key, serialize it, make a Base64 out of those bytes and use that as both username and password.
Completely unrelated and just for the sake of going on a tangent, so far I'm kinda wondering what the advantage of JAAS is, after all. The more I read about it, the more it looks like a buzzword to have on the resume, but not much more. Simply having the authentication/authorizing be function call from a different jar or EJB offers exactly the same separation between business logic and authorizing logic, but with less headache or overhead.
Simply reading the JAAS doc and JBoss security doc will only make you sleepy! Without fully understand how things are working together internally(client side interceptors and server side interceptors), it is hard to get things to work. You owe yourself a J2EE training. J2EE security is not hard, it's actually great! JBoss also gives you a lot of capabilities to customize your security implementation. I fully understand all these frustrations because I have gone through this. But what I found out was most of the docs from JBoss are correct, yet brief. You just need to understand each sentence in it.
A lot of people hope to find EVERYTHING in the forums. It probably works for some very specific issues. But for something like JBoss security, it's better to get some consulting service from JBoss LLC or someone who has done it. It could save you a lot of time and money!!
my 2 cents.
I'm having a similar problem with the 'Catch 22' issue, where EJB's are used in the authentication process. One approach might be to create two LoginModules: the first module provides basic authentication for the 'unauthenticated' user, which allows the second to instantiate EJB's and authenticate for users requiring authentication. I'll let you know how I go with this approach.
zx44093, I'm not opposed to the idea of going to some training, except I'm just a lowly peon at a corporation which isn't even interested in JBoss in the first place. We're really supposed to deploy on WebSphere, only someone above me on the food chain thought "hey, we might as well use JBoss for development and local testing purposes."
Which brings me back to the question about JAAS. By the looks of it, each and every single EJB server developper ran amok in another direction with their security implementation. After I'm through with banging my head against the wall to get this to run in JBoss for the proof of concept, I'll likely have to start all over again and do something completely different for WebSphere. (And god help me if someone changes his mind and wants WebLogic next.)
So exactly what did I gain there? The dubious honour of having my code locked into some vendor's own incompatible JAAS implementation.
OK, in case it helps anyone, I seem to have gotten this thing to work. The things to have in mind, although they may not be exactly clear from the tutorials and stuff are:
1) You must assign roles in the login module. Yes, even if you have your own programmatic security, and even if you have as much use for those JAAS roles as a fish needs a bicycle, or as much as an ice cream needs chilly peppers. So don't forget to make a Group called "Roles" in your principals and add at least one bogus SimplePrincipal with a role name. (E.g., I used one called "application".)
2) You must assign method permissions using that bogus role. (Again, no matter how pointless and irrelevant that declarative security stuff is to your actual project.) You can use "*" to catch all EJB methods, but don't forget to add a separate permission for "create", which is used in your EJB's home. For some reason, "*" doesn't also cover "create". (As if it makes any sense to have rights to all an EJB's methods, but no rights to connect to the EJB.)
3) If you're stuck with using your own data object to authenticate, you can use the default ClientLoginModule on the client side to get that to the actual LoginModule on the server after all. Just use a String representation of your data object as a username and password, and be ready to rebuild the original object from the String on the server side. (E.g., serialize the data object to a byte array and make a String with those bytes in hex or base64 or whatever. I did my own conversion to hex of the data fields in the object, to skip the serialization, but same idea.)
The actual LoginModule on the server will then ask for the username and get this serialzed for back, reconstruct the data object, and check it.
4) If the data object is identification enough (and it should be if you authenticate with it), then that serialized String form can also be used as a SimplePrincipal. (Or, of course, you can make the whole data object implement Principal.) So no need to store it anywhere and generate a new ID as a principal. That makes sure that your EJB's have instant access to the data object by just getting the principal, without any further calls to some EJB or JMX.
5) With the Catch 22 situation, unfortunately there is no easy solution. Once you made an EJB require authentication, you can't say something like "but it can be used without authentication from within the container". So you can't use its methods from your custom LoginModule. You will have to duplicate the authentication code from the LoginEJB to the LoginModule, either by cut-and-paste or (preferrably) by making it a library.
6) Yes, I'm bitter, but I prefer to think of it as "grapefruit flavoured" :p
It's so common that people who use JBoss don't want to spend any money on it even it's a free and great product.
One thing I want to point out is that you should be able to plug in your own JAAS implementation (at least in JBoss). It should not be vendor dependent even vendors come with some kind of reference implementation.
Well, I'll admit that's a good issue, but the thing is: the corporate people who make the money decisions don't want JBoss at all, free or non free. They already have a big fat contract with IBM, and they already paid a ton of money for WebSphere. Even I can see some point in trying to maximize that existing investment, instead of throwing all those WebSphere licenses out the window and starting from scratch with JBoss.
Basically they sort of tollerate (but not encourage) our using JBoss or whatever else we wish for development purposes, as long as the final product does run on WebSphere. But good luck in trying to get them to actually pay for that.