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.
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.
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.
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.
Play is a high-productivity Java and Scala web application framework that integrates the components and APIs you need for modern web application development.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With