Make spring boot web app support Windows Integrated Authentication using AD user

Kent010341 231 Reputation points
2023-04-07T09:09:07.38+00:00

Note: The AD is NOT on Azure. Our goal is to make the person who has already login with an AD user to Windows not need to log in to our web app again (i.e., SSO). We build the web app with spring boot, and use the package "Spring Security Kerberos." Currently, we still have some authentication problems. Hope someone can help us find out the answer. Thanks a lot. Version:

  • Spring boot: 2.7.5
  • Spring Security: 2.7.5
  • Spring Security Kerberos: 1.0.1.RELEASE

Here are the steps we set up:

  1. Add the computer "TEST-TICKET" to the AD domain
  2. Create a user "ticket" on AD
  3. Use the Administrator user to run this command to create service principal mapping and export the keytab file.
ktpass -out Desktop/ticket.keytab -mapUser ******@OA.TEST.COM -princ HTTP/TEST-TICKET.oa.test.com:******@OA.TEST.COM -pass GOGO!WTIETW -ptype KRB5_NT_PRINCIPAL -crypto All
  1. use klist -k -t ticket.keytab and kvno HTTP/TEST-TICKET.oa.test.com:8081 (after run kinit) to check the kvno (key version number) are matched.
  2. Select the "This account supports Kerberos AES 128 bit encryption" and "This account supports Kerberos AES 256 bit encryption" of the Properties of the user "ticket". User's image
  3. At the client's computer (log in with another AD user), set
    1. In "Internet Options -> Advanced", select "Enable Integrated Windows Authentication"
    2. In "Internet Options. -> Security -> Local intranet -> Custom level...", select "User authentication > Logon > Automatic logon only in Intranet zone"
    3. In "Internet Options. -> Security -> Local intranet ->Sites", add "https://TEST-TICKET.oa.test.com:8081"
    4. Use Edge browser, enter "https://TEST-TICKET.oa.test.com:8081", our web app server receives the request header which includes "Negotiate Token", and it seems like it throws an exception while validating the token
  4. Use Edge browser, enter "https://TEST-TICKET.oa.test.com:8081", our web app server receives the request header which includes "Negotiate Token", and it seems like it throws an exception while validating the token
2023-04-07 14:45:44.401  WARN 24820 --- [nio-8081-exec-6] w.a.SpnegoAuthenticationProcessingFilter : Negotiate Header was invalid: Negotiate YIIGhQYGKwYBBQUC.........

org.springframework.security.authentication.BadCredentialsException: Kerberos validation not successful
    at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:71) ~[spring-security-kerberos-core-1.0.1.RELEASE.jar:1.0.1.RELEASE]
    at org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider.authenticate(KerberosServiceAuthenticationProvider.java:64) ~[spring-security-kerberos-core-1.0.1.RELEASE.jar:1.0.1.RELEASE]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182) ~[spring-security-core-5.7.4.jar:5.7.4]
    at org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter.doFilter(SpnegoAuthenticationProcessingFilter.java:145) ~[spring-security-kerberos-web-1.0.1.RELEASE.jar:1.0.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.4.jar:5.7.4]
......
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
Caused by: java.security.PrivilegedActionException: null
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:716) ~[na:na]
    at java.base/javax.security.auth.Subject.doAs(Subject.java:439) ~[na:na]
    at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:68) ~[spring-security-kerberos-core-1.0.1.RELEASE.jar:1.0.1.RELEASE]
    ... 54 common frames omitted
Caused by: org.ietf.jgss.GSSException: Failure unspecified at GSS-API level (Mechanism level: Checksum failed)
    at java.security.jgss/sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:864) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:361) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:303) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.jgss.spnego.SpNegoContext.GSS_acceptSecContext(SpNegoContext.java:908) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.jgss.spnego.SpNegoContext.acceptSecContext(SpNegoContext.java:555) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:361) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:303) ~[java.security.jgss:na]
    at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:170) ~[spring-security-kerberos-core-1.0.1.RELEASE.jar:1.0.1.RELEASE]
    at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:153) ~[spring-security-kerberos-core-1.0.1.RELEASE.jar:1.0.1.RELEASE]
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:712) ~[na:na]
    ... 56 common frames omitted
Caused by: sun.security.krb5.KrbCryptoException: Checksum failed
    at java.security.jgss/sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType.decrypt(Aes256CtsHmacSha1EType.java:102) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType.decrypt(Aes256CtsHmacSha1EType.java:94) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.krb5.EncryptedData.decrypt(EncryptedData.java:180) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.krb5.KrbApReq.authenticate(KrbApReq.java:281) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.krb5.KrbApReq.<init>(KrbApReq.java:149) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.jgss.krb5.InitSecContextToken.<init>(InitSecContextToken.java:139) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:837) ~[java.security.jgss:na]
    ... 65 common frames omitted
Caused by: java.security.GeneralSecurityException: Checksum failed
    at java.security.jgss/sun.security.krb5.internal.crypto.dk.AesDkCrypto.decryptCTS(AesDkCrypto.java:453) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.krb5.internal.crypto.dk.AesDkCrypto.decrypt(AesDkCrypto.java:274) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.krb5.internal.crypto.Aes256.decrypt(Aes256.java:76) ~[java.security.jgss:na]
    at java.security.jgss/sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType.decrypt(Aes256CtsHmacSha1EType.java:100) ~[java.security.jgss:na]
    ... 71 common frames omitted

The Spring configuration file related to the authentication is https://gist.github.com/kent010341/1b715a6d26d30082be3345772dd3d801 (reference)

Windows for business Windows Client for IT Pros Directory services Active Directory
{count} votes

1 answer

Sort by: Most helpful
  1. Kent010341 231 Reputation points
    2023-05-08T03:39:31.7466667+00:00

    We use Wireshark to capture the packets during the Kerberos Authentication, and we find out that the request sent by the client browser doesn't contain the port. Therefore, the Kerberos Authentication will fail if we specify the port (e.g., 8080) while creating keytab due to the unmatched SPN.

    When we create the keytab without the port specified, the Kerberos Authentication passes.

    With this limitation, we decide to use multiple IPs to differentiate between services instead of using ports.

    I don't know if there's a better way to deal with multiple services.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.