How to decode JWT with pem certificate value

Hi,

From the front end, I am getting a JWT and they have given me the below certificate.. If I have a public, we can simply use verify using policy, what if we have a certificate? Please help with this.

  -----BEGIN CERTIFICATE-----
      MIIC4jCCAcqgAwIBAgIQ.....aKLWSqMhozdhXsIIKvJQ==
      -----END CERTIFICATE-----
2 3 5,316
3 REPLIES 3

First, let us be careful about terms. With JWT, it is possible to

  • generate
  • verify
  • decode

The generation of a _signed_ JWT requires the use of a private or secret key. The former implies an asymmetric algorithm; the latter implies a symmetric algorithm. You mentioned a public key, so I'm guessing you're using JWT signed with an asymmetric algorithm, using a private key, and that you want to verify the JWT (not just decode it) with the public key.

What you have is a certificate.

The cert is just a way to bind a name to a public key. A certificate is a digitial document that says "Entity A is the owner of publickey xyz", and that digital document is signed by a signing party. Usually you trust the signing party.

Now let me answer some questions.

Your title asked "how can I decode a JWT"? Decoding a signed JWT is easy. You don't need a key to do it. In Apigee use the DecodeJWT policy. (You can also "manually" decode any signed JWT by splitting the JWT by dots, then base64-decoding the first two parts, then JSON parsing the results you get there.) But be careful! Decoding gives you information, but it does not VERIFY that the information has not been changed since the JWT was created and signed. In other words, just decoding a JWT does not Verify the signature on the JWT. So you should not trust the data you obtain from decoding a JWT, if you do not also verify the JWT.

In Apigee, the VerifyJWT policy lets you verify-and-decode the JWT.

If your JWT is signed with an asymmetric algorithm (let's say RS256), then you would configure the VerifyJWT policy something like this:

<VerifyJWT name='VerifyJWT-1'>
  <Algorithm>RS256</Algorithm>
  <Source>inbound_jwt</Source>
  <PublicKey>
    <Value ref='public_key_pem'/>
  </PublicKey>
</VerifyJWT>

That tells Apigee to retrieve a JWT from the context variable "inbound_jwt", and then retrieve and deserialize an RSA publiuc key from the context variable "public_key_pem". That latter variable should contain something that looks like this:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArouIADal6Q1l3I5RfBaN
Ltvb826+Djm4UrfI5jpO54K6j3GsvCRMYpz++SQ45sP31gFpl3jvBVyQ83DlUTWs
yb1zpjftLLHK04NJeFawS1Nbtj+2V56t7Zbl1byLbr8Rw1c8IO04oqnycrcAU33K
EdF5vluCvg8qpVCJz+AV1ZVNLWiLflyCVsF1RYlS/OfXVxeKQTE6k3UPDkg/5UOh
ZYZ1W96KyJwNM4lrziGqBWJIl6daYsJuT34Z4iOTVsDHPE9yeXFsaftdaPLe0aug
k6B/5we1CbQeijhPUmcnzmf6ArAGmtwooPLjowFjwOv1HS7sG67ODvzZY791hcbE
xQIDAQAB
-----END PUBLIC KEY-----

But you don't have a public key. You have a certificate, which contains a public key. You have something like this :

-----BEGIN CERTIFICATE-----
MIIDmjCCAoICCQDnv7D3k+UOBDANBgkqhkiG9w0BAQUFADCBjjELMAkGA1UEBhMC
VVMxCzAJBgNVBAgMAldBMREwDwYDVQQHDAhLaXJrbGFuZDEPMA0GA1UECgwGR29v
Z2xlMQ8wDQYDVQQLDAZBcGlnZWUxGjAYBgNVBAMMEWFwaWdlZS5nb29nbGUuY29t
MSEwHwYJKoZIhvcNAQkBFhJkY2hpZXNhQGdvb2dsZS5jb20wHhcNMTgxMDMwMjIz
ODAwWhcNMjgxMDI3MjIzODAwWjCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldB
MREwDwYDVQQHDAhLaXJrbGFuZDEPMA0GA1UECgwGR29vZ2xlMQ8wDQYDVQQLDAZB
cGlnZWUxGjAYBgNVBAMMEWFwaWdlZS5nb29nbGUuY29tMSEwHwYJKoZIhvcNAQkB
FhJkY2hpZXNhQGdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQCui4gANqXpDWXcjlF8Fo0u29vzbr4OObhSt8jmOk7ngrqPcay8JExinP75
JDjmw/fWAWmXeO8FXJDzcOVRNazJvXOmN+0sscrTg0l4VrBLU1u2P7ZXnq3tluXV
vItuvxHDVzwg7TiiqfJytwBTfcoR0Xm+W4K+DyqlUInP4BXVlU0taIt+XIJWwXVF
iVL859dXF4pBMTqTdQ8OSD/lQ6FlhnVb3orInA0ziWvOIaoFYkiXp1piwm5Pfhni
I5NWwMc8T3J5cWxp+11o8t7Rq6CToH/nB7UJtB6KOE9SZyfOZ/oCsAaa3Cig8uOj
AWPA6/UdLuwbrs4O/Nljv3WFxsTFAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBACk3
S+pkfeIy18xsfBhrjDcnOlstDRgqBJmUk3cwWu7ElGYK1+49qg0JJVJIsu3Yw3og
NV34yJlmqFILMnGJ9sxBiVVEBkHJqjaFpkgyJhNgWrde2A3EwnAfK+M2TM6RpGh0
NUE0Sy2OxHarM0uwVxDBWIoQZHFA4OAm2DK9WyI7Xv9HwXYk8DktaKS7UbsMa1gR
pn/b+D8wKmJheAM8eqLp+6JDZ8SdKBXcWmPjM++erhgaiFoAF6zAhel2NzaimTZn
VMAOl7Bmm7fSlbXwpfKsGqrlNgRICHwngJCHtcHxudg05ON3JT2BgtVjk4c4Nk7P
nydfuqjt70aZeL9/tJ0=
-----END CERTIFICATE-----

To verify a JWT using something like that, you should be able to do this:

<VerifyJWT name='VerifyJWT-2'>
  <Algorithm>RS256</Algorithm>
  <Source>inbound_jwt</Source>
  <PublicKey>
    <Certificate ref='cert_pem'/> <!-- NOTE -->
  </PublicKey>
</VerifyJWT>

That Certificate element is a newer policy configuration option. It allows you to specify a context variable containing the PEM-encoded certificate, as shown above.

If validation fails when you try to save a policy that uses the Certificate element, then you can try this:

<VerifyJWT name='VerifyJWT-3'>
  <Algorithm>RS256</Algorithm>
  <Source>inbound_jwt</Source>
  <PublicKey>
    <Value ref='cert_pem'/>
  </PublicKey>
</VerifyJWT>

If the thing you specify to the Value element is a public key, then the VerifyJWT policy will deserialize the public key directly. If the thing you specify to the Value element is a certificate, then the VerifyJWT policy will deserialize the public key indirectly, by extracting it from the certificate. In either case VerifyJWT will verify the signature on the inbound jwt using that public key.

Keep in mind: the VerifyJWT policy currently does not verify the signature on the certificate, nor does it check the valid dates on that certificate. It simply extracts the public key and uses it.

If you have further questions, let me know.

Hi.. Thank you so much for the answer.. yes.. i want to verify the token.. And i tried <Certificateref='cert_pem'/> , but its throwing error. So i used <PublicKey><Valueref='cert_pem'/></PublicKey> But still its not validating. Its throwing error as InvalidToken. 😞

"Invalid Token" is probably an indication that:

  • the policy extracted the Public key from the certificate
  • the policy tried to verify the signature using that public key, and also checked the validation times (nbf and exp); and something in that check, failed.

If the policy was unable to extract the public key you would see a different error.

So please check that:

  • your cert is the correct certificate and the public key extracted from it, matches the private key that was used to sign the JWT
  • The JWT is not expired. The not-before claim is valid too.
  • The JWT uses the algorithm you specified (RS256 or PS256 or etc)
  • The other claims you may be verifying are correct