0

I'm trying to implement a Kerberos authentication system integrated within a -based application.

After requesting from my machine a ticket with kinit HTTP/app.company.local@COMPANY.LOCAL I open the web page on Chrome and I get the stacktrace:

GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
at sun.security.jgss.GSSHeader.<init>(GSSHeader.java:97)
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:306)
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285)
at org.eclipse.jetty.security.SpnegoLoginService.login(SpnegoLoginService.java:138)
at org.eclipse.jetty.security.authentication.LoginAuthenticator.login(LoginAuthenticator.java:61)
at org.eclipse.jetty.security.authentication.SpnegoAuthenticator.validateRequest(SpnegoAuthenticator.java:99)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:483)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at org.eclipse.jetty.server.Server.handle(Server.java:524)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:201)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Thread.java:748)

I could find a few threads about this issue (although none so far managed to work for me). I guess the server returns a NTLM token which the web-application isn't able to parse.

I can assess though, that the web-application does manage to reach the Kerberos server, given the event log:

Kerberos event log

I wonder why that logoff happens, if it alters the authentication outcome, and thus triggers the GSSException on the web-server.


  • The first two entries (right after the Log clear),Logon and Special Logon events, have a Logon ID: 0xCDE977CB.
  • The other two + the Logoff event have the ID: 0xCDE9781A.
  • *.company.local and *.company.com (the localhost web-server URL) have been added to the Intranet trusted sites (didn't really understand which one I had to trust)
  • I'm connecting to the Kerberos Server via a VPN
  • I'll have to bind the Jetty/SPNego classes with our custom home-grown authentication system

The problem arises from GSSHeader.class, as the stack-trace shows.

GSSHeader Constructor

For some reason I'm getting the wrong code.

My configuration files:

spnego.conf

com.sun.security.jgss.initiate {
    com.sun.security.auth.module.Krb5LoginModule required
    principal = "HTTP/app.company.local"
    keyTab = "D:/00_company/workspace/branch_develop/modules/config/auth/krb5.keytab"
    useKeyTab = true
    storeKey = true
    debug = true
    isInitiator = false;
};

com.sun.security.jgss.accept {
    com.sun.security.auth.module.Krb5LoginModule required
    principal = "HTTP/app.company.local"
    useKeyTab = true
    keyTab = "D:/00_company/workspace/branch_develop/modules/config/auth/krb5.keytab"
    storeKey=true
    debug=true
    isInitiator=false;
};

krb5.ini

[libdefaults]
default_realm = COMPANY.LOCAL
permitted_enctypes = aes256-cts arcfour-hmac-md5 aes256-cts-hmac-sha1-96
default_tgs_enctypes = aes128-cts aes256-cts arcfour-hmac-md5 aes256-cts-hmac-sha1-96
default_tkt_enctypes = aes128-cts aes256-cts arcfour-hmac-md5 aes256-cts-hmac-sha1-96
default_keytab_name = D:/00_company/workspace/branch_develop/modules/common-config/auth/krb5.keytab
default_cache_name = C:/Users/mp91/krb5cc_mp91

[realms]
COMPANY.LOCAL = {
    kdc = PC-i7.COMPANY.local:88
    admin_server = 192.168.0.5
    default_domain = company.local
}

[domain_realm]
company.local = COMPANY.LOCAL
.company.local = COMPANY.LOCAL

[appdefaults]
autologin = true
forwardable = true

spnego.properties

targetName = HTTP/app.company.local

This is the Java code that programmatically registers the <security-constraint> on application start-up.

private SecurityHandler wrapEnableSSOAuthHandlers(final Handler collection) {

  // programmaticaly set JVM properties

  // ini file
  System.setProperty(
        "java.security.krb5.conf",
        _config.getString("authentication.win_sso.spnego.krb5")
  );
  System.setProperty(
        "java.security.auth.login.config",
        _config.getString("authentication.win_sso.spnego.login")
  );
  System.setProperty(
        "javax.security.auth.useSubjectCredsOnly",
        "false"
  );

  final Constraint spnegoConstraint = new Constraint();
  spnegoConstraint.setName(Constraint.__SPNEGO_AUTH);

  final String domainRealm = _config.getString("authentication.win_sso.domain.realm");
  // resolves to "COMPANY.DOMAIN"

  spnegoConstraint.setRoles(new String[]{domainRealm});
  spnegoConstraint.setAuthenticate(true);

  final ConstraintMapping mapping = new ConstraintMapping();
  mapping.setConstraint(spnegoConstraint);
  mapping.setPathSpec("/*");

  final SpnegoLoginService loginService = new SpnegoLoginService();

  final String spnegoProperties = _config.getString("authentication.win_sso.spnego.properties");

  loginService.setConfig(spnegoProperties);
  loginService.setName(domainRealm);

  final ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
  securityHandler.setLoginService(loginService);
  securityHandler.setConstraintMappings(new ConstraintMapping[]{mapping});
  securityHandler.setRealmName(domainRealm);
  securityHandler.setAuthenticator(new SpnegoAuthenticator());
  securityHandler.setHandler(collection);


  return securityHandler;
}

Registration:

// ...
Handler wrappedSecurityHandler = wrapDisableTraceHandlers(handlers);
final boolean enableWinSSOauthentication = _config.getBoolean("authentication.win_sso.enable");

if (enableWinSSOauthentication) {
  wrappedSecurityHandler = wrapEnableSSOAuthHandlers(wrappedSecurityHandler);
}

_server.setHandler(wrappedSecurityHandler);
// ...
payloc91
  • 3,724
  • 1
  • 17
  • 45
  • 1
    Sounds like you should file a bug at https://github.com/eclipse/jetty.project/issues – Joakim Erdfelt Jun 18 '18 at 13:18
  • @JoakimErdfelt it's a complex system. May as well be a configuration issue. Anyway I have added the configuration files, code and so on... – payloc91 Jun 18 '18 at 14:40

1 Answers1

0

The solution to this (in my case) is the same as the other question I had posted.

Basically (quoting my answer):

having client and server on two distinct virtual machines ( that are on the same physical server! ) can lead to a NTLM token.

So, if you have set everything right but still getting a Defective token detected, you should try to access the server from a different computer (as long as that machine is joined to the company domain).

Community
  • 1
  • 1
payloc91
  • 3,724
  • 1
  • 17
  • 45