Technical backend implementation

Note: You will have to define a custom claim which will be embedded in the signed token (JWS). You have to prefix all the claims with https://iadvize.com/

⚠️ The claim https://iadvize.com/visitorData is optional ⚠️

JWT Library

First, to deal with JWT, you will have to choose the right library which fits to your backend language. You can find on the official JWT website a list of many libraries implemented for many languages. The chosen library should support "A256GCM and RSA_OAEP_256" for creating the JWE, the inner JWS must be signed with "RS256".

An example in SCALA

Here you have a technical implementation of the solution in SCALA:

import java.security.interfaces.RSAPublicKey
import java.security.spec.{PKCS8EncodedKeySpec, X509EncodedKeySpec}
import java.security.{KeyFactory, KeyPairGenerator, PrivateKey, PublicKey}
import java.util.Date
import com.nimbusds.jose._
import com.nimbusds.jose.crypto._
import com.nimbusds.jwt.{JWTClaimsSet, SignedJWT}

object JWEBuilder {
	def main(args: Array[String]): Unit = {
		val (clientPubKey, clientPrivateKey) = getClientKeys()
		val (iadvizePubKey, iadvizePrivateKey) = getIAdvizeKeys()
		val JWS1 = createJWS(clientPrivateKey)
		val JWE1 = createJWE(iadvizePubKey, JWS1)
		println(s"JWS : ${JWS1.serialize()}")
		println(s"JWE : ${JWE1.serialize()}")
		val token = JWE1.serialize()
		val JWS2 = decryptJWE(iadvizePrivateKey, token)
		println(s"Is valid JWS : ${JWS2.verify(new RSASSAVerifier(clientPubKey.asInstanceOf[RSAPublicKey]))}")
		println(s"${JWS2.getJWTClaimsSet}")
	}
	def getClientKeys() : (PublicKey, PrivateKey) = {
		val generator = KeyPairGenerator.getInstance("RSA")
		generator.initialize(2048)
		val pairClient = generator.generateKeyPair
		val pubKeyClient = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(pairClient.getPublic.getEncoded))
		val privateKeyClient = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(pairClient.getPrivate.getEncoded))
		(pubKeyClient, privateKeyClient)
	}
	def getIAdvizeKeys() : (PublicKey, PrivateKey) = {
		val generator = KeyPairGenerator.getInstance("RSA")
		generator.initialize(2048)
		val pairIadvize = generator.generateKeyPair
		val pubKeyIadvize = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(pairIadvize.getPublic.getEncoded))
		val privateKeyIadvize = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(pairIadvize.getPrivate.getEncoded))
		(pubKeyIadvize, privateKeyIadvize)
	}
	def createJWS(clientPrivateKey: PrivateKey) : SignedJWT = {
		val claimsSet = new JWTClaimsSet.Builder()
		// You can define custom claims. Here you can define your User ID which will be embed in the signed token(JWS).
		// You have to prefix all the claims with `https://iadvize.com/”.
		// The claim https://iadvize.com/userId is mandatory.
		claimsSet.claim("https://iadvize.com/userId","c42ab96d-0637-4d1e-8be3-0a872d9d1ef1")
		// For security reason it’s better to set a quick expiration time. As this token will just be used to initialise a new secured visitor session on iAdvize 1 minute seems a good duration.
		claimsSet.expirationTime(ZonedDateTime.now().plusMinutes(1))
		val signer = new RSASSASigner(clientPrivateKey)
		val signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256), claimsSet.build())
		signedJWT.sign(signer)
		signedJWT
	}
	def createJWE(iadvizePublicKey : PublicKey, jws : SignedJWT) : JWEObject = {
		val header = new JWEHeader.Builder(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A256GCM).build()
		val payload = new Payload(jws)
		val jwe = new JWEObject(header, payload)
		jwe.encrypt(new com.nimbusds.jose.crypto.RSAEncrypter(iadvizePublicKey.asInstanceOf[java.security.interfaces.RSAPublicKey]))
		jwe
	}
	def decryptJWE(iadvizePrivateKey: PrivateKey, token : String): SignedJWT = {
		val o = JWEObject.parse(token)
		o.decrypt(new RSADecrypter(iadvizePrivateKey))
		o.getPayload.toSignedJWT
	}
}

The key parts for you are the functions createJWS() and createJWE() which we will detail below.

createJWS()

For security reason, it’s better to set a quick expiration time. As this token will just be used to initialize a new secured visitor session on iAdvize 1 minute seems a good duration. createJWE() Once we have a signed JWT, a JWS, we could encrypt this JWS to finally have a JWE.

Here is how the createJWS function would be modified to add the firstName and the lastName fields:

In the example above, the visitorData claim is a JSON object containing the “firstName” and “lastName” fields. Here is a complete example with all possible fields:

An example in Node.js

Here is how the same function would look in Node.js:

Last updated

Was this helpful?