Integrated Windows Authentication (SPNEGO) for Web Applications on JBoss EAP 6.1
Posted: July 7th, 2013 | Author: sabre1041 | Filed under: Technology | Tags: JBoss, PicketLink, SPNEGO | 16 Comments »Configuring the JBoss Server
As with any authentication method in JBoss, security domains are used to facilitate the authentication and authorization process. In earlier versions of EAP, this configuration was made in the login-config.xml file, but since EAP 6 consolidates these configurations into a single file, this is done in either the standalone.xml or domain.xml file depending on which mode of EAP being run. Two security domains are required: one which will represent the identity of the JBoss server to facilitate Kerberos authentication and the other to secure the web application.
JBoss Integrated Authentication Security Domain
To authenticate the JBoss container against the KDC, the Krb5LoginModule is used. The service principal and keytab generated previously are passed in as login module options in addition to several others. EAP 6 allows for the usage of codes in login modules in lieu of specifying the entire class name. With that being said, the code Kerberos can be used. Configure the login module as follows:
<security-domain name="host" cache-type="default"> <authentication> <login-module code="Kerberos" flag="required"> <module-option name="storeKey" value="true"/> <module-option name="useKeyTab" value="true"/> <module-option name="principal" value="HTTP/eapdev.jboss.org@JBOSS.ORG"/> <module-option name="keyTab" value="<location_of_key>"/> <module-option name="doNotPrompt" value="true"/> <module-option name="debug" value="false"/> </login-module> </authentication> </security-domain>
The debug module option can be used to aid in configuring and testing the authentication process. It is recommended this value be set to true until authentication is configured successfully. In addition, the login module also requires the presence of the following two Java system properties to be defined which will assist in the authentication process.
- java.security.krb5.kdc – The host name of the KDC
- java.security.krb5.realm – The name of the realm
These properties can be defined during the initialization of the JBoss server or specified in the standalone/domain.xml as follows:
<system-properties> <property name="java.security.krb5.kdc" value="dc1.jboss.org"/> <property name="java.security.krb5.realm" value="JBOSS.ORG"/> </system-properties>
Web Application Security Domain
To secure the web application itself, multiple login modules will need to be utilized. The first login module will authenticate the user while the second will search for roles to apply to the user. Let’s break down the security domain configuration by login module. The following is a stub security domain named “SPNEGO” that will be used to authenticate the web application.
<security-domain name="SPNEGO" cache-type="default"> <authentication> <!-- Login Module 1 - Authenticate User --> <!-- Login Module 2 - Search for roles --> </authentication> </security-domain>
The SPNEGO login module will do the brunt of the work by authenticating the user to Active Directory. This will set the username of the authenticated principal. It can be configured as follows:
<login-module code="SPNEGO" flag="requisite"> <module-option name="password-stacking" value="useFirstPass"/> <module-option name="serverSecurityDomain" value="host"/> </login-module>
The password-stacking module option is often used when stacking multiple login modules and an authenticated principal may already exist. If it does, it will be used instead of proceeding with authentication. The serverSecurityDomain option is configured with the name of the security domain configured previously which will perform the Kerberos authentication. By default, the name of the principal returned by this login module will be in the form username@REALM. For the sake of this discussion, the name of the principal would return in the form user@JBOSS.ORG. If the name of the realm is not desired, it can be removed by specifying the following login module option:
<module-option name="removeRealmFromPrincipal" value="true"/>
With the user now authenticated, their associated roles can be mapped. There are a variety of ways roles can be mapped, including roles defined on the authentication server or in a relational database. The most simplistic example is to use a properties file to define the roles. The UsersRolesLoginModule (EAP code UsersRoles) can map values from the properties file to the authenticated user. To accomplish this, create two files in either the <JBOSS_HOME>/standalone/configuration or <JBOSS_HOME>/domain/configuration depending on the mode JBoss is running in named “spnego-users.properties” and “spnego-roles.properties”. The spnego-users file will remain empty, but it’s existence is required by the login module. Defining roles in the roles file is accomplished specifying the username and then a series of comma separated roles in the form:
username=role1,role2….
Keep in mind, if the removeRealmFromPrincipal property was not defined on the previous login module, you must ensure you include the realm.
For example, if user jdoe had roles admin and user, and the removeRealmFromPrincipal option was not specified, it would appear in the following form in the properties file
jdoe@JBOSS.ORG=admin,user
The UserRoles login module is configured as follows:
<login-module code="UsersRoles" flag="required"> <module-option name="password-stacking" value="useFirstPass" /> <module-option name="usersProperties" value="spnego-users.properties" /> <module-option name="rolesProperties" value="spnego-roles.properties" /> </login-module>
With both login modules configured, the resulting SPNEGO security domain can be added to the standalone.xml/domain.xml file.
<security-domain name="SPNEGO" cache-type="default"> <authentication> <login-module code="SPNEGO" flag="requisite"> <module-option name="password-stacking" value="useFirstPass"/> <module-option name="serverSecurityDomain" value="host"/> </login-module> <login-module code="UserRoles" flag="required"> <module-option name="password-stacking" value="useFirstPass" /> <module-option name="usersProperties" value="spnego-users.properties" /> <module-option name="rolesProperties" value="spnego-roles.properties" /> </login-module> </authentication> </security-domain>
At this point, a user can be authenticated within the JBoss container with their associated roles mapped.
Good stuff man. I will have to give it a shot. Could be very useful for me 🙂
Thanks a lot for that great tutorial. It’s the best and most comprehensive I’ve ever seen.
Nevertheless I’ve been fallen (in my environment) into some traps and I want to share some hints:
– the service user AND the calling user have to be flagged “AES256 for Kerberos enabled”; otherwise I’ve got a GSSException: “Checksum failed”; (maybe they only have to have the same encryptions enabled/disabled)
– the SPN assigned to the service user is not allowed to be assigned to ANY other user
– there may be a global Kerberos configuration (C:\Windows\krb5.ini) on the machine running the JBoss; check that for correct values
– “Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy” has to be installed on the server for AES256 support
Some corrections:
– the code of the login module is “UsersRoles” and not “UserRoles” (page 3)
– the code of the login module is “SPNEGOUsers” and not “SPNEGO” (page 3)
Maybe an interesting scenario to use SPNEGO for users logged into the domain, authenticate users not logged into the domain (e.g. working with a local account) using username/password against AD but load roles from AD in both cases:
…
Thank you!
Alex,
Thanks for the sharing some of your experiences with SPNEGO in your environment. I’m sure others implementing in a more secure environment will find the information very useful.
In addition, good catch pointing out the error with the UsersRoles login module. I have gone in and made the appropriate corrections to the post.
The SPNEGO login module can be represented as either SPNEGOUsers or just plain old SPNEGO. The EAP 6.1 Security Guide has examples of both implementations.
Certainly an interesting scenario you poised. You may be able to accomplish this by chaining login modules and tweaking their configuration types. Very interested to hear if you are able to accomplish this.
– Andy
Big thanks! Managed to get it to work without major hiccups.
Is it possible to make this work without using roles? That is, any user that is authenticated in Active Directory would be able to log in without requiring extra configuration in the roles.properties.
Chris, you can use the AdvancedLdapLoginModule. See the following link for more information on how to configure it with SPNEGO:
https://access.redhat.com/site/documentation/en-US/JBoss_Enterprise_Application_Platform/5/html/Negotiation_User_Guide/ch02s04s02.html
Example Configuration:
https://access.redhat.com/site/documentation/en-US/JBoss_Enterprise_Application_Platform/5/html/Negotiation_User_Guide/apas02.html#AdvLDAP_on_AD
I currently have CAS configured with JBOSS 5 and need to move over to JBOSS 7. I already have keytab files and SPNs generated.
I have 2 configurations. 1. Username and password is the same (default) 2. SPENGO authentication to Active Directory. The new CAS zip file needs to be build with Ant or Maven. I did not see mention of that in your post. is there something I am missing?
Many, many thanks for this. I managed to get IWA working with our app without to many problems thanks to your very clear blog.
I wondered if you knew of any way that an application could be configured to use SPNEGO/IWA if available and to fall back to a form based authentication if not?
John,
You can add a form-login-config section to the login-config section of your web.xml. If SPNEGO authentication fails, it will fallback to the form based authentication
I configured the jboss-eap-6.1 as mentioned in this tutorial when I test the negotiation toolkit security domain shows following error unable to obtain the password from user and secured showing 401 , can any one help
[…] The first thing that I need to do is identify who the user is. After reading Block 87’s article, I should start looking at SPNEGO and setting up each of the environments. From that point, I […]
Hi Andy,
Thanks a lot for very great tutorial on integrated windows authentication for web applications and it is very well described step by step in good detail.
Hi,
I am configuring kerberos for JBOSS EAP 6.4. I followed all the steps mentioned in link https://access.redhat.com/webassets/avalon/d/Red_Hat_JBoss_Enterprise_Application_Platform-6.4-How_to_Setup_SSO_with_Kerberos-en-US/Red_Hat_JBoss_Enterprise_Application_Platform-6.4-How_to_Setup_SSO_with_Kerberos-en-US.pdf but getting
15:24:43,139 INFO [stdout] (http-/127.0.0.1:8080-1) [Krb5LoginModule
] authentication failed
15:24:43,140 INFO [stdout] (http-/127.0.0.1:8080-1) Client not found in Kerbero
s database (6)
Hi everyone:I’ve aadelry completed each step of these processes. AD Users are able to authenticate through SQUID to surf by internet, BUT!! after 2 hours -sometimes more or less- suddenly some users -one or two- couln’t surf by Internet Internet Explorer requests for new credentials (user/password).. Then AD users type them, but They aren’t able to surf by internet I checked that an AD user type user/password correctly but the prompt appears every time From cache.log these lines are recorded:: -2011/02/10 17:58:15| squid_kerb_auth: Got YR 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’ from squid (length: 2107).2011/02/10 17:58:15| squid_kerb_auth: gss_accept_sec_context() failed: Unspecified GSS failure. Minor code may provide more information. Key table entry not found -I’ve been using:+RHEL 5.0+SQUID 3.0+modules: (squid_kerb_auth1.0.7 and squid_kerb_ldap1.2.1a) from squid.confI’ve configured the option debug_options ALL,1 33,2 28,9 in order to get more records.. but all these records aren’t useful.Can somebody help?Thanks in advance.
Great post and detailed explanation. However, I still have no clue how to implement this in the servlet. I am working on a Struts 1.3 app. And I need to add the SSO with the existing login system – backed in RDBMS. Is there any sample codes or a clue to implementing the SSO auth within an existing webapp?
Thanks, nice post
Let’s discuss the not so uncommon case where there are not one but several Web Application servers. For example these may be duplicates of the same application (prod, uat, dev, etc) or they may simply be running different application.
In this case would you recommend to create one AD account per app server or would it suffice to have only one AD account in ttal ? Of course the SPN and the keytab file needs to be per-server, I understand that much, but I’m not sure why you would need one AD account per server ??