Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kerberos Authentication issue: SpnegoEngineException: No LoginModules configured for " #528

Open
sandeepsingh74 opened this issue Feb 19, 2020 · 4 comments

Comments

@sandeepsingh74
Copy link

Play Version

2.8.1

API

Scala

Operating System

CentOS Linux release 7.7.1908 (Core)

JDK

OpenJDK Runtime Environment (build 1.8.0_232-b09)

Library Dependencies

N/A

Expected Behavior

The playframework doc says it supports KERBEROS AuthScheme (https://www.playframework.com/documentation/2.8.x/ScalaWS#Configuring-WS). I am trying to connect an end-point which requires Kerberos authentication from a Play web application.

  1. Block of code that makes the request:
wsClient.url(someUrl).withAuth(username =someUser, password = somePwd, WSAuthScheme.KERBEROS).post(someJsonBody)
  1. My JVM options to specify Jaas login configuration:
    -Djava.security.auth.login.config=/path/to/jaas.conf
    Content of jaas.conf:
SomeContext {
     com.sun.security.auth.module.Krb5LoginModule required
     useKeyTab=false
     useTicketCache=true
     ticketCache="/dev/shm/ccache"
     principal="[email protected]";
};

I expected play framework to use my jaas.conf and load Kerberos login module. And then use the ticket cache from the location specified in ticketCache above. Prior to running the code I had performed kinit and verified that the ticket cache had the valid token.

Actual Behavior

  1. When I post the request, I get an Exception play.shaded.ahc.org.asynchttpclient.spnego.SpnegoEngineException: No LoginModules configured for "
javax.security.auth.login.LoginContext.init(LoginContext.java:264)
javax.security.auth.login.LoginContext.<init>(LoginContext.java:512)
play.shaded.ahc.org.asynchttpclient.spnego.SpnegoEngine.generateToken(SpnegoEngine.java:183)
play.shaded.ahc.org.asynchttpclient.util.AuthenticatorUtils.perConnectionAuthorizationHeader(AuthenticatorUtils.java:185)
play.shaded.ahc.org.asynchttpclient.netty.request.NettyRequestSender.sendRequestWithNewChannel(NettyRequestSender.java:279)
play.shaded.ahc.org.asynchttpclient.netty.request.NettyRequestSender.sendRequestWithCertainForceConnect(NettyRequestSender.java:142)
play.shaded.ahc.org.asynchttpclient.netty.request.NettyRequestSender.sendRequest(NettyRequestSender.java:113)
play.shaded.ahc.org.asynchttpclient.DefaultAsyncHttpClient.execute(DefaultAsyncHttpClient.java:241)
play.shaded.ahc.org.asynchttpclient.DefaultAsyncHttpClient.executeRequest(DefaultAsyncHttpClient.java:210)
play.api.libs.ws.ahc.StandaloneAhcWSClient.execute(StandaloneAhcWSClient.scala:90)
play.api.libs.ws.ahc.StandaloneAhcWSRequest.$anonfun$execute$1(StandaloneAhcWSRequest.scala:216)
play.api.libs.ws.WSRequestExecutor$$anon$2.apply(WSRequestFilter.scala:52)
play.api.libs.ws.WSRequestExecutor$$anon$2.apply(WSRequestFilter.scala:51)
play.api.libs.ws.ahc.StandaloneAhcWSRequest.execute(StandaloneAhcWSRequest.scala:219)
play.api.libs.ws.ahc.AhcWSRequest.execute(AhcWSRequest.scala:264)
play.api.libs.ws.ahc.AhcWSRequest.execute(AhcWSRequest.scala:260)
play.api.libs.ws.ahc.AhcWSRequest.post(AhcWSRequest.scala:192)

Is there any guide or example on how to use the WSAuthScheme.KERBEROS authentication? There are no examples or any config references for Kerberos authentication in Play framework doc (https://www.playframework.com/documentation/2.8.x/ScalaWS#Configuring-WS).

After tracing the underlying asynchttp client code, I noticed that the following line sets the loginContextName to empty string.
https://github.com/AsyncHttpClient/async-http-client/blob/master/client/src/main/java/org/asynchttpclient/spnego/SpnegoEngine.java#L178
Which is responsible for the exception: play.shaded.ahc.org.asynchttpclient.spnego.SpnegoEngineException: No LoginModules configured for "

Is there a way to configure Play server, so the loginContextName is set to a value, say "SomeContext" as in my jaas.conf? The bug seems to be with play framework not specifying a default loginContextName or allowing user to specify one.

@hhagblom
Copy link

hhagblom commented Aug 31, 2020

I experience the same issue when upgrading from Play 2.6 to Play 2.8 on Java 11

I downgraded to
compile group: 'com.typesafe.play', name: 'play-ahc-ws-standalone_2.12', version: '1.1.14'
Which does work, so this seems like a regression to me.

@ihostage

This comment has been minimized.

@ignasi35

This comment has been minimized.

@ignasi35 ignasi35 transferred this issue from playframework/playframework Sep 3, 2020
@totibi
Copy link

totibi commented May 18, 2021

Here are workaround which i'm found

// create custom WSClient For kerberos request. RELEASE after all work!
protected def getStandAloneWsClient(login: String, password: String)
                                     (implicit materializer: Materializer): AhcWSClient = {
      import scala.jdk.CollectionConverters._
      // custom realm building for this client
      val realmBuilder = new Realm.Builder(login, password)
          .setScheme(AuthScheme.KERBEROS)
          .setUsePreemptiveAuth(true)
          // tried if can't find any LoggingContext, src - play.shaded.ahc.org.asynchttpclient.spnego.SpnegoEngine.getLoginConfiguration
          // should not be empty!
          .setCustomLoginConfig(
              Map[String, String](
                  "useKeyTab" -> "false",
                  //                        "useTicketCache" -> "true",
                  //                        "ticketCache" -> "/dev/shm/ccache",
                  //                        "principal" -> principal,
              ).asJava
          )
      val configBuilder = new AhcConfigBuilder(AhcWSClientConfigFactory.forConfig())
      configBuilder.builder.setRealm(realmBuilder)
      val config: AsyncHttpClientConfig = configBuilder.build()
      // from play.api.libs.ws.ahc.StandaloneAhcWSClient.apply for setting Realm throught wrappers layers
      val asyncHttpClient = new DefaultAsyncHttpClient(config)
      val wsClient = new StandaloneAhcWSClient(asyncHttpClient)
      new AhcWSClient(wsClient)
  }

And then use as

val wsClient = getStandAloneWsClient(authSettings)
val responseF = wsClient.url(url).get
 // free resources
responseF.onComplete(_ => wsClient.close())
responseF

Don't use .withAuth on this client or it will be overwritten again!
This is looks like source of problem btw

// play/api/libs/ws/ahc/StandaloneAhcWSRequest.scala:276
 auth.foreach { data =>
      val realm = auth(data._1, data._2, authScheme(data._3))
      builder.setRealm(realm)
    }
    
 //  play.api.libs.ws.ahc.StandaloneAhcWSRequest#auth 
   /**
   * Add http auth headers. Defaults to HTTP Basic.
   */
  private[libs] def auth(username: String, password: String, scheme: Realm.AuthScheme = Realm.AuthScheme.BASIC): Realm = {
    val usePreemptiveAuth = scheme match {
      case AuthScheme.DIGEST => false
      case _ => true
    }


  // totibi: What about loggin context here?
    new Realm.Builder(username, password)
      .setScheme(scheme)
      .setUsePreemptiveAuth(usePreemptiveAuth)
      .build()
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants