SPNEGO
New CAS documentation site
CAS documentation has moved over to apereo.github.io/cas, starting with CAS version 4.x. The wiki will no longer be maintained. For the most recent version of the documentation, please refer to the aforementioned link.
CAS Server's Java Version
SPNEGO support is tightly couple to the version of the JVM used by CAS. Full compatibility for SPNEGO requires JDK 1.6u19 and greater. For information about the particulars of using an older version of Java, view Version 21 of this page.Â
SPNEGO Basics
Before getting started it will help to understand the steps involved in SPNEGO authentication. There are three actors involved, the client, the CAS server, and the ActiveDirectory DomainController/KDC.Â
Assumptions:
- Client is logged in to a windows domain
- Client is Windows XP pro SP2 or greater running IE 6 or IE 7
- CAS is running on a UNIX server configured for kerberos against the AD server in the windows domain.
Spnego Steps:
- Client sends CAS:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â HTTP GET to CASÂ for cas protected page
- CAS responds:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â HTTP 401 - Access Denied WWW-Authenticate: Negotiate
- Client sends ticket request: Kerberos(KRB_TGS_REQ) Requesting ticket for HTTP/<Fully qualified domain name of CAS>@KERBEROS REALM
- Kerberos KDC responds:Â Â Â Â Â Kerberos(KRB_TGS_REP) Granting ticket for HTTP/<Fully qualified domain name of CAS>@KERBEROS REALM
- Client sends CAS:Â Â Â Â Â Â Â Â Â Â Â Â Â Â HTTP GET Authorization: Negotiate w/SPNEGO Token
- CAS responds:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â HTTP 200 - OK WWW-Authenticate w/SPNEGO response + requested page.
This only happens for the first request, when there is no CAS ticket associated with the users session. Once CAS grants a ticket, this will not happen again until the CAS ticket expires
Including the Handler
In the pom.xml file for your CAS Maven2 WAR Overlay, add the following dependency:
<dependency> <groupId>org.jasig.cas</groupId> <artifactId>cas-server-support-spnego</artifactId> <version>${cas.version}</version> </dependency>
Core Classes
JCIFSSpnegoAuthenticationHandler
This is the implementation of an AuthenticationHandler for SPNEGO supports. This Handler support both NTLM and Kerberos. NTLM is disabled by default. This class supports the following properties:
- principalWithDomainName - boolean to enable or disable domain name in the returned netid
- NTLMallowed - allows to authenticate using SPNEGO/NTLM token
JCIFSConfig
This class is the configuration helper for JCIFS and the Spring framework. This class supports the following properties:
- jcifsServicePrincipal - set the Service Principal Name
- jcifsServicePassword - set the password for the principal name
- kerberosDebug - boolean to enable or disable the debug mode on Kerberos
- kerberosRealm - set the Realm
- kerberosKdc - set the KDC address
- loginConf - path to the login.conf
SpnegoNegociateCredentialsAction
First action of a SPNEGO flow : negociation. The server checks if the negociation string is in the request header:
- If found do nothing and return success()
- else add a WWW-Authenticate response header and a 401 response status, then return success()
SpnegoCredentialsAction
Second action of a SPNEGO flow : decode the gssapi-data and build a new SpnegoCredentials.
Once AbstractNonInteractiveCredentialsAction has executed the authentication procedure, this action check whether a principal is present in Credentials and add correspondings response headers.
Configuration
Set up the Active Directory
A service account should be created. This account is called a Service Principal Name account (SPN account).
Create the User
- Start the Active Directory User and Computers from the Administration Tools menu.
- Right click on the Users Repository and select New > User
- Enter user information (by example myspnaccount for user login), press Next.
- Enter the password and select Password never expires and click on Next and then on Finish.
Now that the user account has been created and updated, we need to create a service principal setting for the created user account. This is automatically handled by exporting a keytab file for the created account.
Create the Keytab File
The Keytab file enables a trust link between the CAS server and the Key Distribution Center (KDC). This file contains a cryptographic key. The ktpass tool, which comes from the Windows Resource Kit, is used to generate this file. Be sure that you are running the command on your server where your Active Directory is installed and you are logged in as an administrator.
In a console, enter the command:
ktpass.exe /out myspnaccount.keytab /princ HTTP/your.server.name.here@YOUR.REALM.HERE /pass * /mapuser myspnaccount@YOUR.REALM.HERE /ptype KRB5_NT_PRINCIPAL /crypto RC4-HMAC-NT
This command will generate the myspnaccount.keytab file which has to be copied on the CAS server in order to test Kerberos from a bash using the MIT Kerberos V. Additionally when the properties of the spn account are viewed in Active Directory Users and Computers, a new delegation tab is displayed.
The syntax can be confusing. Here's an example assuming the samAccountName of the service account is "cassp", the fully qualified domain name of the CAS server is "cas.gasper.local", and a domain name of "gasper.local":
ktpass.exe /out cassp.keytab /princ HTTP/cas.gasper.local@GASPER.LOCAL /pass * /mapuser cassp@GASPER.LOCAL /ptype KRB5_NT_PRINCIPAL /crypto RC4-HMAC-NT
Test the SPN account
First configure MIT Kerberos V on the server. The file is <literal>/etc/krb5.conf</literal>. Here is an example:
[logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] ticket_lifetime = 24000 default_realm = YOUR.REALM.HERE default_keytab_name = /home/cas/kerberos/myspnaccount.keytab dns_lookup_realm = false dns_lookup_kdc = false default_tkt_enctypes = rc4-hmac default_tgs_enctypes = rc4-hmac [realms] YOUR.REALM.HERE = { kdc = your.kdc.your.realm.here:88 } [domain_realm] .your.realm.here = YOUR.REALM.HERE your.realm.here = YOUR.REALM.HERE
Then verify that your are able to read the keytab file:
klist -k
Then verify that your are able to read the keytab file :
kinit a_user_in_the_realm@YOUR.REALM.HERE klist
Another test is to try the command:
kinit -V HTTP/your.server.name.here@YOUR.REALM.HERE -k -t /home/cas/kerberos/myspnaccount.keytab
You should not be prompted for a password. Here's the command using the example domain:
kinit -V HTTP/cas.gasper.local@GASPER.LOCAL -k -t /home/user/kerberos/cas.keytab
Set up Browser
Internet Explorer (min 5.01)
- In Internet Explorer, click Internet Options on the Tools menu.
- Click on the Advanced tab, click to select the Enable Integrated Windows Authentication (requires restart) check box in the Security section, and then click OK.
- Click on the Security tab, click to select Local Intranet then click on Sites, then click on Advanced.
- Enter https://your.server.name.here_ and validate by clicking on _Add and OK.
- Restart Internet Explorer.
Firefox (min 0.9)
- In Firefox, enter about:config as url and click on Go.
- On the line network.negotiate-auth.trusted-uris, right click on Modify and enter _https://your.server.name.here_
Kerberos authentication does not work from a browser hosted on the CAS SSO server. See this CAS Users thread.
Set Up CAS
Set up the login webflow
The CAS 3 Login Webflow needs to be modified. This webflow is located in /WEB-INF/login-webflow.xml. There are 2 new action states which are placed before the state viewLoginForm.
<action-state id="startAuthenticate"> <evaluate expression="negociateSpnego" /> <transition on="success" to="spnego" /> </action-state> <action-state id="spnego"> <evaluate expression="spnego" /> <transition on="success" to="sendTicketGrantingTicket" /> <transition on="error" to="viewLoginForm" /> </action-state>
And 2 existing transitions need to be update:
- In the decision-state gatewayRequestCheck, replace reference to viewLoginForm by startAuthenticate
- In the decision-state renewRequestCheck, replace reference to viewLoginForm by startAuthenticate
diff against version 3.5.2:
/WEB-INF/cas-servlet.xml
Two beans are needed for the login flow. Those beans are:
<bean id="negociateSpnego" class="org.jasig.cas.support.spnego.web.flow.SpnegoNegociateCredentialsAction" /> <bean id="spnego" class="org.jasig.cas.support.spnego.web.flow.SpnegoCredentialsAction"> <property name="centralAuthenticationService" ref="centralAuthenticationService"/> </bean>
diff against cas version 3.5.2:
/WEB-INF/deployerConfigContext.xml
In the bean authenticationManager, add:
*_ org.jasig.cas.adaptors.spnego.authentication.principal.SpnegoCredentialsToPrincipalResolver_ as credentialsToPrincipalResolvers
*_ org.jasig.cas.adaptors.spnego.authentication.handler.support.JCIFSSpnegoAuthenticationHandler_ as authenticationHandlers
<bean id="authenticationManager" class="org.jasig.cas.authentication.AuthenticationManagerImpl"> <property name="credentialsToPrincipalResolvers"> <list> <!-- ... the others credentialsToPrincipalResolvers ... --> <bean class="org.jasig.cas.support.spnego.authentication.principal.SpnegoCredentialsToPrincipalResolver" /> </list> </property> <property name="authenticationHandlers"> <list> <bean class="org.jasig.cas.support.spnego.authentication.handler.support.JCIFSSpnegoAuthenticationHandler"> <property name="authentication"> <bean class="jcifs.spnego.Authentication" /> </property> <property name="principalWithDomainName" value="false" /> <property name="NTLMallowed" value="true"/> </bean> <!-- ... the others authenticationHandlers... --> </list> </property> </bean>
There is also the jcifsConfig bean which needs to be added.
<bean name="jcifsConfig" class="org.jasig.cas.support.spnego.authentication.handler.support.JCIFSConfig"> <property name="jcifsServicePrincipal" value="HTTP/your.server.name.here@YOUR.REALM.HERE" /> <property name="kerberosDebug" value="false" /> <property name="kerberosRealm" value="YOUR.REALM.HERE" /> <property name="kerberosKdc" value="THE.KDC.IP.HERE" /> <property name="loginConf" value="/path/to/WEB-INF/login.conf" /> </bean>
diff against cas version 3.5.2:
/WEB-INF/login.conf
Copy or create the file /path/to/WEB-INF/login.conf
jcifs.spnego.initiate { com.sun.security.auth.module.Krb5LoginModule required storeKey=true useKeyTab=true keyTab="/home/cas/kerberos/myspnaccount.keytab"; }; jcifs.spnego.accept { com.sun.security.auth.module.Krb5LoginModule required storeKey=true useKeyTab=true keyTab="/home/cas/kerberos/myspnaccount.keytab"; };
Changes for JBoss
JBoss has its own security manager so specifying the login.conf file above has no effect. This was solved by amending a section in the login-config.xml file in the /SERVER-ROOT/server/default/conf directory as follows:
<application-policy name="other"> <authentication> <login-module code="com.sun.security.auth.module.Krb5LoginModule" flag="required"> <module-option name="storeKey">true</module-option> </login-module> </authentication> </application-policy>
This means that JBoss defaults to using the Kerberos login module when no others are specified. This can be extracted to a custom application policy and specified in a jboss-web.xml file so that it can be explicitly selected.
Â
ClassNotFound jcifs/spnego/AuthenticationException
You need the jcifs and jcifs-ext jars in order to make spnego working. They can be downloaded from http://developer.jasig.org/repo/content/groups/m2-legacy/org/samba/jcifs/
If there any dependency problems, you can run 'mvn compile' in the cas source. After that, your maven repo (~/.m2 by defualt) will contain all the dependency jars, go cherrypick!
Â