Single-Sign-On (SSO) in Java Platform using Active Directory

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.

  1. Active Directory server ip address or hostname.
  2. 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:
http://webmoli.googlecode.com/svn/trunk/sso/

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

 

About these ads

55 Responses to Single-Sign-On (SSO) in Java Platform using Active Directory

  1. hluong says:

    where is the link to the ssotest.jsp file?

  2. Venkat says:

    sorry for the delay. ssotest.jsp is available now.

  3. hussain says:

    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)

  4. Venkat says:

    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!.

  5. Venkat says:

    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.

  6. Murali says:

    Venkat is back to blogging. :)

  7. Agus says:

    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

  8. Venkat says:

    In your active directory.

  9. Randy says:

    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?

  10. Andy says:

    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

  11. Venkat says:

    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.

  12. Andy says:

    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

  13. Andy says:

    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…

  14. Venkat says:

    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.

  15. Karthik says:

    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

  16. Venkat says:

    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=

  17. Karthik says:

    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

  18. cristina says:

    Hi Venkat,

    “setspn”

    In what machine? The windows server hosting the active directory. The machine hosting Tomcat webserver? The client workstation? …?

    Thanks,
    Agus

  19. cristina says:

    –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 !~

  20. Venkat says:

    setspn = AD (Active Directory)
    jaas.conf = WebServer

  21. 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.

  22. and) says:

    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)

  23. and) says:

    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)

  24. Venkat says:

    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.

  25. Pingback: SPNEGO based Single sing-on (SSO) setup for Webtop « Documentum DAA

  26. francis says:

    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!

  27. Vishal says:

    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.

  28. Jake says:

    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.

  29. sara says:

    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

  30. Frank says:

    > 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?

  31. Jon says:

    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.

  32. Visol says:

    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!

  33. Mounir says:

    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,

  34. lkafle says:

    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

  35. Pingback: Single-Sign-On (SSO) in Java Platform using Active Directory (via WebMoli – Rediscover the Basics) « lava kafle kathmandu nepal

  36. 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.

  37. ocpjp says:

    I get the below exception:
    LoginException: Message steam modified (41)

    Not sure if i am doing something wrong. Any help would be appreciated.

  38. Pingback: Confluence: Software Tools & Systems Development

  39. ajay says:

    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)

  40. ajay says:

    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”;
    };

  41. Shelly says:

    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.

  42. Cha says:

    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?

  43. Gary TANG says:

    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?

  44. gold invest says:

    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!

  45. 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.

  46. 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.

  47. Nika Gerson Lohman says:

    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? :(

  48. ssl proxy says:

    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.

  49. Vishwa says:

    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

  50. Pingback: Confluence: REIS

  51. yogesh says:

    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.

  52. yogesh says:

    Hi, I am getting Checksum failed error !!!!

  53. Pingback: natural skin care products

  54. Pingback: age spots removal cream

  55. Solomon says:

    Finally i quit my regular job, now i earn decent money online you should try too, just search in google
    – blackhand roulette system

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 51 other followers

%d bloggers like this: