==== NEGOTIATE authentication ==== This type of authentication is used in for example MS Windows Domains and can utilize [[wp>SPNEGO]], [[wp>NTLM]] or [[wp>Kerberos_protocol|Kerberos]] authentication. The flow is the following (the same steps as are given [[wp>Kerberos_protocol#Description|here]] or [[http://technet.microsoft.com/en-us/library/bb742431.aspx|here]] but in terms of browser / Web server interaction; also local developers please check [[conflepo>RNA/SPNEGO-Overview#SPNEGO-Overview-HowSPNEGOworksinaWebenvironment|here]]): * The user authenticates itself once he logins into the system. The system sends the credentials to authentication server and receives back the client session ticket (also called [[wp>Ticket Granting Ticket|TGT]]), which is stored safely on the client and authenticates the client (e.g. the user). * Browser access a secured resource in some Web application. The Web server responds with a 401 response containing special header ''WWW-Authenticate: NEGOTIATE''. * The NEGOTIATE-aware browser realizes it needs to acquire a service ticket for the given URL (service). It first tries the Kerberos authentication: it sends a request to the KDC and acquires the service ticket that will be used to authenticate the client to the service. If the browser fails on some reason (service is not registered in KDC (see below note) or user is rejected to access the service), the browser falls-back to NTLM authentication: it displays the login box (that looks like one you would see with BASIC authentication) and the entered credentials are transferred in an encrypted NTLM block. * The browser tries to access the same resource URL as before but this time it adds ''WWW-authorization: NEGOTIATE //encoded-spnego-token//'' header to the HTTP request. Here ''//encoded-spnego-token//'' is the SPNEGO token encoded in base64 which is basically a wrapper for the service ticket or NTLM block. * The authenticator on Web server unwraps the SPNEGO token and gets the service ticket. Using the secret key (shared only by Web server and KDC) it decodes the service ticket and makes sure the timestamp is close enough to the current time. Those two steps are the validation that this is the user that sent the ticket. If all passes, the user is valid to request a service. * The authenticator returns true, and passes control to the servlet container which sends back the requested resource. Otherwise, a 403 response is sent back to the browser. GSS API is an standard API / Protocol for authentication and authorization. JGSSAPI is the Java implementation of this API. [[javase>docs/guide/security/jaas/tutorials/|JAAS]] is an authentication and authorization model, created by Sun. JBoss implemented their security model using JAAS model. This enables any person to plug their own authentication and authorization modules into JBoss security module. JGSS Sun's implementation is using JAAS model for accessing ADS. See [[javase>docs/guide/security/jgss/tutorials/JGSSvsJSSE.html|When to use Java GSS-API vs. JSSE]] for more information. A service secret key is created when registering the service principal in ADS (which looks like ''HTTP/host.fqdn.com@KERBEROS-REALM''). This is done using the utility ''[[http://support.microsoft.com/kb/324144|ktpass.exe]]''. One of its arguments is the keytab file location to save the secret key to. This keytab contains the list of pairs "service principal name -> secret key" (which is derived from the Kerberos password). You should place this in a secure / non-public-access location. In JBoss you define the location of the the keytab via '''' in ''conf/login-config.xml'' (is implementation-specific). The authenticator searches the keytab for a pre-configured service principal and retrieves the service secret key. In Tomcat, since you don't have ''login-config.xml'', you need to define this in a separate configuration file. You can different approaches to implement SSO on Tomcat/JBoss [[apache>tomcat/FAQ/Windows#Q4|here]] and [[http://swordsystems.com/category/spnego/|here]] but: * [[http://waffle.codeplex.com/|WAFFLE]] is Win32-only solution :NO: * [[http://tomcatspnego.codeplex.com/|TomcatSPNEGO]] needs intermediate Negoserver for authentication :NO: * [[http://appliedcrypto.com/whatisspnego.do|AppliedCrypto SPNEGO SSO]] is a commercial product :NO: * [[http://static.devel.it.su.se/gssapi-valve/|GSSAPI Valve]] lacks flexibility of configuration (no fine configuration is possible) :NO: * [[sourceforge>spnego|SPNEGO library]] does not provide Tomcat ''[[tomcat>api/org/apache/catalina/Authenticator.html|Authenticator]]'' implementation (see [[https://sourceforge.net/tracker/?func=detail&aid=3040679&group_id=276784&atid=1175546|bug#3040679]]) :NO: * [[http://static.springsource.org/spring-security/site/extensions/krb/index.html|Spring Security Kerberos Extension]] :YES: * [[https://spring.io/blog/2009/09/28/spring-security-kerberos-spnego-extension|Spring Security Kerberos/SPNEGO Extension]] * [[https://docs.spring.io/spring-security-kerberos/docs/1.0.1.RELEASE/reference/htmlsingle/#crash-course-to-kerberos|Spring Security Kerberos - Crash Course to Kerberos]] * [[http://wiki.exoplatform.org/xwiki/bin/view/WS/Kerberos%20SSO%20on%20Active%20Directory|eXo SSO]] :YES: === References === {{topic>SPNEGO}} === Further reading === * [[http://appliedcrypto.com/spnegoarticles.do|Articles about Security, SPNEGO and SSO]] * [[http://s2.diffuse.it/blog/show/6602-SPNEGO_authentication_and_credential_delegation_with_Java|SPNEGO authentication and credential delegation with Java]] * [[http://msdn.microsoft.com/en-us/library/ms995329.aspx|HTTP-Based Cross-Platform Authentication by Using the Negotiate Protocol]] ({{:software:http_based_cross_platform_authentication_by_using_negotiate_protocol.pdf|local copy}}) * [[http://www.grolmsnet.de/kerbtut/|Using ''mod_auth_kerb'' and Windows 2000/2003/2008R2 as KDC]] * [[stackoverflow>8164817|Spring-security, Tomcat and SPNEGO]] * [[http://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html#spnego|SPNEGO/Kerberos Authentication in Apache HttpClient]]. * [[http://cxf.apache.org/docs/client-http-transport-including-ssl-support.html#ClientHTTPTransport%28includingSSLsupport%29-SpnegoAuthentication%28Kerberos%29|Spnego Authentication (Kerberos) in Apache CXF client]] * [[https://blogs.oracle.com/wangwj/entry/kerberos_programming_on_windows|Kerberos Programming on Windows]] ({{:software:kerberos_programming_on_windows.pdf|local copy}}, [[http://cr.openjdk.java.net/~weijun/special/krb5winguide-2/raw_files/new/kwin|text version]]) * [[https://community.jboss.org/wiki/NegotiateKerberos|Negotiate Authentication on Tomcat in JBoss AS]] * [[http://docs.oracle.com/javase/6/docs/technotes/guides/security/jgss/tutorials/ClientServer.html|Use of JAAS Login Utility and GSS-API for Secure Message Exchanges]] * [[stackoverflow>1125517|wget support for NTLM authentication]] is broken (?) * [[SourceForge>cntlm|Cntlm Authentication Proxy]] for 3rd party Windows applications, which don't support NTLM natively ===== Questions answered ===== === How to verify that the service ticket has OK-AS-DELEGATE flag enabled in [[wp>Active Directory|ADS]]? === * :OPT: Refresh your personal [[wp>Ticket Granting Ticket|TGT]]: $ kinit Password for user123@REALM.COMPANY.ORG: ***** * Populate the credentials' cache with the service ticket (the requested endpoint should be secured): $ curl --negotiate -u : http://service-id.company.org/status No resource method found for GET, return 405 with Allow header * The **''O''** flag reported for ''HTTP/service-id.company.org'' means that ok-as-delegate is enabled: $ klist -f Ticket cache: FILE:/tmp/krb5cc Default principal: user123@REALM.COMPANY.ORG Valid starting Expires Service principal 02/07/17 16:02:30 02/08/17 05:02:23 HTTP/service-id.company.org@REALM.COMPANY.ORG renew until 02/08/17 16:02:22, Flags: FRAO For description of flags check [[https://web.mit.edu/kerberos/krb5-devel/doc/user/tkt_mgmt.html#kerberos-ticket-properties|Kerberos ticket properties]]. === How to create keytab for the given user? === From [[http://www.itadmintools.com/2011/07/creating-kerberos-keytab-files.html|Creating kerberos keytab files compatible with Active Directory]]: On Linux: user123@host:~> ktutil ktutil: addent -password -p USER123@REALM.COMPANY.ORG -k 1 -e RC4-HMAC Password for USER123@REALM.COMPANY.ORG: ***** ktutil: wkt USER123.keytab ktutil: q On Windows: C:\> ktab -a USER123@REALM.COMPANY.ORG -k USER123.keytab Password for USER123@REALM.COMPANY.ORG:***** Done! Service key for USER123@REALM.COMPANY.ORG is saved in USER123.keytab or C:\> ktab -a USER123@REALM.COMPANY.ORG -k USER123.keytab Now this keytab can be used in ''[[http://grepcode.com/file/repo1.maven.org/maven2/org.springframework.security.kerberos/spring-security-kerberos-client/1.0.1.RELEASE/org/springframework/security/kerberos/client/KerberosRestTemplate.java#180|KerberosRestTemplate]]'' or in ''login.config'' (to be passed to Java via ''-Djava.security.auth.login.config=login.config''): // Login entry for a Kerberos client (initiator of a secure Kerberos connection): com.sun.security.jgss.krb5.initiate { com.sun.security.auth.module.Krb5LoginModule required storeKey=true useKeyTab=true doNotPrompt=true principal="USER123@REALM.COMPANY.ORG" keyTab="USER123.keytab" ; }; If you get ''[[stackoverflowa>40763237/267197|javax.security.auth.login.LoginException: No key to store]]'' exception when using the keytab, then remove your ticket cache (''rm /tmp/krb5cc_nnnn''). Username can be written in lower case (''user123'') provided that it matches ''principal'' in ''login.config''. ==== Troubleshooting NEGOTIATE authentication ==== * Define ''-Dsun.security.krb5.debug=true'' * Define ''-Dsun.security.spnego.debug=true'' * Add ''debug=true'' to module configuration in ''login.config''. Check also: * [[http://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/tutorials/Troubleshooting.html|Troubleshooting JGSS]] * [[http://weblogic-wonders.com/weblogic/2010/01/07/troubleshooting-kerberos-issues-with-weblogic-server/|Troubleshooting Kerberos Issues with Weblogic Server]] * [[http://gsa-kerberos-test-client.googlecode.com/svn-history/r27/trunk/gsa-kerberos-test-client/README.txt|Google Search Appliance Kerberos Client – Common errors]] * [[https://steveloughran.gitbooks.io/kerberos_and_hadoop/content/sections/errors.html|Common Kerberos Error Messages]] === ''GSSException: Defective token detected'' === GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag) at sun.security.jgss.GSSHeader.(GSSHeader.java:80) at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:287) at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:267) at org.eclipse.jetty.security.SpnegoLoginService.login(SpnegoLoginService.java:132) at org.eclipse.jetty.security.authentication.SpnegoAuthenticator.validateRequest(SpnegoAuthenticator.java:80) From [[http://forum.springsource.org/showthread.php?109918-spring-secutiry-cant-read-any-principal-from-any-keytab#post367237|here]]: Make sure you are using the browser from different machine as the server. === ''KrbException: Cannot find key of appropriate type to decrypt AP REP - RC4 with HMAC'' === KrbException: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - RC4 with HMAC at sun.security.krb5.KrbApReq.authenticate(KrbApReq.java:263) at sun.security.krb5.KrbApReq.(KrbApReq.java:134) at sun.security.jgss.krb5.InitSecContextToken.(InitSecContextToken.java:79) at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:724) at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:323) at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:267) at sun.security.jgss.spnego.SpNegoContext.GSS_acceptSecContext(SpNegoContext.java:874) at sun.security.jgss.spnego.SpNegoContext.acceptSecContext(SpNegoContext.java:541) at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:323) at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:267) at org.eclipse.jetty.security.SpnegoLoginService.login(SpnegoLoginService.java:132) AD uses ''rc4-hmac'' in [[http://www.gnu.org/software/gsasl/draft-josefsson-sasl-kerberos5.html#anchor5|Authentication Protocol (AP) reply]]. In order to use ''des-cbc-md5'' one must activate the //Use Kerberos DES encryption types for this account// setting for server user account otherwise you get stuck in ''rc4-hmac'' mode (which apparently is default in Win2K8 R2 and later). References: * [[https://communities.bmc.com/communities/thread/59505#212660|Setting up Kerberos on a BBSA server]] * [[http://grails.1312388.n4.nabble.com/Grails-Spring-Security-Kerberos-Windows-2008-R2-td4269756.html#a4270080|Grails + Spring Security + Kerberos + Windows 2008 R2 ]] * [[http://www.coderanch.com/t/502443/JBoss/SSO-SPNEGO-JBOSS#2296456|SSO using SPNEGO in JBOSS 4.2.2]]): To be sure also check that ''des-cbc-md5'' ([[http://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xml#kerberos-parameters-1|Kerberos encryption type 3]]) is the one listed in your keytab file: $ klist -e -k service.keytab [1] Service principal: HTTP/service-id.company.org@REALM.COMPANY.ORG KVNO: 3 Key type: 3 Otherwise you need to regenerate the keytab file (see [[http://fixunix.com/kerberos/60926-cannot-find-key-appropriate-type-decrypt-ap-rep.html#post198960|Cannot find key of appropriate type to decrypt AP REP]], [[https://forums.oracle.com/forums/thread.jspa?threadID=1525533#6384535|"Cannot find key of appropriate type to decrypt" error again on W2k8]]). === What is the application of ''javax.security.auth.useSubjectCredsOnly''? === From [[http://docs.oracle.com/javase/6/docs/technotes/guides/security/jgss/tutorials/BasicClientServer.html#useSub|Use of Java GSS-API for Secure Message Exchanges Without JAAS Programming]]:
Setting the system property ''javax.security.auth.useSubjectCredsOnly'' to false allows us to relax the usual restriction of requiring a GSS mechanism to obtain necessary credentials from an existing //Subject//, set up by JAAS. When this restriction is relaxed, it allows the mechanism to obtain credentials from some vendor-specific location. For example, some vendors might choose to use the operating system's cache if one exists, while others might choose to read from a protected file on disk. When this restriction is relaxed, Sun Microsystem's Kerberos mechanism still looks for the credentials in the Subject associated with the thread's access control context, but if it doesn't find any there, it performs JAAS authentication using a Kerberos module to obtain new ones. The Kerberos module prompts you for a Kerberos principal name and password. Note that Kerberos mechanism implementations from other vendors may behave differently when this property is set to false. Consult their documentation to determine their implementation's behavior.