Preface:
What is Paseto?: https://developer.okta.com/blog/2019/10/17/a-thorough-introduction-to-paseto
I have been able to successfully achieve the creation of a Paseto V1 token and corresponding public key using the PHP lib (with a RSA private key on the server side for keypair), and then use the public key to verify the given token on the Node.js side:
PHP Paseto Public V1:
$privateKeyV1 = new AsymmetricSecretKey($rsaPrivate, new Version1());
$publicKeyV1 = $privateKeyV1->getPublicKey();
$token = (string) (new Builder())
->setKey($privateKeyV1)
->setVersion(new Version1())
->setPurpose(Purpose::public())
// Set it to expire in one day
->setExpiration(
(new DateTime())->add(new DateInterval('P01D'))
)
->setAudience('Foo')
->setIssuedAt(new DateTime())
->setIssuer('Bar')
->setNotBefore()
->setSubject('IDP Paseto')
->setClaims([
'claim' => json_decode($this->claimJSON(), true),
])->toString();
return $response->withJson([
'public_key_v1' => $publicKeyV1->raw(),
'token' => $token
]);
NodeJS Paseto Public V1:
const token = "v1.public.sdsw5vsdf4554...............exampletoken:"; // Example paseto V1 token
const pubKey = await createPublicKey("-----BEGIN PUBLIC KEY-----\r\npubKeyFromAbovePHP\r\n-----END PUBLIC KEY-----"); // Example public key
const response = await verify(token, pubKey);
This works great, I can verify my claim in Node.js and process what I need using the ingested data.
Now if I try the following w/ V2, calling bin2hex()
on the public key to be able to store it and use it on the Node.js side, I am unable to properly verify in Node.js. I believe it has something to do with the sodium crypto binary key generation, and how the $publicKey->encode()
uses Base64UrlSafe::encodeUnpadded($this->key);
but am not sure.. I don't ever get the BEGIN PUBLIC KEY
from the publicKey created using V2, as I believe it is just stored as binary?
PHP Paseto Public V2:
$privateKeyV2 = AsymmetricSecretKey::generate(new Version2());
$publicKeyV2 = $privateKeyV2->getPublicKey();
$token = (string) (new Builder())
->setKey($privateKeyV2)
->setVersion(new Version2())
->setPurpose(Purpose::public())
->setExpiration((new DateTime())->add(new DateInterval('P01D')))
->setClaims([
'claim' => json_decode($this->claimJSON(), true),
])->toString();
return $response->withJson([
'public_key_v2' => bin2hex($publicKeyV2->raw()),
'token' => $token
]);
NodeJS Paseto Public V2:
const pubKey = await createPublicKey(Buffer.from('public_key_from_php_response_above', 'hex'));
const token = 'token_output_from_php_response_above';
const response = await verify(token, pubKey);
console.log(response);
I appreciate any feedback you may be able to provide. Please let me know if you have any additional questions. I tagged this with slim
for the PHP framework, as I am using the PHP paseto lib within a slim project to store the public/private keys on my slim container, etc. and NodeJS within the context of a lambda.