Kerberos authentication

Hello,

I’m trying to simulate a kerberos authentification.

The server return a normal 401 with the “WWW-Authenticate: Negotiate” header.

During the generation of the kerberos token, I get the following exception:
org.ietf.jgss.GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)

Here is my scenario
`
package packagename.iam

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.http.util.HttpHelper
import org.asynchttpclient.Realm.AuthScheme

class
SSO extends Simulation {

System.setProperty(“java.security.krb5.conf”,"/etc/krb5.conf");
// System.setProperty(“java.security.krb5.realm”,“ADNAME.AD.domain.com”)
// System.setProperty(“java.security.krb5.kdc”,“domain.com”);

val httpProtocol = http
.baseURL(“https://integration.domain.com”)
.inferHtmlResources()
.acceptHeader(“text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8”)
.acceptEncodingHeader(“gzip, deflate”)
.acceptLanguageHeader(“en-US,en;q=0.5”)
.userAgentHeader(“Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0”)
.extraInfoExtractor(extraInfo => List(extraInfo.response.body.string))
.authRealm(HttpHelper.buildRealm(“userid”, “passwd”, AuthScheme.KERBEROS, false, None, None))
.disableWarmUp

val headers_0 = Map(“Upgrade-Insecure-Requests” → “1”)

val scn = scenario(“SSO”)
.exec(http(“request_0”)
.get("/iam/accueil/")
.headers(headers_0))

setUp(scn.inject(atOnceUsers(1))).protocols(httpProtocol)
}
`

I try to understand what is wrong by analysing the SpnegoEngine.generateToken method. It looks like something is missing, so I check the cached ticket with klist:
`
$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: userid@ADNAME.AD.domain.com

Valid starting Expires Service principal
16/06/2017 11:02:59 16/06/2017 21:02:59 krbtgt/ADNAME.AD.domain.com@ADNAME.AD.domain.com
renew until 17/06/2017 11:02:55
16/06/2017 11:03:04 16/06/2017 21:02:59 HTTP/integration.domain.com@
renew until 17/06/2017 11:02:55
16/06/2017 11:03:04 16/06/2017 21:02:59 HTTP/integration.domain.com@ADNAME.AD.domain.com
renew until 17/06/2017 11:02:55
`

I run the scenario with the debug logs activate.
`
12:09:44.467 [INFO ] a.e.s.Slf4jLogger - Slf4jLogger started
packagename.iam.SSO is the only simulation, executing it.
Select simulation id (default is ‘sso’). Accepted characters are a-z, A-Z, 0-9, - and _

Select run description (optional)

12:09:47.770 [INFO ] i.g.c.s.w.ConsoleDataWriter - Initializing
12:09:47.770 [INFO ] i.g.c.s.w.LogFileDataWriter - Initializing
12:09:47.773 [INFO ] i.g.c.s.w.ConsoleDataWriter - Initialized
12:09:47.782 [INFO ] i.g.c.s.w.LogFileDataWriter - Initialized
12:09:47.800 [DEBUG] i.n.c.MultithreadEventLoopGroup - -Dio.netty.eventLoopThreads: 16
12:09:47.809 [DEBUG] i.n.u.i.PlatformDependent - -Dio.netty.noUnsafe: false
12:09:47.810 [DEBUG] i.n.u.i.PlatformDependent0 - java.nio.Buffer.address: available
12:09:47.811 [DEBUG] i.n.u.i.PlatformDependent0 - sun.misc.Unsafe.theUnsafe: available
12:09:47.811 [DEBUG] i.n.u.i.PlatformDependent0 - sun.misc.Unsafe.copyMemory: available
12:09:47.811 [DEBUG] i.n.u.i.PlatformDependent0 - direct buffer constructor: available
12:09:47.812 [DEBUG] i.n.u.i.PlatformDependent0 - java.nio.Bits.unaligned: available, true
12:09:47.812 [DEBUG] i.n.u.i.PlatformDependent0 - java.nio.DirectByteBuffer.(long, int): available
12:09:47.812 [DEBUG] i.n.u.i.Cleaner0 - java.nio.ByteBuffer.cleaner(): available
12:09:47.813 [DEBUG] i.n.u.i.PlatformDependent - Java version: 8
12:09:47.813 [DEBUG] i.n.u.i.PlatformDependent - sun.misc.Unsafe: available
12:09:47.813 [DEBUG] i.n.u.i.PlatformDependent - -Dio.netty.noJavassist: false
12:09:47.862 [DEBUG] i.n.u.i.PlatformDependent - Javassist: available
12:09:47.862 [DEBUG] i.n.u.i.PlatformDependent - -Dio.netty.tmpdir: /tmp (java.io.tmpdir)
12:09:47.863 [DEBUG] i.n.u.i.PlatformDependent - -Dio.netty.bitMode: 64 (sun.arch.data.model)
12:09:47.863 [DEBUG] i.n.u.i.PlatformDependent - -Dio.netty.noPreferDirect: false
12:09:47.863 [DEBUG] i.n.u.i.PlatformDependent - io.netty.maxDirectMemory: 3711959040 bytes
12:09:47.872 [DEBUG] i.n.c.n.NioEventLoop - -Dio.netty.noKeySetOptimization: false
12:09:47.874 [DEBUG] i.n.c.n.NioEventLoop - -Dio.netty.selectorAutoRebuildThreshold: 512
12:09:47.876 [DEBUG] i.n.u.i.PlatformDependent - org.jctools-core.MpscChunkedArrayQueue: available
12:09:47.883 [DEBUG] i.n.u.ResourceLeakDetector - -Dio.netty.leakDetection.level: simple
12:09:47.883 [DEBUG] i.n.u.ResourceLeakDetector - -Dio.netty.leakDetection.maxRecords: 4
12:09:47.883 [DEBUG] i.n.u.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@6b98a075
12:09:47.885 [DEBUG] i.n.u.i.ThreadLocalRandom - -Dio.netty.initialSeedUniquifier: 0x85fefd9596d3e950 (took 0 ms)
12:09:47.897 [DEBUG] i.n.h.s.JdkSslContext - Default protocols (JDK): [TLSv1.2, TLSv1.1, TLSv1]
12:09:47.898 [DEBUG] i.n.h.s.JdkSslContext - Default cipher suites (JDK): [TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA]
12:09:47.933 [DEBUG] i.n.b.PooledByteBufAllocator - -Dio.netty.allocator.numHeapArenas: 16
12:09:47.933 [DEBUG] i.n.b.PooledByteBufAllocator - -Dio.netty.allocator.numDirectArenas: 16
12:09:47.933 [DEBUG] i.n.b.PooledByteBufAllocator - -Dio.netty.allocator.pageSize: 8192
12:09:47.933 [DEBUG] i.n.b.PooledByteBufAllocator - -Dio.netty.allocator.maxOrder: 11
12:09:47.933 [DEBUG] i.n.b.PooledByteBufAllocator - -Dio.netty.allocator.chunkSize: 16777216
12:09:47.933 [DEBUG] i.n.b.PooledByteBufAllocator - -Dio.netty.allocator.tinyCacheSize: 512
12:09:47.933 [DEBUG] i.n.b.PooledByteBufAllocator - -Dio.netty.allocator.smallCacheSize: 256
12:09:47.933 [DEBUG] i.n.b.PooledByteBufAllocator - -Dio.netty.allocator.normalCacheSize: 64
12:09:47.933 [DEBUG] i.n.b.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedBufferCapacity: 32768
12:09:47.933 [DEBUG] i.n.b.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimInterval: 8192
12:09:47.933 [DEBUG] i.n.b.PooledByteBufAllocator - -Dio.netty.allocator.useCacheForAllThreads: true
12:09:47.940 [DEBUG] i.n.b.ByteBufUtil - -Dio.netty.allocator.type: pooled
12:09:47.940 [DEBUG] i.n.b.ByteBufUtil - -Dio.netty.threadLocalDirectBufferSize: 65536
12:09:47.940 [DEBUG] i.n.b.ByteBufUtil - -Dio.netty.maxThreadLocalCharBufferSize: 200000
12:09:48.119 [INFO ] i.g.h.a.HttpEngine - Start warm up
12:09:48.146 [INFO ] i.g.h.a.HttpEngine - Warm up done
Simulation packagename.iam.SSO started…
12:09:48.268 [DEBUG] i.g.h.a.s.HttpTx$ - Sending request=request_0 uri=https://integration.domain.com/iam/accueil/: scenario=SSO, userId=1
12:09:48.322 [DEBUG] i.g.c.c.i.Injector - Start user #1
12:09:48.328 [DEBUG] i.g.c.c.i.Injector - Injecting 1 users, continue=false
12:09:48.329 [INFO ] i.g.c.c.Controller - InjectionStopped expectedCount=1
12:09:48.333 [DEBUG] i.n.b.AbstractByteBuf - -Dio.netty.buffer.bytebuf.checkAccessible: true
12:09:48.333 [DEBUG] i.n.u.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@5f8133eb
12:09:48.337 [DEBUG] i.n.u.i.JavassistTypeParameterMatcherGenerator - Generated: io.netty.util.internal.matchers.io.netty.handler.codec.http.HttpObjectMatcher
12:09:48.365 [DEBUG] i.n.u.Recycler - -Dio.netty.recycler.maxCapacity.default: 32768
12:09:48.365 [DEBUG] i.n.u.Recycler - -Dio.netty.recycler.maxSharedCapacityFactor: 2
12:09:48.365 [DEBUG] i.n.u.Recycler - -Dio.netty.recycler.linkCapacity: 16
12:09:48.365 [DEBUG] i.n.u.Recycler - -Dio.netty.recycler.ratio: 8
12:09:48.378 [DEBUG] o.a.n.s.InsecureTrustManagerFactory - Accepting a server certificate: CN=integration.domain.com, OU=SERVER, O=Canton de Vaud, C=CH
12:09:48.434 [DEBUG] o.a.n.c.NettyConnectListener - Using new Channel ‘[id: 0x82f72d6c, L:/10.247.161.251:41598 - R:integration.domain.com/10.120.192.100:443]’ for ‘GET’ to ‘/iam/accueil/’
12:09:48.438 [DEBUG] i.n.h.s.SslHandler - [id: 0x82f72d6c, L:/10.247.161.251:41598 - R:integration.domain.com/10.120.192.100:443] HANDSHAKEN: TLS_RSA_WITH_AES_128_CBC_SHA
12:09:48.460 [DEBUG] o.a.n.h.HttpHandler -

Request DefaultFullHttpRequest(decodeResult: success, version: HTTP/1.1, content: EmptyByteBufBE)
GET /iam/accueil/ HTTP/1.1
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
Host: integration.domain.com

Response DefaultHttpResponse(decodeResult: success, version: HTTP/1.1)
HTTP/1.1 401 Unauthorized
Set-Cookie: rpihttp=rp2i-front; path=/
Server: Apache
WWW-Authenticate: Negotiate
Content-Length: 129
Connection: close
Content-Type: text/html; charset=iso-8859-1

12:09:48.463 [DEBUG] o.a.s.SpnegoEngine - init integration.domain.com
Java config name: /etc/krb5.conf
Loaded from Java config
Search Subject for SPNEGO INIT cred (<>, sun.security.jgss.spnego.SpNegoCredElement)
No Subject
Search Subject for Kerberos V5 INIT cred (<>, sun.security.jgss.krb5.Krb5InitCredential)
No Subject
12:09:48.472 [ERROR] o.a.s.SpnegoEngine - generateToken
org.ietf.jgss.GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)
at sun.security.jgss.krb5.Krb5InitCredential.getInstance(Krb5InitCredential.java:147)
at sun.security.jgss.krb5.Krb5MechFactory.getCredentialElement(Krb5MechFactory.java:122)
at sun.security.jgss.krb5.Krb5MechFactory.getMechanismContext(Krb5MechFactory.java:187)
at sun.security.jgss.GSSManagerImpl.getMechanismContext(GSSManagerImpl.java:224)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:212)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:179)
at sun.security.jgss.spnego.SpNegoContext.GSS_initSecContext(SpNegoContext.java:882)
at sun.security.jgss.spnego.SpNegoContext.initSecContext(SpNegoContext.java:317)
… 48 common frames omitted
Wrapped by: org.ietf.jgss.GSSException: No valid credentials provided (Mechanism level: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt))
at sun.security.jgss.spnego.SpNegoContext.initSecContext(SpNegoContext.java:454)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:248)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:179)
at org.asynchttpclient.spnego.SpnegoEngine.generateToken(SpnegoEngine.java:141)
at org.asynchttpclient.netty.handler.intercept.Unauthorized401Interceptor.kerberosChallenge(Unauthorized401Interceptor.java:218)
at org.asynchttpclient.netty.handler.intercept.Unauthorized401Interceptor.exitAfterHandling401(Unauthorized401Interceptor.java:147)
at org.asynchttpclient.netty.handler.intercept.Interceptors.exitAfterIntercept(Interceptors.java:77)
at org.asynchttpclient.netty.handler.HttpHandler.handleHttpResponse(HttpHandler.java:130)
at org.asynchttpclient.netty.handler.HttpHandler.handleRead(HttpHandler.java:184)
at org.asynchttpclient.netty.handler.AsyncHttpClientHandler.channelRead(AsyncHttpClientHandler.java:76)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:435)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:280)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:396)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248)
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:250)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1228)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1039)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:411)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:643)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:566)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:480)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:442)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:131)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
at java.lang.Thread.run(Thread.java:748)
12:09:48.473 [DEBUG] o.a.n.c.ChannelManager - Closing Channel [id: 0x82f72d6c, L:/10.247.161.251:41598 - R:integration.domain.com/10.120.192.100:443]
12:09:48.476 [DEBUG] o.a.n.r.NettyRequestSender - Aborting Future NettyResponseFuture{currentRetry=0,
isDone=0,
isCancelled=0,
asyncHandler=io.gatling.http.ahc.AsyncHandler@1b4bd593,
nettyRequest=org.asynchttpclient.netty.request.NettyRequest@71e71e9e,
future=java.util.concurrent.CompletableFuture@3e5d1047[Not completed],
uri=https://integration.domain.com/iam/accueil/,
keepAlive=false,
redirectCount=0,
timeoutsHolder=org.asynchttpclient.netty.timeout.TimeoutsHolder@6a56961e,
inAuth=1,
statusReceived=0,
touch=1497607788460}

12:09:48.476 [DEBUG] o.a.n.r.NettyRequestSender - No valid credentials provided (Mechanism level: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt))
org.ietf.jgss.GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)
at sun.security.jgss.krb5.Krb5InitCredential.getInstance(Krb5InitCredential.java:147)
at sun.security.jgss.krb5.Krb5MechFactory.getCredentialElement(Krb5MechFactory.java:122)
at sun.security.jgss.krb5.Krb5MechFactory.getMechanismContext(Krb5MechFactory.java:187)
at sun.security.jgss.GSSManagerImpl.getMechanismContext(GSSManagerImpl.java:224)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:212)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:179)
at sun.security.jgss.spnego.SpNegoContext.GSS_initSecContext(SpNegoContext.java:882)
at sun.security.jgss.spnego.SpNegoContext.initSecContext(SpNegoContext.java:317)
… 48 common frames omitted
Wrapped by: org.ietf.jgss.GSSException: No valid credentials provided (Mechanism level: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt))
at sun.security.jgss.spnego.SpNegoContext.initSecContext(SpNegoContext.java:454)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:248)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:179)
at org.asynchttpclient.spnego.SpnegoEngine.generateToken(SpnegoEngine.java:141)
… 45 common frames omitted
Wrapped by: org.asynchttpclient.spnego.SpnegoEngineException: No valid credentials provided (Mechanism level: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt))
at org.asynchttpclient.spnego.SpnegoEngine.generateToken(SpnegoEngine.java:164)
at org.asynchttpclient.netty.handler.intercept.Unauthorized401Interceptor.kerberosChallenge(Unauthorized401Interceptor.java:218)
at org.asynchttpclient.netty.handler.intercept.Unauthorized401Interceptor.exitAfterHandling401(Unauthorized401Interceptor.java:147)
at org.asynchttpclient.netty.handler.intercept.Interceptors.exitAfterIntercept(Interceptors.java:77)
at org.asynchttpclient.netty.handler.HttpHandler.handleHttpResponse(HttpHandler.java:130)
at org.asynchttpclient.netty.handler.HttpHandler.handleRead(HttpHandler.java:184)
at org.asynchttpclient.netty.handler.AsyncHttpClientHandler.channelRead(AsyncHttpClientHandler.java:76)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:435)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:280)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:396)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248)
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:250)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1228)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1039)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:411)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:643)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:566)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:480)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:442)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:131)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
at java.lang.Thread.run(Thread.java:748)
12:09:48.486 [DEBUG] i.g.h.a.AsyncHandler - Request ‘request_0’ failed for user 1
org.ietf.jgss.GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)
at sun.security.jgss.krb5.Krb5InitCredential.getInstance(Krb5InitCredential.java:147)
at sun.security.jgss.krb5.Krb5MechFactory.getCredentialElement(Krb5MechFactory.java:122)
at sun.security.jgss.krb5.Krb5MechFactory.getMechanismContext(Krb5MechFactory.java:187)
at sun.security.jgss.GSSManagerImpl.getMechanismContext(GSSManagerImpl.java:224)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:212)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:179)
at sun.security.jgss.spnego.SpNegoContext.GSS_initSecContext(SpNegoContext.java:882)
at sun.security.jgss.spnego.SpNegoContext.initSecContext(SpNegoContext.java:317)
… 48 common frames omitted
Wrapped by: org.ietf.jgss.GSSException: No valid credentials provided (Mechanism level: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt))
at sun.security.jgss.spnego.SpNegoContext.initSecContext(SpNegoContext.java:454)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:248)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:179)
at org.asynchttpclient.spnego.SpnegoEngine.generateToken(SpnegoEngine.java:141)
… 45 common frames omitted
Wrapped by: org.asynchttpclient.spnego.SpnegoEngineException: No valid credentials provided (Mechanism level: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt))
at org.asynchttpclient.spnego.SpnegoEngine.generateToken(SpnegoEngine.java:164)
at org.asynchttpclient.netty.handler.intercept.Unauthorized401Interceptor.kerberosChallenge(Unauthorized401Interceptor.java:218)
at org.asynchttpclient.netty.handler.intercept.Unauthorized401Interceptor.exitAfterHandling401(Unauthorized401Interceptor.java:147)
at org.asynchttpclient.netty.handler.intercept.Interceptors.exitAfterIntercept(Interceptors.java:77)
at org.asynchttpclient.netty.handler.HttpHandler.handleHttpResponse(HttpHandler.java:130)
at org.asynchttpclient.netty.handler.HttpHandler.handleRead(HttpHandler.java:184)
at org.asynchttpclient.netty.handler.AsyncHttpClientHandler.channelRead(AsyncHttpClientHandler.java:76)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:435)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:280)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:396)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248)
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:250)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1228)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1039)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:411)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:643)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:566)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:480)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:442)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:131)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
at java.lang.Thread.run(Thread.java:748)
12:09:48.488 [WARN ] i.g.h.a.ResponseProcessor - Request ‘request_0’ failed: o.a.s.SpnegoEngineException: No valid credentials provided (Mechanism level: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt))
12:09:48.495 [DEBUG] i.g.h.a.ResponseProcessor -

Request:
request_0: KO o.a.s.SpnegoEngineException: No valid credentials provided (Mechanism level: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt))

Session:
Session(SSO,1,Map(gatling.http.cache.dns → io.gatling.http.resolver.ShuffleJdkNameResolver@2e20d91c),1497607788232,0,KO,List(),io.gatling.core.protocol.ProtocolComponentsRegistry$$Lambda$160/1177101170@33adcdd2)

HTTP request:
GET https://integration.domain.com/iam/accueil/
headers=
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
Host: integration.domain.com
realm=Realm{principal=‘userid’, scheme=KERBEROS, realmName=‘null’, nonce=‘null’, algorithm=‘null’, response=‘null’, qop=‘null’, nc=‘00000001’, cnonce=‘null’, uri=‘null’, methodName=‘GET’, useAbsoluteURI=‘false’, omitQuery=‘false’}

HTTP response:

12:09:48.498 [DEBUG] i.g.c.a.Exit - End user #1
12:09:48.499 [DEBUG] i.g.c.c.Controller - End user #1
12:09:48.499 [INFO ] i.g.c.c.Controller - All users are stopped
12:09:48.502 [DEBUG] o.a.n.h.HttpHandler - Channel Closed: [id: 0x82f72d6c, L:/10.247.161.251:41598 ! R:integration.domain.com/10.120.192.100:443] with attribute INSTANCE

Hi all,

I have some news.

Adding the -Djavax.security.auth.useSubjectCredsOnly=false option solved the following exception:
GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)

Then, I had a new exception:

unsupported key type found the default TGT: 18

This one was solved by installing the “Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy File”. My bad, I thought it was already installed.

So now, I have the following situation: Kerberos authentication is ok, but I can only authenticate with the user who is in the ticket cache, which I can check with the klist command.

I think it should be possible to do an authentication with the user / password specified in the realm

.authRealm(HttpHelper.buildRealm("userid", "passwd", AuthScheme.KERBEROS, false, None, None))

Any idea?

Best regards,
Maxime

Hey there,

Sorry, for some reason, your messages ended up in my spams.

Kerberos support is something very hard to investigate without a testing environment at hand.
Sadly, organizations with such entreprisey authentication mechanism are not very keen on sharing with/granting access to people from the outside.
I’m afraid you’ll have to investigate yourself, and hopefully contribute back. Or maybe contract with us so we can investigate in your environment.

Regards,

Hello Stéphane,

Thanks for your answer. I totally understand that you can’t reproduce the scenario. That’s why I’m investigating as much as I can. Currently, I’m running the scenario in remote debug.

The kerberos authentication is ok if there already a valid ticket, for example with the following command:

`
$ kinit userid1
Password for userid1@DOMAIN.AD.COM:
$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: userid1@DOMAIN.AD.COM

Valid starting Expires Service principal
23/06/2017 10:56:12 23/06/2017 20:56:12 krbtgt/DOMAIN.AD.COM@DOMAIN.AD.COM
renew until 24/06/2017 10:56:09
`

In this situation the authentication is ok. I can provide the debug log.
If there is no ticket in the cache the username and the password are prompted.

What I’m trying to do is to use the userid and password parameters of HttpHelper.buildRealm

Credentials are well set in org.asynchttpclient.Realm

After that the kerberosChallenge method of org.asynchttpclient.netty.handler.intercept.Unauthorized401Interceptor is called, everything looks fine.

I’m trying to understand if it’s normal to create a GSSContextImpl with GSSCredential object which is null.
Second option, I have seen that there is several option for the KRb5Module : https://docs.oracle.com/javase/7/docs/jre/api/security/jaas/spec/com/sun/security/auth/module/Krb5LoginModule.html
I tried different combination without success.

I’m sure I’m pretty close to have a valid configuration.

Please, let me know if you have any idea. I will be happy to share the result with the community.

Best regards,
Maxime

Hi Maxime,

Thanks a lot for sharing.
Frankly, I haven’t touch this piece of code in AHC for ages, and I was never able to run it myself against a real environment, just unit tests with mocks.
If you end up finding a solution, I’ll gladly review any PR you’d submit against AHC or Gatling, but I’m afraid I can’t do more than that.

Good luck!

Hi Maxime ,
are You able to solve the above problem?

Actually Iam also facing the same problem, Can you Please Helpme out?

Thanks,
Ashish Kumar

Hello,

Finally I manage to do a Kerberos authentication with AHC and then with Gatling.

As I explained in my message of the 19th June, the scenario works fine if there were already a valid ticket cache. I discover that it was also possible to enter the login password in the console.

First I do a simple java main to test the Kerberos authentication from this example: https://stackoverflow.com/questions/22774602/jaas-kerberos-authentication-fails-for-user-with-international-characters
It’s a good example to validate the Kerberos configuration and to create a custom CallbackHandler
Creating a custom CallbackHandler is the key to solve this problem.

It took a long time to understand how to use the custom CallbackHandler with the async http client.
It’s possible to define the callback handler with the following settings

`

Hi Maxime ,

Thanks for sharing the solution ,Can you please share the KerberosClientCallbackHandler code or scala file.

Thanks,
Ashish Kumar

Hello,

Here is my class KerberosClientCallbackHandler.

`

@Maxime, what does your gatling simulation look like. I created a KerberosClientCallBackHandler (Java class) just like the one you posted, and had no issues logging in using just it.

And in the Simulation I added the following 2 lines

Security.setProperty(“auth.login.defaultCallbackHandler”, classOf[KerberosClientCallbackHandler].getName)
System.setProperty(“javax.security.auth.useSubjectCredsOnly”, “false”)
but am having no luck hitting a page using the simulation.