Skip to content

Instantly share code, notes, and snippets.

@dacr
Last active May 6, 2023 15:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dacr/05fdc62826a96dfaca5834c9720c2c61 to your computer and use it in GitHub Desktop.
Save dacr/05fdc62826a96dfaca5834c9720c2c61 to your computer and use it in GitHub Desktop.
decode/encode/validate JWT token with public key / published by https://github.com/dacr/code-examples-manager #118813f0-c4ea-4196-aa28-880e97e43991/10df923dd5b0c02eedd087c9aff788b47c1b5d98
// summary : decode/encode/validate JWT token with public key
// keywords : scala, token, api, jwt, authentication, publickey, privatekey, @testable
// publish : gist
// authors : David Crosson
// license : Apache NON-AI License Version 2.0 (https://raw.githubusercontent.com/non-ai-licenses/non-ai-licenses/main/NON-AI-APACHE2)
// id : 118813f0-c4ea-4196-aa28-880e97e43991
// created-on : 2022-01-24T20:21:14+01:00
// managed-by : https://github.com/dacr/code-examples-manager
// run-with : scala-cli $file
// ---------------------
//> using scala "3.2.2"
//> using dep "org.json4s::json4s-jackson:4.0.6"
//> using dep "org.json4s::json4s-ext:4.0.6"
//> using dep "com.github.jwt-scala::jwt-json4s-jackson:9.2.0"
//> using dep "com.github.jwt-scala::jwt-core:9.2.0"
// ---------------------
import org.json4s.*
import org.json4s.jackson.Serialization
import org.json4s.JsonDSL.WithBigDecimal.*
import pdi.jwt.{JwtAlgorithm, JwtJson4s}
import java.time.Instant
import java.security.*
import java.security.interfaces.RSAPublicKey
import java.security.spec.*
import java.util.UUID
import scala.util.{Failure, Success, Try}
val key = KeyPairGenerator.getInstance("RSA")
val keysize = 4096
key.initialize(keysize)
val generatedKeyPair = key.generateKeyPair()
val pubkey = generatedKeyPair.getPublic.asInstanceOf[RSAPublicKey] // TODO of course very bad practice
val privkey = generatedKeyPair.getPrivate
// -----------------------------------------------------------------------------
val nowEpochSeconds: Long = Instant.now().getEpochSecond
// https://datatracker.ietf.org/doc/html/rfc7519#section-4.1
val claim = JObject(
("jti", UUID.randomUUID().toString), // JTW ID
("iss", "this-app"), // Issuer
("iat", nowEpochSeconds), // Issued at
("exp", nowEpochSeconds + 60), // Expiration time
("nbf", nowEpochSeconds + 2), // Not before
("sub", "userlogin@example.com"), // The subject
("user", 1)
)
val algo = JwtAlgorithm.RS512
val token = JwtJson4s.encode(claim, privkey, algo)
val decodedJson = JwtJson4s.decodeJson(token, pubkey, Seq(algo))
val decodedClaim = JwtJson4s.decode(token, pubkey, Seq(algo))
// -----------------------------------------------------------------------------
val validatingAlgorithms = JwtAlgorithm.allRSA()
// -----------------------------------------------------------------------------
println("Validating before nbf")
assert(Try(JwtJson4s.validate(token, pubkey, validatingAlgorithms)).isFailure)
assert(!JwtJson4s.isValid(token, pubkey, validatingAlgorithms))
println("TOKEN INVALID")
// -----------------------------------------------------------------------------
Thread.sleep(2100)
println("Validating after nbf")
assert(Try(JwtJson4s.validate(token, pubkey, validatingAlgorithms)).isSuccess)
assert(JwtJson4s.isValid(token, pubkey, validatingAlgorithms))
println("TOKEN VALID !")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment