Friday, November 20, 2009

LoginContext of ACC or more?

Many of the questions I see on Google are about how to setup a LoginContext and then use that context to login to the Glassfish server. First off, the server already creates a LoginContext for you, you do not need to make another one unless you have some real serious demands. Second, when you do make a new LoginContext you are making it outside of the Glassfish server.

JAAS uses a set of local files to determine which Java Objects (modules) to execute in order to make a login. Those configuration files also specify which of those modules are required to send back a "GO" to equal a full login. This is called a stacked login. You could have an application that requires not only a username and password, but also a smart card inserted. If either or both of them return a "NO-GO" then you are denied access.

The thing about JAAS is servers are not the only ones that can use it. You could make your normal Java 2 SE program use JAAS to authenticate smart cards or even a flat file that holds encrypted passwords stored on the local machine. Because anyone could have any given set of configuration files setup on their machine, when you use Glassfish to secure EJBs understand that Glassfish considers the server's configuration files to be the final say in the matter of logging on to access the EJB.

When you create your own LoginContext in your client application, JAAS has to consult the local configuration files. Since a JVM outside of the Glassfish JVM is running your client application, these JAAS configuration files have no say in authenticating your client to Glassfish.

Enter the ClientPasswordLoginModule. This module is a pretty neat little module. It takes in a client username and password and stores it. If you try to go somewhere that requires you to login, this module will take the information that it collected and pass it on to the module asking for login information.

Here is where some people get confused. They assume that the local JAAS needs to use the same module as the Glassfish module. No. Becuase there is no way the Glassfish server can be sure that your local result would be the same result with the Glassfish configuration. If our Application Client used a jdbcModule in the local JAAS configuration, we could (in theory) use a local MySQL to say (Oh yeah, he's who he says he is.) Instead, we have to pass username/password information on to the Glassfish server and the Glassfish server runs it through its jdbcModule, not our local jdbcModule. ClientPasswordLoginModule simply passes that information on to whoever asks for it.

You may also have heard of a ClientCertificateLoginModule, this allows a client to send a X509 certificate to login to a system. Usually your appclient is setup to use both ClientPasswordLoginModule and ClientCertificateLoginModule. The ClientCertificateLoginModule doesn't really do much if you haven't signed the application. If you have, this module makes sure that only the application that was signed is being used to access the resources. This keeps rouge applications from accessing your data. If you want IIMOP over SSL that's a whole other thing.

Remember, when you create a LoginContext inside you Java Client Application it will read in the local JAAS configurations. Those configurations should be setup to pass information back to Glassfish. However, my advice is to not even create your own LoginContext. The ACC on Glassfish is good enough for most needs, you shouldn't have to create your own LoginContext. I'll cover a method of how to get a bit more control over user logins with EJBs on Glassfish with your plain ol' Java Application Client.


Unknown said...

Hello I am interested in the last sentence. I have an application client that accesses secure EJB. I do not like the eager authentication that happens when I inject the EJB. Is there a way to defeat this mechanism? How can I gain more control over this?

Justin said...


When you inject a secure resource you are using it!

Your injected resource will be resolved on it's first use. In order to resolve it you must authenticate.

I think what you want is to be able to check to see if the person logged in correctly and do something if they didn't? Correct?

You can do that in a round about way. You can create a secure EJB that does about nothing and see what happens when you try to access it. That will mean they failed login or something.

However, the correct way to do a more custom login process is to use programmatic login.

You can find out about all of that in the Java EE 6 spec.