Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Play Framework & JSON Web Token

Is there a Scala implementation of JWT or at least an example with Play? After having posted this question I searched further on the Internet and found some intros to JWT. Any suggestion would be really appreciated.

like image 839
j3d Avatar asked Mar 18 '14 13:03

j3d


People also ask

What is Play Framework used for?

Play Framework makes it easy to build web applications with Java & Scala. Play is based on a lightweight, stateless, web-friendly architecture. Built on Akka, Play provides predictable and minimal resource consumption (CPU, memory, threads) for highly-scalable applications.

Is Play Framework MVC?

A play application follows the MVC architectural pattern applied to the Web architecture. This pattern splits the application into separate layers: the Presentation layer and the Model layer. The Presentation layer is further split into a View and a Controller layer.

Is Play Framework backend?

Play comes with two configurable server backends, which handle the low level work of processing HTTP requests and responses to and from TCP/IP packets. Starting in 2.6. x, the default server backend is the Akka HTTP server backend, based on the Akka-HTTP server. Prior to 2.6.

Is Play a Java framework?

Play is a high-productivity Java and Scala web application framework that integrates the components and APIs you need for modern web application development.


1 Answers

I am using Nimbus-JOSE-JWT in a spray.io app and am quite happy with it. The object performing authentication extends HttpAuthenticator and if it finds a correct JWT it returns the token subject and related info, otherwise None (authentication fails). With Play2 you can implement HTTP Basic Auth with something like this. Regarding token setting/getting which I assume is of more interest to you:

First, create a private/public key pair (I used parts of this code). Create the authentication object that loads the keys on initialization from the filesystem.

Create a a com.nimbusds.jose.crypto.MACSigner and a com.nimbusds.jose.crypto.MACVerifier using these keys.

Whenever you want to set a key, FIRST encrypt it, THEN sign it. Encryption:

private def encrypt(subject: String) = {
   val header = new JWEHeader(JWEAlgorithm.RSA_OAEP, EncryptionMethod.A128GCM)
   val jwt = new EncryptedJWT(header, claimSet(subject))
   val encrypter = new RSAEncrypter(publicKey.asInstanceOf[java.security.interfaces.RSAPublicKey])
   jwt.encrypt(encrypter)
   jwt.serialize()
}

The claimSet method predictably returns a set of claims:

def claimSet(subject: String) = {
   val jwtClaims = new JWTClaimsSet()
   jwtClaims.setIssuer(Config.JWT.issuer)
   jwtClaims.setSubject(subject)
   jwtClaims.setJWTID(java.util.UUID.randomUUID().toString())
   jwtClaims
}

The publicKey property is the value returned from KeyFactory.getInstance("RSA").generatePublic.

Signing:

private def sign(jwt: String) = {
   val jwsObject = new JWSObject(new JWSHeader(JWSAlgorithm.HS256), new Payload(jwt))
   jwsObject.sign(Tokens.signer)
   jwsObject.serialize
}

Given the above, when you receive a key you need to verify the signature first, then decrypt it. For verification, first you try to parse it with com.nimbusds.jose.JWSObject.parse(my_token) and as long as it doesn't throw a ParseException you call verify on the JWSObject that parse returns, using as an argument the MACVerifier that you created earlier. If verify returns true, you only need to call getPayload.toString on the same JWSObject to get the verified payload.

To decrypt the verified payload you call com.nimbusds.jwt.EncryptedJWT.parse on it, then something like:

val decrypter = new RSADecrypter(privateKey.asInstanceOf[java.security.interfaces.RSAPrivateKey])
jwt.decrypt(decrypter)

privateKey is the value returned from KeyFactory.getInstance("RSA").generatePrivate.

You can then get the claim set with jwt.getJWTClaimsSet.

Finally, with regard to setting the Authorization header, I'm doing this on my AngularJS client using principles also mentioned in this post.

like image 83
Costas Kotsokalis Avatar answered Oct 08 '22 16:10

Costas Kotsokalis