Single-Sign-On (SSO) in Java Platform using Active Directory
August 29, 2009 76 Comments
Sorry guys it been long time writing in my blog.
Nowadays single-sign-on became a hot selling feature for all desktop and web-based products. In this article I talk about single-sign-on implementation in Java platform with Active Directory server. Since Microsoft Windows has become one of the most common corporate network platforms it is worth integrating with your product. Starting from Windows 2000 Microsoft supports Kerberos protocol. It is unusal that Microsoft support open-standard protocol, but they do in this case; good for us :-)
Keyword/ Jargons
Before jumping into implementation and configurations it is good to know some common keywords /jargons used on single-sign-on technique.
Single-Sign-On http://en.wikipedia.org/wiki/Single_sign-on
Kerberos – http://en.wikipedia.org/wiki/Kerberos_(protocol)
Active Directory – http://en.wikipedia.org/wiki/Active_Directory
SPNEGO – http://en.wikipedia.org/wiki/SPNEGO
JAAS – http://java.sun.com/j2se/1.5.0/docs/guide/security/jaas/tutorials/index.html
How does Kerberos protocol works
The Web Server has to hand-shake with browser to obtain kerberos token. The token can be validated against keytab file (http://kb.iu.edu/data/aumh.html) or connecting through Active Directory.
The below diagram explains how the handshake happens between browser and webserver to obtain kerberos token for authentication.
Environment/ Infrastructure
In this article I am going to talk about implementing Single-Sign-On in Java platform (i.e. JAAS) using Active Directory through Kerberos protocol for web-based products/applications.
I used below softwares:
JDK 1.6 – (previous version doesn’t support SPNEGO Kerberos protocol)
Windows 2003 Server with Active Directory
Windows XP with Internet Explorer 7 for client machine
Tomcat 6.0 Web Server
Required Information
The following information are required from your system administrators.
- Active Directory server ip address or hostname.
- Your complete domain name in the active directory. (Example. JAVA.SUN.COM)
Create a Server Name Alias
You have to create a server alias for WebServer to interact with ActiveDirectory for SSO token validation. Create a user called testsso and set “Password never expires” as checked. Assign a password for testsso user we will be using this password in Java coding later.
Create a Service Name
The account you created in the previous is meant to be used as an Kerberos HTTP service for the We Server. This is done in using the setspn command line tool that manages SPNs (Service Principal Name) in the Active Directory.
[More information on Setspn: http://technet.microsoft.com/en-us/library/cc773257(WS.10).aspx].
You would need to add (-a) an SPN for such an account, associating it with the fully qualified server alias name. For example:
setspn -a HTTP/java.sun.com testsso
You could see it has been successfully created listing (-l) the SPNs available for such account:
setspn -l testsso
Note: this command line utility might not be available in your OS and you should have to download it from Microsoft site.
Initial verification
You can do a basic Kerberos check using kinit tool. From one of the computers in your network that have access to the KDC (Key Distribution Center), in Windows is usually the Domain Controller, check the following using your user account (ex: testsso@JAVA.SUN.COM):
kinit testsso@JAVA.SUN.COM
If everything is ok, the command will ask you for your domain password and terminates without an error message. This command will show you the initial ticket you got from the KDC if you execute it without any argument.
Create jaas.conf file
Create a jaas.conf file and place in c:\jaas.conf location.
SSOTESTING {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=false
storeKey=true
useTicketCache=false
principal=”testsso@JAVA.SUN.COM”;
};
Download jaas.conf from here
Finally the most awaited test JSP file
Download ssotest.jsp and change the following variable values according to your configuration and environments.
ACTIVE_DIRECTORY_SERVER = “<hostname/ipaddress>”;
DEAULT_DOMAIN = “<the default domain>”;
SP_PASSWORD = “<server-principal-password>”;
The best way to implement Single-Sign-On is using servlet; for easy of testing at your environment I made it as JSP. Once you get this sample code working in your environment you can nicely integrate into your framework.
The example files are available in the below link as well:
https://github.com/venkatsalem/workspace/blob/master/ad-auth/src/main/webapp/sso.jsp
Checklist
- Make sure setspn url is uniquely associated to one active directory user.
- Internet Explorer should be able to identify your site as Intranet site. If not change the IE setting to make it as intranet site.
- Kerberos requires the clocks of the involved hosts to be synchronized.
- Always specify domain names in upper case. Example testsso@JAVA.SUN.COM
OC4J / OracleAS
OC4J will not recognize jaas.conf hence you need to update system-jazn-data.xml file for custom provider. Find more information in below link:
http://download.oracle.com/docs/cd/B31017_01/web.1013/b28957/ovsecadm.htm
References
http://web.mit.edu/Kerberos/
http://tools.ietf.org/html/rfc4559
http://msdn2.microsoft.com/en-us/library/ms995329.aspx
Updated on Nov 4, 2010
The below link contains tutorial and samples from Oracle.
http://download.oracle.com/javase/6/docs/technotes/guides/security/jgss/lab/part6.html
where is the link to the ssotest.jsp file?
sorry for the delay. ssotest.jsp is available now.
i followed the steps and it gave me the following error
GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
at jsp_servlet.__ssotest.authenticate(__ssotest.java:119)
at jsp_servlet.__ssotest._jspService(__ssotest.java:268)
it means that you browser sending NTLM token instead of Kerberos token. You have to configure your workstation to generate Kerberos token for your new service while you logon to windows. I don’t know how to do that!.
Some more tips:
a) make sure testsso is part of Administrator group.
b) On the test workstation login through domain user (don’t login as local computer user).
Hope this helps.
Venkat is back to blogging. :)
Hi Venkat,
“Create a user called testsso”
In what machine? The windows server hosting the active directory. The machine hosting Tomcat webserver? The client workstation? …?
Thanks,
Agus
In your active directory.
I received the following exception:
SEVERE: Servlet.service() for servlet jsp threw exception
java.lang.Exception: javax.security.auth.login.LoginException: No LoginModules configured for SSOTESTING
at org.apache.jsp.ssotest_jsp.authenticate(ssotest_jsp.java:66)
at org.apache.jsp.ssotest_jsp._jspService(ssotest_jsp.java:234)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:334)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
at java.lang.Thread.run(Thread.java:595)
Caused by: javax.security.auth.login.LoginException: No LoginModules configured for SSOTESTING
at javax.security.auth.login.LoginContext.init(LoginContext.java:256)
at javax.security.auth.login.LoginContext.(LoginContext.java:403)
at org.apache.jsp.ssotest_jsp.createServiceSubject(ssotest_jsp.java:78)
at org.apache.jsp.ssotest_jsp.authenticate(ssotest_jsp.java:54)
… 21 more
Any ideas?
I tried your solution, i’m running the servlet in a Tomcat 6.0 server on Ubuntu, so i’ve modified the path to the jaas.conf file accordingly. The user trying to authenticate from an AD domain is in fact a computer account created with the ADS. I get a configfile error, “expected [OptionKey], found [null]” exception when this line executes:
LoginContext loginCtx = new LoginContext(LOGIN_MODULE_NAME, new LoginCallbackHandler(password));
Any ideas?…
Thanks in advance
Randy, your error indicates that jaas.conf file is not in correct path or you are using lesser than JRE6 version.
Andy , try accessing the Tomcat server from different workstation. The other reason could be jaas.conf file may contain some invisible special characters.
Thank you for your reply. My Tomcat server NEEDS to run on Linux so the path to jaas.conf is of the form \home\…\jaas.conf. I’ve tried accessing it from different workstations but i still get the same result. The jaas.conf file only contains what you recommended it to, matching my environment… i don’t know of any invisible characters
I solved my last issue, when copying the jaas.conf file, do make sure to replace the ‘ ” ‘s in the path. Now i get the defective tokens exception as well…
defective tokens – you will get this error when browser send NTLM token instead of kerberos token. The checklist section might help you to resolve the issue.
I followed your steps, but i am getting an exception.
Windows 2003 R2 Server
Java 1.6_15
Tomcat 6.20
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 3 1 23 16 17.
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 3 1 23 16 17.
>>> KrbAsReq calling createMessage
>>> KrbAsReq in createMessage
>>> KrbKdcReq send: kdc=mydomain.mycomp.com UDP:88, timeout=30000, number of retries =3, #bytes=172
>>> KDCCommunication: kdc=mydomain.mycomp.com UDP:88, timeout=30000,Attempt =1, #bytes=172
>>> KrbKdcReq send: #bytes read=257
>>> KrbKdcReq send: #bytes read=257
>>> KDCRep: init() encoding tag is 126 req type is 11
>>>KRBError:
sTime is Sat Oct 03 16:50:34 EDT 2009 1254603034000
suSec is 651761
error code is 25
error Message is Additional pre-authentication required
realm is mydomain.mycomp.com
sname is krbtgt/mydomain.mycomp.com
eData provided.
msgType is 30
>>>Pre-Authentication Data:
PA-DATA type = 11
PA-ETYPE-INFO etype = 23
>>>Pre-Authentication Data:
PA-DATA type = 2
PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
PA-DATA type = 15
AcquireTGT: PREAUTH FAILED/REQUIRED, re-send AS-REQ
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 3 1 23 16 17.
Pre-Authentication: Set preferred etype = 23
>>>KrbAsReq salt is mydomain.mycomp.comtestsso
Pre-Authenticaton: find key for etype = 23
AS-REQ: Add PA_ENC_TIMESTAMP now
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
>>> KrbAsReq calling createMessage
>>> KrbAsReq in createMessage
>>> KrbKdcReq send: kdc=mydomain.mycomp.com UDP:88, timeout=30000, number of retries =3, #bytes=238
>>> KDCCommunication: kdc=mydomain.mycomp.com UDP:88, timeout=30000,Attempt =1, #bytes=238
>>> KrbKdcReq send: #bytes read=1283
>>> KrbKdcReq send: #bytes read=1283
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Token: Negotiate TlRMTVNTUAABAAAAB7IIogkACQAvAAAABwAHACgAAAAFAs4OAAAAD0RNMkRFVjJHQUxBWFlMQUI=
javax.security.auth.login.LoginException: Message stream modified (41)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Unknown Source)
at com.sun.security.auth.module.Krb5LoginModule.login(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at javax.security.auth.login.LoginContext.invoke(Unknown Source)
at javax.security.auth.login.LoginContext.access$000(Unknown Source)
at javax.security.auth.login.LoginContext$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(Unknown Source)
at javax.security.auth.login.LoginContext.login(Unknown Source)
at org.apache.jsp.ssotest_jsp.createServiceSubject(ssotest_jsp.java:80)
at org.apache.jsp.ssotest_jsp.authenticate(ssotest_jsp.java:54)
at org.apache.jsp.ssotest_jsp._jspService(ssotest_jsp.java:243)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Unknown Source)
Caused by: KrbException: Message stream modified (41)
at sun.security.krb5.KrbKdcRep.check(Unknown Source)
at sun.security.krb5.KrbAsRep.(Unknown Source)
at sun.security.krb5.KrbAsReq.getReply(Unknown Source)
at sun.security.krb5.Credentials.sendASRequest(Unknown Source)
at sun.security.krb5.Credentials.acquireTGT(Unknown Source)
… 33 more
Any idea why this is happening?
Thanks for the help
-Karthik
Don’t worry about the below error.
error code is 25
error Message is Additional pre-authentication required
The below ling indicates that your browser sends NTLM auth info instead of Kerberos auth info. See the about Checklist section and make everything is ok.
Token: Negotiate TlRMTVNTUAABAAAAB7IIogkACQAvAAAABwAHACgAAAAFAs4OAAAAD0RNMkRFVjJHQUxBWFlMQUI=
Everything the Checklist seems to be Ok, but still i am seeing this exception
Debug is true storeKey true useTicketCache false useKeyTab false doNotPrompt false ticketCache is null isInitiator true KeyTab is null refreshKrb5Config is false principal is spnuser@mydomain.mycomp.com tryFirstPass is false useFirstPass is false storePass is false clearPass is false
[Krb5LoginModule] user entered username: spnuser@mydomain.mycomp.com
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 3 1 23 16 17.
Acquire TGT using AS Exchange
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 3 1 23 16 17.
>>> KrbAsReq calling createMessage
>>> KrbAsReq in createMessage
>>> KrbKdcReq send: kdc=mydomain.mycomp.com UDP:88, timeout=30000, number of retries =3, #bytes=160
>>> KDCCommunication: kdc=mydomain.mycomp.com UDP:88, timeout=30000,Attempt =1, #bytes=160
>>> KrbKdcReq send: #bytes read=230
>>> KrbKdcReq send: #bytes read=230
>>> KDCRep: init() encoding tag is 126 req type is 11
>>>KRBError:
sTime is Mon Oct 05 20:56:27 EDT 2009 1254790587000
suSec is 158155
error code is 25
error Message is Additional pre-authentication required
realm is mydomain.mycomp.com
sname is krbtgt/mydomain.mycomp.com
eData provided.
msgType is 30
>>>Pre-Authentication Data:
PA-DATA type = 19
PA-ETYPE-INFO2 etype = 3
>>>Pre-Authentication Data:
PA-DATA type = 2
PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
PA-DATA type = 16
>>>Pre-Authentication Data:
PA-DATA type = 15
AcquireTGT: PREAUTH FAILED/REQUIRED, re-send AS-REQ
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 3 1 23 16 17.
Pre-Authentication: Set preferred etype = 3
Updated salt from pre-auth = mydomain.mycomp.comspnuser
>>>KrbAsReq salt is mydomain.mycomp.comspnuser
Pre-Authenticaton: find key for etype = 3
AS-REQ: Add PA_ENC_TIMESTAMP now
>>> EType: sun.security.krb5.internal.crypto.DesCbcMd5EType
>>> KrbAsReq calling createMessage
>>> KrbAsReq in createMessage
>>> KrbKdcReq send: kdc=mydomain.mycomp.com UDP:88, timeout=30000, number of retries =3, #bytes=229
>>> KDCCommunication: kdc=mydomain.mycomp.com UDP:88, timeout=30000,Attempt =1, #bytes=229
>>> KrbKdcReq send: #bytes read=1402
>>> KrbKdcReq send: #bytes read=1402
>>> EType: sun.security.krb5.internal.crypto.DesCbcMd5EType
[Krb5LoginModule] authentication failed
Message stream modified (41)
Token: Negotiate YIIFWQYGKwYBBQUCoIIFTTCCBUmgJDAiBgkqhkiC9xIBAgIGCSqGSIb3EgECAgYKKwYBBAGCNwICCqKCBR8EggUbYIIFFwYJKoZIhvcSAQICAQBuggUGMIIFAqADAgEFoQMCAQ6iBwMFACAAAACjggQyYYIELjCCBCqgAwIBBaETGxFETTIuQ09NTVZBVUxULkNPTaIsMCqgAwIBAqEjMCEbBEhUVFAbGWRtMmRldjIuZG0yLmNvbW12YXVsdC5jb22jggPeMIID2qADAgEDoQMCAQKiggPMBIIDyGTMuIrY6QQvJOpnyI+/UjNJwr1QlYhzCPbTYK2EQpX72bmFE3IxqNxpw1i+i2DT5u1WCwYf8Swr0tXbiMlwu4U0NgK9Lmsy3R+sDQM2oNxZUAySNsXsihvSu7esDz2aV2VVMWttWK7AWXyFXicJrDcU/uJGP/VLwE6zhKgccUBUY6B/n2jzx02cIncyO+dqpnFslf32JaBhkxxCz8jDfVkaInMnbHAOH/QUe3z54p4zVh3qxBidvq/k6GYk/WnbO3QOBGbr7Kkx2ASE1rr+CtdRH+yKRLp3tVYcOn9YK2opogX4sExSn4ES3xM7tWPgqIfv+LDuibJp3Vf0+eliNtoaLeNRi321xmWNzy3jpSSp3XIQo0EU8HhCo0c0jrfCtF3rAFyTtM2exK0C5KhDIcM4zKqB6sREjzU0O68V3pxWHPEfI7OOurMy26KACoplaSYDoXs8WTi+QRM4pJWX77mHytuifO1rZ48XyrqRBsaD9poPkES6Ly73a5koBpab/YuNhfz0TliTzvJvxF6Mh2K4mxfXXoVBm8+X4S6GcEFdeOMMoHKvA9dVcXfj2XcLv59r1iVdeV42HoKbZ5P3pAEccFamm7h6XU2Lt6vVGVq7PqGmw60lH/LJwalz4d9qwG4sboeyCtpf4+8aQ82GMGi6Ytd2nvF1MFNJLUcwJjfr1CDV0Q341Scg2GHYXOGjlgusE8UF1mw192Q6127i8J3U9BDQwcjfhcyObwaZ2WwpLXG1623X2Wc27cLFvYXdzzcKvcW+tavFP2ewhN6PtHDYwCZOc/6tjaC4ARgm6kAxmzCbmNgamwnIqc2cBJEaAp1dQa0AqRfCuFcPwSG+DSuN8cFYqdUznaYhL0Pc6LewvpaeZ8sRM7xSQM5unop9Sn6Dm21kbsj/n+jhPjwpTd1BPIODB1WApqwrQH17pj+0WIgjoecLt7oyUG0imm5zz61d6Iwwr1+/FprAheVqUjZ6a0MC7LVd0ejnRLCgTGhj2zgwO7UVySIrwxYwaDXwcnWzY7jiu/YSW8m4g7WQkb7QjeDkelWouswyXhMnv/pbiiRJWSZXmlUlzV607impHjM9tEgdoO1YZN6I+4nw+hfDpYNzdAxKjlrNkh+5gsvfkFg/NuCoQ3ijJYJZ+2v/bZfgm9GPEUmYvaritDM2l9vW03LJ10Rbo7q9NkI0+vIi0YFcp9h9uQmuFl5vD2upxmJeYzrKLDTHA4w4noQUNN/wMAb0KhwxFonVlf5l/tRyzJadYMGh1/5zyGZdj+QVmLhXyf+XR40qpIG2MIGzoAMCAQOigasEgajz+s+hAjvyika5Uud8d3Aoio2h1c9NP24l2BG316AZOyy3pvRXGeItl7GTx5TqijstCuVTOeUNwJFr8O+EGM86zIGDd1g+gokBg38l7Oqvo1CBddItQnhhHKPpz12Z0dgxKjIsvKzy8hBSrz8tv9HE6DG2yY5A6Hpo75mhEhFAWT89/TpwOOcMgVwaf3U4IkfMx+fLFPG27VtzcVpusMb7FCIYBUs5I+Y=
javax.security.auth.login.LoginException: Message stream modified (41)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Unknown Source)
at com.sun.security.auth.module.Krb5LoginModule.login(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at javax.security.auth.login.LoginContext.invoke(Unknown Source)
at javax.security.auth.login.LoginContext.access$000(Unknown Source)
at javax.security.auth.login.LoginContext$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(Unknown Source)
at javax.security.auth.login.LoginContext.login(Unknown Source)
at org.apache.jsp.ssotest_jsp.createServiceSubject(ssotest_jsp.java:78)
at org.apache.jsp.ssotest_jsp.authenticate(ssotest_jsp.java:52)
at org.apache.jsp.ssotest_jsp._jspService(ssotest_jsp.java:241)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Unknown Source)
Caused by: KrbException: Message stream modified (41)
at sun.security.krb5.KrbKdcRep.check(Unknown Source)
at sun.security.krb5.KrbAsRep.(Unknown Source)
at sun.security.krb5.KrbAsReq.getReply(Unknown Source)
at sun.security.krb5.Credentials.sendASRequest(Unknown Source)
at sun.security.krb5.Credentials.acquireTGT(Unknown Source)
… 33 more
Hi Venkat,
“setspn”
In what machine? The windows server hosting the active directory. The machine hosting Tomcat webserver? The client workstation? …?
Thanks,
Agus
–setspn config ?
1. AD server
2.Web server
— do not config from tomcat ?
1.yes
2.no
— jaas.conf location is….
1.webServer
2.AD server..
ps.. sorry i can’t speake english very well…
thanks !~
setspn = AD (Active Directory)
jaas.conf = WebServer
Here’s a project, http://spnego.sourceforge.net/pre_flight.html, that has some easy to understand documentation as well as an implementation of an SPNEGO Http Servlet Filter.
Hi Venkat,
javax.security.auth.login.LoginException: No route to host: Datagram send failed
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Kr
b5LoginModule.java:700)
at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.ja
va:542)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:1
86)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:6
80)
at javax.security.auth.login.LoginContext.login(LoginContext.java:579)
at org.apache.jsp.ssotest_jsp.createServiceSubject(ssotest_jsp.java:80)
at org.apache.jsp.ssotest_jsp.authenticate(ssotest_jsp.java:54)
after command kinit i have next error
C:\Program Files\Java\jdk1.6.0_14\bin>kinit.exe testsso@mydomain.ru
Password for testsso@mydomain.ru:
Exception: krb_error 41 Message stream modified (41) Message stream modified
KrbException: Message stream modified (41)
at sun.security.krb5.KrbKdcRep.check(KrbKdcRep.java:53)
at sun.security.krb5.KrbAsRep.(KrbAsRep.java:96)
at sun.security.krb5.KrbAsReq.getReply(KrbAsReq.java:449)
at sun.security.krb5.KrbAsReq.getReply(KrbAsReq.java:407)
at sun.security.krb5.internal.tools.Kinit.sendASRequest(Kinit.java:308)
at sun.security.krb5.internal.tools.Kinit.(Kinit.java:257)
at sun.security.krb5.internal.tools.Kinit.main(Kinit.java:107)
To execute kinit.exe you need krb5.ini file in C:\Windows directory.
Download MIT Kerberos windows distribution from below page.
http://web.mit.edu/Kerberos/dist/index.html
This kinit command would be more convenient for you.
Pingback: SPNEGO based Single sing-on (SSO) setup for Webtop « Documentum DAA
Hi,
I’ve implemented authentication using Krb5LoginModule. I would like to know:
Can i get an (authenticated) user’s Active Directory details/attributes using a LoginContext? To be specific, i need the “memberOf” attribute.
If so, how do i go about it?
Much thanks!
Nice article, thanks!
For anyone getting “Message stream modified” error, ensure the domiain name and default realm are all in uppercase (usually the case with AD). Also when giving the kinit command use the domain again in uppercase.
Thanks for the article, it was very helpful. I ended up needing to configure a keytab file on my tomcat server for the service account that connects to the active directory.
I was wondering if anyone has any advice on using this transparent sign on with a java client using jms to a jboss based server.
Hi Venkat,
I am implementing SSO with spnego (kerberos) with application server weblogic10 and i did everything as followed all set up mentioned in
http://spnego.sourceforge.net/
http://spnego.sourceforge.net/pre_flight.html
And the stand alone program (referenced here http://spnego.sourceforge.net/pre_flight.html) executes successfully
but currently i am not bothered about SSO becoz that i am going to test it later but what i am concerned is about
1. PC1 is in domain and weblogic is running on this (please note that i logged in domain a/c ans then started weblogic) so no issue till here
2. I accessed application running in above weblogic (PC1) from PC2 then i get below error on weblogic console
NTLM specified. Downgraded to Basic Auth (and/or SSL) but downgrade not supported.
java.lang.UnsupportedOperationException: NTLM specified. Downgraded to Basic Auth (and/or SSL) but downgrade not supported.
at nett.sourceforge.spnego.SpnegoProvider.negotiate(SpnegoProvider.java:146)
and when i debugged this i found that browser (PC2) is sending NTLM token (“TlRMTVNT”) which is why i am getting 404 eror code in browser
So the question is why PC2 is sending NTLM token
i expect it shouldn’t send this token and i want when PC2 is not in domain i want normal login to my application entering user/pwd instead SSO functinality
Please help me
> Some more tips:
> a) make sure testsso is part of Administrator group.
Is there any way around this requirement? Our team who manages AD would never give out an administrator account in AD.
Is it possible to authenticate end users without needing the testsso user also?
Frank,
Have your AD team setup the account as a Domain Member and under Delegation have them set “Trust this user for delegate to any service (Kerberos Only)”. This worked for me in the past.
Hey all,
I’m having the “error code is 25” issue. I know the token isn’t NTLM because it does not start with “TIRM…” My server is 2008 and the client is Win 7.
Does anyone have some tips on how to get beyond this hang-up? I am basically at the same point as this comment: http://webmoli.com/2009/08/29/single-sign-on-in-java-platform/#comment-641
Any assistance would be greatly appreciated!
Hi Venkat
First thanks for your interesting website.
I hope you you can read my message and help me.
Well, I have Windows 2003 server as AD, weblogic 10.3 as webserver under oracle enterprise manager fusion middleware 11g and I would like to deploy testsso application to authenticate users from client machine.
I have done succefuly all operations with SPN and test with kinit, i also configured weblogic, now i can see in weblogic users that create in the AD.
I deploy an application we with your testsso.jsp file and i deploy it.
When I call it for a configured browser of a client machine i get a window asking for user and password to conect to weblogic server than after that :
Error 500–Internal Server Error
From RFC 2068 Hypertext Transfer Protocol — HTTP/1.1:
10.5.1 500 Internal Server Error
The server encountered an unexpected condition which prevented it from fulfilling the request.
From an indepedent machine i get only a blank page
I will really appreciate your help
Best regards,
great great article for us: I did all but still in default tomcat examples protected I get j_Security_check not available error instead of verification of username password
Pingback: Single-Sign-On (SSO) in Java Platform using Active Directory (via WebMoli – Rediscover the Basics) « lava kafle kathmandu nepal
Hi. Thanks for the guide.
Just thought i’d share a way to make this work for those of us stuck with JDK 1.4. JDK 1.4 does’nt get SPNEGO or decrypt windows AD default rc4-hmac encryption.
1. Add jcifs-ext jar library to decode/remove the SBNEGO wrapper.
http://sourceforge.net/projects/jcifs-ext/
2. Modify the code in this example
replace
context.acceptSecContext(serviceTicket, 0, serviceTicket.length);
with
jcifs.spnego.NegTokenInit spTok = new jcifs.spnego.NegTokenInit(serviceTicket);
byte[] krbTok = spTok.getMechanismToken();
context.acceptSecContext(krbTok, 0, krbTok.length);
3. In windows AD, At the AD user account level enable “Use DES encryption type for this account”. in this example that would be the testsso user that have the spn’s added. DES encryption is supported by JDK 1.4
Thats it.
I get the below exception:
LoginException: Message steam modified (41)
Not sure if i am doing something wrong. Any help would be appreciated.
Pingback: Confluence: Software Tools & Systems Development
I am getting same exception like Randy. I am using JRE : 1.6.0_29 and copied the C:\jaas.conf
java.lang.Exception: javax.security.auth.login.LoginException: No LoginModules configured for SSOTESTING
org.apache.jsp.autoSignin_jsp.authenticate(autoSignin_jsp.java:66)
org.apache.jsp.autoSignin_jsp._jspService(autoSignin_jsp.java:325)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:337)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:71)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:75)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
net.sf.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:292)
net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:84)
net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter.doFilter(SecurityEnforcementFilter.java:182)
net.sf.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
net.sf.acegisecurity.wrapper.ContextHolderAwareRequestFilter.doFilter(ContextHolderAwareRequestFilter.java:50)
net.sf.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
net.sf.acegisecurity.securechannel.ChannelProcessingFilter.doFilter(ChannelProcessingFilter.java:168)
net.sf.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:226)
net.sf.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
net.sf.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:173)
net.sf.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:125)
com.nihilent.hrms.webapp.filter.UrlValidationFilter.doFilter(UrlValidationFilter.java:211)
I solved above problem.
My project is already using the other .conf file for NTLM authentication.So instead of creating new jass.conf,I just added below entry in that file :
SSOTESTING {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=false
storeKey=true
useTicketCache=false
principal=”testsso@JAVA.SUN.COM”;
};
I am trying to implement SSO using JAAS and GSS API with Apache DS and Kerberos. I did the following steps-
1. Setup the KDC using Apache DS 1.5.1 and Apache Directory Studio 1.5.3
2. Created a JAAS config file with below details-
GSSClient{
com.sun.security.auth.module.Krb5LoginModule required
useTicketCache=false;
};
GSSServer{
com.sun.security.auth.module.Krb5LoginModule required
storeKey=true;
};
3. Created Server and Client classes
4. Ran server using the main method
5. When I try to run the server code I get a timeout exception-
>>> KrbAsReq in createMessage
>>> KrbKdcReq send: kdc=localhost UDP:88, timeout=30000, number of retries =3, #bytes=238
>>> KDCCommunication: kdc=localhost UDP:88, timeout=30000,Attempt =1, #bytes=238
SocketTimeOutException with attempt: 1
>>> KDCCommunication: kdc=localhost UDP:88, timeout=30000,Attempt =2, #bytes=238
SocketTimeOutException with attempt: 2
>>> KDCCommunication: kdc=localhost UDP:88, timeout=30000,Attempt =3, #bytes=238
6. I am completely stuck and need advise.
Thanks.
Based on your checklist, I need to do this step: Internet Explorer should be able to identify your site as Intranet site. If not change the IE setting to make it as intranet site. Unfortunately, these settings are read only on end-users. What else can I do to get this to work?
i am trying to setup the SSO, but it has following error
GSSException: Failure unspecified at GSS-API level (Mechanism level: KDC has no support for encryption type (14))
at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:734)
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:300)
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:246)
at GSSServer.run(GSSServer.java:177)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:320)
at GSSServer.startServer(GSSServer.java:116)
at GSSServer.main(GSSServer.java:86)
it is pointing on GSSServer.java. it is
byteToken = serverGSSContext.acceptSecContext(byteToken, 0, byteToken.length);
what is the problem? how can i solve it?
It’s a pity you don’t have a donate button!
I’d most certainly donate to this excellent blog! I guess for now i’ll settle for bookmarking and adding your RSS feed to my Google account.
I look forward to new updates and will talk about this website with my Facebook group.
Talk soon!
Thanks for this! Stated on other replies too, uppercase of the realm is very important to avoid “Exception: krb_error 41 Message stream modified (41) “.
Here’s an example of correct notation:
[libdefaults]
default_realm = EXAMPLE.COM
[realms]
EXAMPLE.COM = {
kdc = domaincontroller.example.com
admin_server = domaincontroller.example.com
default_domain = EXAMPLE.COM
}
[domain_realm]
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COM
Regards,
Nika.
Hmm is anyone else having problems with the images on this blog loading?
I’m trying to find out if its a problem on my end or if it’s
the blog. Any feedback would be greatly appreciated.
It’s only one picture in this case and seems not to be a problem. Although judging from your username, this is a spam message? :(
The formerly-missing MPPE module has been added to the message, because only you possess your private key.
Another interesting feature with BCA online banking is customer can buy prepaid cell phone credit through their online account such as Saving account and
credit card details or banking details? Have
it automatically connect to a POP3 mail account and check for set up options especially
the disabling of the Browser Ssl Version error warnings.
Hi Venkat,
I think, I have got all the setup done like test id, setspn. But I am getting NULL from request.getHeader(“Authorization”);.
Could you please help me why I am getting null in getHeader.
Thanks
Vishwa
Pingback: Confluence: REIS
Hi Venkat,
private static String acceptSecurityContext(Subject subject, final byte[] serviceTicket)
throws GSSException {
// Accept the context and return the client principal name.
return Subject.doAs( subject, new PrivilegedAction() {
public String run() {
try {
// Identify the server that communications are being made to.
GSSManager manager = GSSManager.getInstance();
GSSContext context = manager.createContext( (GSSCredential) null);
System.out.println(“**********DATA*************”);
System.out.println(context.getLifetime());
System.out.println(serviceTicket);
context.acceptSecContext( serviceTicket, 0, serviceTicket.length); // Getting Error here for Defective token
return context.getSrcName().toString();
}
catch ( Exception e) {
e.printStackTrace();
return null;
}
}
});
}
I am getting Defective token detected (Mechanism level: GSSHeader did not find the right tag).
I checked my browser gives me Kerberos token.
Please Help Me.
Hi, I am getting Checksum failed error !!!!
Pingback: natural skin care products
Pingback: age spots removal cream
Finally i quit my regular job, now i earn decent money online you should try too, just search in google
– blackhand roulette system
you’re actually a excellent webmaster. The website loading pace is incredible.
It sort of feels that you’re doing any unique trick. Also, The contents are masterwork.
you’ve done a magnificent task in this matter!
Search Engine Optimization SEO friendly web design at a time
frame for website design is that the software has options, some providers
offer free shopping cart is an easy to start.
You must seo make your page. It takes a few lines about their website has just a site that’s elements are
all made up of a sudden, it cost many pounds per
click, you should know about development? Members stay ahead in the near future;
t a v t eg ee.
On unlicensed contractors the other leakers. This money may have been shot down an agreement witha potential customer has with many cases, a competent contractor.
Hi,
I need to develop a web application for the Intranet users. I dont want them to enter the login credentials each time they visit the site. It should be automatically loaded from the System Username and Password.
I have successfully implemented functionality which prompt user name and password registered with active directory. But i am confused to create and copy keytab file to login directly without prompt username & password.
Here is my queries, please let me know your suggestion.
1. Is it compulsory to set spn?
2. Do we need to create separate keytab file for each client? In my organization, there is around 800 people are working so should i need to add all client principal in keytab file & copy to client machine to perform autologin.
Regards
VsquareSolution
Thanks for another informative blog. Where else may I am getting that type of information written in such an ideal means?
I’ve a challenge that I am simply now running on, and I have been at the
look out for such information.
Pingback: How To Fix Error 3002 A Jsp Or Servlet Runtime Exception Errors - Windows Vista, Windows 7 & 8
Pingback: Kerberos authentication from my custom servlet? | Yerke Answers
Pingback: Fix J_security_check Error Handling Windows XP, Vista, 7, 8 [Solved]
Pingback: Confluence: 2. ЦОТТ - ТЗ на развитие
Credit card generator 2013 with cvv and expiration date free.
Regardez la vidéo pour entendre Gyllenhaal parler de
son expérience sur le tournage du film.
Pingback: Sso Net | injurylawyerhoustontx.xyz
Hi ,
How to get client windows user name . Bcoz i have tried with below codes .But it’s not working at all.
String userName = new com.sun.security.auth.module.NTSystem().getName();
and
String userName = System.getProperty(“username”);
In my servlet i am trying to check it , I am sharing my url to different person but always i am getting same username like it’s my username but the hostname i am getting correct one .
Can u please suggest me .
Regards
Tony
Hi,
I follow up your step it work on jdk 6 but jdk 8 has error kdc has no support for encryption type (14)
Hi can you please help me to find how can I authenticate a user in Swings based desktop application using Windows credentials.
You can use LDAP based authentication for dekstop application.
https://venkatsadasivam.com/2014/01/03/java-sample-active-directory-authentication-code/
hi Venkat,
what for do you use SPN in the code ? Many clients won’t give you SPN user/pass.
Any possibilities to make a code without it ?
Thanks
Please any one help on this?
Hi Venkat,
How to
Windows NT logon credentials in java swing application.I can able to get username using NTsystem
Hi All,
Can Anyone help me on below error while doing Kerberos authentication for webtop 6.8.2.
window server 2012 R2 standard
Tomcat 7
Java 7
com.documentum.web.formext.session.KerberosSSOAuthenticationScheme:Failed to accept or delegate service token :Failure unspecified at GSS-API level (Mechanism level: com.dstc.security.kerberos.KerberosException: Successfully matched service principal “HTTP/hostname.abc.com@ABC.COM” but not key type (17) + KVNO (14) in these entries:
Hi Venkat,
I have an application which uses SPNEGO om tomcat. 8.5.83. The SSO works fine with Google Chrome, internet explorer, safari but with Microsoft Edge getting HTTP 401 error on application path. It seems it is not getting certificate after tomcat port 8443 in the path. On the server logs getting “WARNING [https-jsse-nio-443-exec-7] net.sourceforge.spnego.SpnegoProvider.negotiate Downgrade NTLM request to Basic Auth.” warning.
Thanks in advance