How to verify ES256 JWTs (JSON Web Tokens)

(I’m doing this from Elixir, but I don’t think that makes any real difference to the use of the Erlang libraries)

I’ve got a JWT:

eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IllkWVRDTEF4R0tXUmVWcmF1cVR6VmVwTlM2SHViM0NPT3Z1OHpvdk02SkkifQ.eyJzaWQiOiJjbTFxb2t6MjcwMWdkeXphdDc4MGIzNnhlIiwiaXNzIjoicHJpdnkuaW8iLCJpYXQiOjE3MjgyODYyODIsImF1ZCI6ImNtMW9tNmw5YjA2N3pwcjJrNXJqYTI5emEiLCJzdWIiOiJkaWQ6cHJpdnk6Y20xcHhvYTliMDBlbmx1ZnJjaWNsMDNoYyIsImV4cCI6MTcyODI4OTg4Mn0.d6adVWpxGpBjgctcxNGhl7JYifTJ2DuGQ7UgiyCgLAOaV2EEi93QdyIxaqIvJqE8MlWBUB75U7lkx7VDHVmkIA

And a public key:

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKb10T35LVhx3qRHe644XbRwY3ck/FvkuIcOrX1xQYmyUZZ4FcNKTF5L0e8K+eMgYur0hCl2JaPFjpAHG2EYzTA==
-----END PUBLIC KEY-----

https://jwt.io/ agrees that the signature matches with that public key. The basic process I’m using is:

        [asn] = :public_key.pem_decode("-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKb10T35LVhx3qRHe644XbRwY3ck/FvkuIcOrX1xQYmyUZZ4FcNKTF5L0e8K+eMgYur0hCl2JaPFjpAHG2EYzTA==
-----END PUBLIC KEY-----")
        pubkey = :public_key.pem_entry_decode(asn)
        signed = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IllkWVRDTEF4R0tXUmVWcmF1cVR6VmVwTlM2SHViM0NPT3Z1OHpvdk02SkkifQ.eyJzaWQiOiJjbTFxb2t6MjcwMWdkeXphdDc4MGIzNnhlIiwiaXNzIjoicHJpdnkuaW8iLCJpYXQiOjE3MjgyODYyODIsImF1ZCI6ImNtMW9tNmw5YjA2N3pwcjJrNXJqYTI5emEiLCJzdWIiOiJkaWQ6cHJpdnk6Y20xcHhvYTliMDBlbmx1ZnJjaWNsMDNoYyIsImV4cCI6MTcyODI4OTg4Mn0"
        signature = :base64url.decode("d6adVWpxGpBjgctcxNGhl7JYifTJ2DuGQ7UgiyCgLAOaV2EEi93QdyIxaqIvJqE8MlWBUB75U7lkx7VDHVmkIA")
        true = :public_key.verify(signed, :sha256, signature, pubkey)

This process works fine for RS256 JWTs, and I have working code for EdDSA JWTs as well, but for some reason the final verify returns false here rather than true. I know that this particular JWT is now expired, that doesn’t matter for verifying the signature.

Presumably I’m doing something wrong, but I can’t work out what it might be

1 Like

Have you considered just using jose? https://hex.pm/packages/jose
Provides both Elixir and Erlang APIs

1 Like

MongooseIM uses jwerl for JWTs
GitHub - G-Corp/jwerl: [MIRROR] Erlang JWT Library