SPNEGO Token generation

Alexey Novakov
Dec 25, 2019 · 3 min read
Photo by Jon Moore on Unsplash

SPNEGO — is a simple and protected negotiation mechanism used by client-server software. Often times, you may find it used in HTTP authentication. In this scenario, internet browser sends an encrypted token to an HTTP service and the last one is using Kerberos to verify that the token is valid. In the result, client request will be either successful/handled in case token is valid or otherwise failed. Internet browsers send such negotiation token automatically based on predefined user-trusted URIs in browser settings.

SPNEGO protocol is described in RFC 4178. If you want to know more about it go to:

Generate SPNEGO token in Scala

In order to implement SPNEGO Kerberos authentication in Scala or Java, one can do that by just using standard JRE library, without depending on any third-party library from Scala/Java world.

Below is a working code sample, that can generate SPNEGO token as a string. Before trying this code sample you need:

  1. Get Kerberos ticket or user keytab on your client machine, i.e. the machine which will be running further code.
  2. Prepare jaas.conf file by setting 3 last properties in it:
com.sun.security.jgss.initiate {
com.sun.security.auth.module.Krb5LoginModule required
debug=true
useTicketCache=true
storeKey=false
doNotPrompt=true
renewTGT = false
useKeyTab=true
isInitiator=true
refreshKrb5Config=true
ticketCache="/tmp/krb" # either set path to your ticket cache
keyTab="/tmp/myuser.keytab" # or set path to a keytab, if any
principal="myuser@EXAMPLE.COM"; # set principal for authentication
};

Save content of the above configuration into jaas.conf file.

Then set path to your jaas.conf at loginConfigPath variable. Then below code sample can be run:

import java.nio.file.{Files, Path, Paths}
import java.util.Base64
// these are JRE-included classes, so no 3rd party libs needed
import
org.ietf.jgss.{GSSContext, GSSCredential, GSSManager, Oid}
def getKerberosToken(serverPrincipal: String): String = {
System.setProperty("sun.security.krb5.debug", "true")
System.setProperty(
"javax.security.auth.useSubjectCredsOnly", "false")
val loginConfigPath = "/path/to/jaas.conf"

System.setProperty("java.security.auth.login.config",
loginConfigPath)

val manager = GSSManager.getInstance
val serverName = manager.createName(serverPrincipal, null)
val krb5Oid = new Oid("1.2.840.113554.1.2.2")
val clientContext =
manager.createContext(serverName, krb5Oid,
null.asInstanceOf[GSSCredential], GSSContext.DEFAULT_LIFETIME)

val clientToken = clientContext.initSecContext(
new Array[Byte](0), 0, 0)
Base64.getEncoder.encodeToString(clientToken)
}

Then take the returned value of getKerberosToken function and include into your HTTP request. An example using Requests Scala library:

val token = getKerberosToken("HTTP/myservice@EXAMPLE.COM")requests.get(
"http://myservice/api",
headers = Map(
"Authorization" -> s"Negotiate $token"
)
)

Summary

SE Notes by Alexey Novakov

Software Engineering notes on Scala, JVM and other goodies

Alexey Novakov

Written by

SE Notes by Alexey Novakov

Software Engineering notes on Scala, JVM and other goodies

More From Medium

More from SE Notes by Alexey Novakov

More from SE Notes by Alexey Novakov

Of Scala Type Classes

More from SE Notes by Alexey Novakov

More from SE Notes by Alexey Novakov

Build Your Spark Image on GCP

More on Scala from SE Notes by Alexey Novakov

More on Scala from SE Notes by Alexey Novakov

Scala Type Classes comparison

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade