...
The third possibility is that the individual application may have a JAAS configuration file embedded in it. A path to a login configuration file is part of the client API. Of course, this packaging violates the original idea of separating authentication as a system administration function from the application programmer's domain, but not all institutions have Java literate system administrators.
What's in a Name?
JAAS configuration offers enormous flexibility, but this leaves an ambiguity that should be resolved by institutional policy. If it is not given some global thought, you leave room for inconsistency and confusion.
During application development, it makes sense for system administrators to create a set of pre-packaged JAAS configuration parameters representing the different supported types of authentication and different back end servers that the local environment supports. This suggests names like MITKerberosAuth or ActiveDirectoryLdapAuth. The application programmer can regard these names as configured system services and use them to get started.
However, when an application is deployed in production, the JAAS design seeks to completely separate the authentication mechanism from the application code. Even using a name that indicates a particular protocol or back end service contradicts this design objective. This produces two plausible naming conventions.
An application could use its own name as the JAAS configuration bundle name. Thus the CAS Server could specify "cas-server" as the bundle name. This is a good default for a product that is distributed to lots of different institutions that have to make up their own local policy about what authentication mechanism to use, but if the default is not changed then the typical institutional JAAS login configuration file will have dozens of identical configuration bundles differing only in the the application name at the start of the bundle.
Alternately, an institution could specify a small number of bundle names representing the generic type of authentication (an authentication design pattern) that an application might select (SingleSignOn, SingleSignOnWithProxy, SharedAuthentication). Note that these names do not reflect a particular protocol or server, but neither are they limited to a particular application. Unfortunately, these design patterns have not be assigned industry standard names, so this preferred approach will probably vary from institution to institution.
The JAAS Objects
An application using JAAS creates a LoginContext object associated with the name of a bundle of configuration data. Up to this point each example has shown the configuration of a single fully qualified classname and its parameters. However, JAAS allows a named bundle to configure more than one plug-in module, allowing the user to make a single call and log into either the first system that accepts him or more than one back end system (Kerberos and LDAP for example).
The JAAS client application calls the login() method of the LoginContext object. After a sucessful login, the LoginContext has acquired a javax.security.auth.Subject object and one or more javax.security.auth.Principal objects (there will be one Principal for every sucessful login to a different plug-in class in the named configuration bundle).
If you are just using JAAS to validate a userid and password, you will never inspect the Subject or Principal objects. Immediately after the sucessful login(), such code calls the logout() method of the LoginContext to delete all the generated objects and clean everything up.
Actually examining the generated objects may provide a bit of interesting but probably useless information. For example, after a successful LDAP login to Active Directory by userid "gilbert" (which in the previous configuration example above searches for an LDAP User object with sAMAccountName=gilbert), one might be mildly interested that the Distinguished Name of the LDAP User object was "CN=gilbert, CN=Users, DC=yu, DC=yale, DC=edu", but this is hardly an unexpected result.
The JAAS Objects when you use Krb5LoginModule
JAAS internal behavior becomes a lot more interesting in the special case where you use the standard Sun Kerberos 5 plug-in module. Extra function becomes available and a variety of new use cases is exposed when you add a few extra configuration parameter options.
The first interesting parameter is "useTicketCache=true". This exploits the special permission that JAAS has to do different things on different operating systems. With this parameter, JAAS shares whatever is the native host operating system Kerberos login ticket storage mechanism. On a Windows machine logged into an Active Directory domain, JAAS can simply connect to the existing login and create a Subject and Principal that reflects the host environment native Windows userid.
SPN
Up to this point, we have discussed the userid of individuals. However, in Kerberos each server has an identity called the Service Principal Name. A Web Server on a machine named "secure.its.yale.edu" has an SPN of "HTTP/secure.its.yale.edu". When you use real Kerberos protocol, including real K5 Service Tickets, then the client logs on to Kerberos with his userid, the server logs on with the SPN, and then the client obtains a Service Ticket that the server can validate.
JAAS can be used to log the service into Kerberos using the SPN. In theory, you can use the standard JAAS login simply replacing the userid with an SPN, but while a service has an identity it does not typically use a regular password. The more common convention is for a system administrator to use Kerberos utility tools to create a "keytab" file. The keytab file contains the private key that Kerberos really uses to identify services on the network. The Krb5LoginModule has parameters "useKeyTab=true" and "keyTab=path/to/file" to support the login of a service.
In the special case where Active Directory provides the Kerberos service, Microsoft allows a standard SPN to be "mapped" to a dummy User object also in AD. For example, one can create a dummy user named "s_cas" in Active Directory and give it a normal password. Then, one can use administrator tools in AD to map the "HTTP/secure.its.yale.edu" SPN ID to the "s_cas" userid. Now instead of using the keytab=... form of login, the service (corresponding to URL "https://secure.its.yale.edu/cas") can login using the standard userid/password API of JAAS with the userid "s_cas" and the password assigned to that dummy user account.
Either way, after the service logs in through the Krb5LoginModule of JAAS, if it has requested that the ticket be stored in a ticket cache and uses the "storeKey=true" configuration parameter, the Subject and Principal objects created by the LoginContext contain the information that the Java service needs to validate real Kerberos 5 Service Tickets.
Real Service Ticket Validation
Which brings us to yet another use of the Krb5LoginModule. In addition to logging real desktop user clients into Kerberos with a userid and password, and logging a service SPN into Kerberos using a keytab or mapped userid, Krb5LoginModule can "login" a the remote network client using the Service Ticket supplied by that remote client specifically for use by this particular service SPN.
Obviously somewhere under the covers there is an explicit description of this specific use of the JAAS API. However, in most common cases it is used under the covers by some other technology or library. The first step is to log in the service (using the keytab or mapped service userid). Then from the credentials stored in the Subject and Principal objects the code can extract the private key of the service which is used by Service Ticket validation.
Now you need an entirely different LoginContext (because now the Subject will be the remote use of the service and not the service itself). It too has to be configured to use Krb5LoginModule and obviously it will be using the same KDC as the previous step. However, it will have different configuration parameters and therefore will probably use a different bundle name. Now we waive our hands a bit because the details are uncertain, but somehow the remote user obtains a Service Ticket targeted to this SPN and it transmits the ticket to us. Using the Ticket instead of a userid/password as credentials, and plugging into the second LoginContext the private key obtained from the Subject object of the first LoginContext we provide Krb5LoginModule everything it needs to validate the Service Ticket and create in the second LoginContext Subject and Principal objects that represent the authenticated remote user.
Now the gotcha. There is no public standard Java API that directly obtains Service Tickets for a remote service. However, GSSAPI does this under the covers as part of its protocol. When it does this, GSSAPI and JAAS operate together sharing Kerberos configuration info and some ticket and key objects. It is through this collaboration and not through some pure, naked Kerberos API that we most commonly find Kerberos Service Ticket validation operating. In Web applications, this means the use of SPNEGO authentication.
...
Interestingly, when the client specifies a login file it is added to, instead of replacing, the login configuration files supplied by the JRE. A configuration parameter bundle name must be unique within the complete set of files used (an exception is thrown if the same name is found in both the application file and the JRE file). Thus the application cannot override a bundle name already defined by the JRE but can only add new bundle names.
What's in a Name?
JAAS configuration offers enormous flexibility, but this leaves an ambiguity that should be resolved by institutional policy. If it is not given some global thought, you leave room for inconsistency and confusion.
During application development, it makes sense for system administrators to create a set of pre-packaged JAAS configuration parameters representing the different supported types of authentication and different back end servers that the local environment supports. This suggests names like MITKerberosAuth or ActiveDirectoryLdapAuth. The application programmer can regard these names as configured system services and use them to get started.
However, when an application is deployed in production, the JAAS design seeks to completely separate the authentication mechanism from the application code. Even using a name that indicates a particular protocol or back end service contradicts this design objective. This produces two plausible naming conventions.
An application could use its own name as the JAAS configuration bundle name. Thus the CAS Server could specify "cas-server" as the bundle name. This is a good default for a product that is distributed to lots of different institutions that have to make up their own local policy about what authentication mechanism to use, but if the default is not changed then the typical institutional JAAS login configuration file will have dozens of identical configuration bundles differing only in the the application name at the start of the bundle.
Alternately, an institution could specify a small number of bundle names representing the generic type of authentication (an authentication design pattern) that an application might select (SingleSignOn, SingleSignOnWithProxy, SharedAuthentication). Note that these names do not reflect a particular protocol or server, but neither are they limited to a particular application. Unfortunately, these design patterns have not be assigned industry standard names, so this preferred approach will probably vary from institution to institution.
The JAAS Objects
An application using JAAS creates a LoginContext object associated with the name of a bundle of configuration data. Up to this point each example has shown the configuration of a single fully qualified classname and its parameters. However, JAAS allows a named bundle to configure more than one plug-in module, allowing the user to make a single call and log into either the first system that accepts him or more than one back end system (Kerberos and LDAP for example).
The JAAS client application calls the login() method of the LoginContext object. After a sucessful login, the LoginContext has acquired a javax.security.auth.Subject object and one or more javax.security.auth.Principal objects (there will be one Principal for every sucessful login to a different plug-in class in the named configuration bundle).
If you are just using JAAS to validate a userid and password, you will never inspect the Subject or Principal objects. Immediately after the sucessful login(), such code calls the logout() method of the LoginContext to delete all the generated objects and clean everything up.
Actually examining the generated objects may provide a bit of interesting but probably useless information. For example, after a successful LDAP login to Active Directory by userid "gilbert" (which in the previous configuration example above searches for an LDAP User object with sAMAccountName=gilbert), one might be mildly interested that the Distinguished Name of the LDAP User object was "CN=gilbert, CN=Users, DC=yu, DC=yale, DC=edu", but this is hardly an unexpected result.
The JAAS Objects when you use Krb5LoginModule
JAAS internal behavior becomes a lot more interesting in the special case where you use the standard Sun Kerberos 5 plug-in module. Extra function becomes available and a variety of new use cases is exposed when you add a few extra configuration parameter options.
The first interesting parameter is "useTicketCache=true". This exploits the special permission that JAAS has to do different things on different operating systems. With this parameter, JAAS shares whatever is the native host operating system Kerberos login ticket storage mechanism. On a Windows machine logged into an Active Directory domain, JAAS can simply connect to the existing login and create a Subject and Principal that reflects the host environment native Windows userid.
SPN
Up to this point, we have discussed the userid of individuals. However, in Kerberos each server has an identity called the Service Principal Name. A Web Server on a machine named "secure.its.yale.edu" has an SPN of "HTTP/secure.its.yale.edu". When you use real Kerberos protocol, including real K5 Service Tickets, then the client logs on to Kerberos with his userid, the server logs on with the SPN, and then the client obtains a Service Ticket that the server can validate.
JAAS can be used to log the service into Kerberos using the SPN. In theory, you can use the standard JAAS login simply replacing the userid with an SPN, but while a service has an identity it does not typically use a regular password. The more common convention is for a system administrator to use Kerberos utility tools to create a "keytab" file. The keytab file contains the private key that Kerberos really uses to identify services on the network. The Krb5LoginModule has parameters "useKeyTab=true" and "keyTab=path/to/file" to support the login of a service.
In the special case where Active Directory provides the Kerberos service, Microsoft allows a standard SPN to be "mapped" to a dummy User object also in AD. For example, one can create a dummy user named "s_cas" in Active Directory and give it a normal password. Then, one can use administrator tools in AD to map the "HTTP/secure.its.yale.edu" SPN ID to the "s_cas" userid. Now instead of using the keytab=... form of login, the service (corresponding to URL "https://secure.its.yale.edu/cas") can login using the standard userid/password API of JAAS with the userid "s_cas" and the password assigned to that dummy user account.
Either way, after the service logs in through the Krb5LoginModule of JAAS, if it has requested that the ticket be stored in a ticket cache and uses the "storeKey=true" configuration parameter, the Subject and Principal objects created by the LoginContext contain the information that the Java service needs to validate real Kerberos 5 Service Tickets.
Real Service Ticket Validation
Which brings us to yet another use of the Krb5LoginModule. In addition to logging real desktop user clients into Kerberos with a userid and password, and logging a service SPN into Kerberos using a keytab or mapped userid, Krb5LoginModule can "login" a the remote network client using the Service Ticket supplied by that remote client specifically for use by this particular service SPN.
Obviously somewhere under the covers there is an explicit description of this specific use of the JAAS API. However, in most common cases it is used under the covers by some other technology or library. The first step is to log in the service (using the keytab or mapped service userid). Then from the credentials stored in the Subject and Principal objects the code can extract the private key of the service which is used by Service Ticket validation.
Now you need an entirely different LoginContext (because now the Subject will be the remote use of the service and not the service itself). It too has to be configured to use Krb5LoginModule and obviously it will be using the same KDC as the previous step. However, it will have different configuration parameters and therefore will probably use a different bundle name. Now we waive our hands a bit because the details are uncertain, but somehow the remote user obtains a Service Ticket targeted to this SPN and it transmits the ticket to us. Using the Ticket instead of a userid/password as credentials, and plugging into the second LoginContext the private key obtained from the Subject object of the first LoginContext we provide Krb5LoginModule everything it needs to validate the Service Ticket and create in the second LoginContext Subject and Principal objects that represent the authenticated remote user.
Now the gotcha. There is no public standard Java API that directly obtains Service Tickets for a remote service. However, GSSAPI does this under the covers as part of its protocol. When it does this, GSSAPI and JAAS operate together sharing Kerberos configuration info and some ticket and key objects. It is through this collaboration and not through some pure, naked Kerberos API that we most commonly find Kerberos Service Ticket validation operating. In Web applications, this means the use of SPNEGO authentication.
JAAS in a Container (JBoss)
The JAAS client program API and the Service Provider Interface (SPI) to the plug-in modules represent two perfectly acceptable interfaces that anyone trying to solve the same problem would have to reinvent. Furthermore, the particular Sun plug in modules provide sophisticated services (especially Krb5LoginModule) that it would be wasteful to try and reproduce.
However, the standard JAAS service is a J2SE interface. The application creates a LoginContext, logs in, and obtains Subject and Principal objects. Only the application knows it has done this. Furthermore, the LoginContext and Subject are private to the class that does the login and have no wider visibility unless the application code chooses to invent some convention.
JBoss exposes to its JVM environment what might be called JAAS+. It is the standard JAAS service, plug-ins, and an XML version of the standard configuration file. The extra added feature is that the JAAS generated Subject and Principal objects are not only returned to the caller's LoginContext, but they also become part of the container's Security Context environment. They become a feature of the Request and the Thread that has been assigned to process it. When an EJB is called, they propogate to the EJB environment, even across a Remote call to an EJB on another JBoss server.
For this to work, the Subject/Principal has to be in some sense "serializable". Obviously if you login to Krb5LoginModule the ticket you receive cannot itself be transmitted to another machine. If the login presented a userid/password, then these "primary credentials" can be stored in the Subject/Principal, serialized, transmitted to a second system, and then the second system can do a second primary login presenting the same userid/password to its own Krb5LoginModule.
It remains to be seen how the SPNEGO support now incubating in JBoss will accomplish the same remote propagation of credentials when JBoss never had primary credentials to transmit.
Who's on First?
The CAS Server is (or can be) configured to use JAAS to validate a userid/password typed into the Login form. At Yale, JAAS has been configured to authenticate against the MIT K5 KDC.
However, other applications regard CAS itself as an authentication mechanism. If these applications (like JBoss) expect to authenticate users through a JAAS call, then it is possible to supply them with a CAS plug-in that uses the JAAS Service Provider Interface (SPI) to validate credentials (the ticket id) against a configured back end system (the CAS Server).
The first step toward sanity is not to confuse these two distinct uses of JAAS by the CAS Server (against Kerberos) and by the CAS client (against the CAS Server itself).