Policy Error While referencing Public key Value In Verify JWT Policy

Hello ,

We are trying to Validate External JWT Token using below configuration in the Verify JWT Policy .

<PublicKey>

<Certificate ref="public.cert"/>

</PublicKey> .

Where we have stored the certificate in public.cert variable .

var x5c = MIIDBTCCAe2gAwIBAgIQdRnV9VlJ0JZDXnbfp+XqZjANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE5MDcxNTAwMDAwMFoXDTIxMDcxNTAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOvLcdnJzn5Lx3+9OXPmSGX14ssROnPS6sVUA4yLPvQ27wxCO+Od5GYvbb0GM7JCRXQZQ/DGLlYV/AaYv2FBRfHqCdTxQtv/NrA4RfpjSe7D62LIDCQC9638zikGqcd5vUT0vtfCgGToPkiA8GzXKw5ua2MOaF4to2zuHLSs0Sj94857xw3i5ywk3JwxpDAkQbhDSboMIe6B47RqYdS97zaSNpa6Adxytk3A9TK+XGE3K3fo+m5pPC0XsCwiY4qWcJrtw4luP5EZ4oMPDuQZmIDGJFmexpdOPCgWS/uz8h0wF2+7TKfRXSX1mPl7vSgfWsgFvOBmwjCe6qKI8KAg290CAwEAAaMhMB8wHQYDVR0OBBYEFCle84Tr3/8aZbTs2jryx2w21ANZMA0GCSqGSIb3DQEBCwUAA4IBAQAZsQq6JX4IFDXjfV9UnauPP2E5OUMQvqnNasAATucYctaeW307aQEhB4OQgFDKKUpcN4RHOLqxG4phqUhI72PzW8kNVjGvgSL+uXO7P0mYi0N+ujGXYi92ZzH9tODODQ2147ZDLDe0kiRB9KXwFLdJcY6dbkj0wVmIy4D5JtB9zTRj4R5ymWXCXz3ecN4DhjeZnjnZfxaqJJA6lbWLIcjenKjRXoW95WgtdSu2gpjaJCt4zITTw1cFL6sdHrcsT24j23EpNxUld8C/3IY8ac72HKMR5AloTRlXxwXM8XUwLcrUCVp0c61VNY6U2J0TXYdSvJHwSQ98wSbiSryT2SUk

context.setVariable("public.cert", "-----BEGIN Certificate-----" + x5c + "-----END Certificate-----");

With this approach it results in failure with message
" Invalid Key configuration : policy(VerifyJWTToken)." .


We tried another approach using below configuration .

<PublicKey> <Value ref="public.publickey"/> </PublicKey>

var x5c = MIIDBTCCAe2gAwIBAgIQdRnV9VlJ0JZDXnbfp+XqZjANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE5MDcxNTAwMDAwMFoXDTIxMDcxNTAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOvLcdnJzn5Lx3+9OXPmSGX14ssROnPS6sVUA4yLPvQ27wxCO+Od5GYvbb0GM7JCRXQZQ/DGLlYV/AaYv2FBRfHqCdTxQtv/NrA4RfpjSe7D62LIDCQC9638zikGqcd5vUT0vtfCgGToPkiA8GzXKw5ua2MOaF4to2zuHLSs0Sj94857xw3i5ywk3JwxpDAkQbhDSboMIe6B47RqYdS97zaSNpa6Adxytk3A9TK+XGE3K3fo+m5pPC0XsCwiY4qWcJrtw4luP5EZ4oMPDuQZmIDGJFmexpdOPCgWS/uz8h0wF2+7TKfRXSX1mPl7vSgfWsgFvOBmwjCe6qKI8KAg290CAwEAAaMhMB8wHQYDVR0OBBYEFCle84Tr3/8aZbTs2jryx2w21ANZMA0GCSqGSIb3DQEBCwUAA4IBAQAZsQq6JX4IFDXjfV9UnauPP2E5OUMQvqnNasAATucYctaeW307aQEhB4OQgFDKKUpcN4RHOLqxG4phqUhI72PzW8kNVjGvgSL+uXO7P0mYi0N+ujGXYi92ZzH9tODODQ2147ZDLDe0kiRB9KXwFLdJcY6dbkj0wVmIy4D5JtB9zTRj4R5ymWXCXz3ecN4DhjeZnjnZfxaqJJA6lbWLIcjenKjRXoW95WgtdSu2gpjaJCt4zITTw1cFL6sdHrcsT24j23EpNxUld8C/3IY8ac72HKMR5AloTRlXxwXM8XUwLcrUCVp0c61VNY6U2J0TXYdSvJHwSQ98wSbiSryT2SUk

context.setVariable("public.publickey", "-----BEGIN PUBLIC KEY-----" + x5c + "-----END PUBLIC KEY-----");


This Approach helps in saving the configurations in api , but however at run time we get " Invalid Public key" though we are passing the correct one provided the token provider .

Could you please help us in knowing why the first approach fails with Ïnvalid Key Configuration

and are we doing anything wrong while following the second approach with reference to how we are storing the value of public.publickey .

.



Solved Solved
0 8 649
1 ACCEPTED SOLUTION

Check the documentation on the VerifyJWT policy . Thats not a valid public key format. The public key format you want is something like this:

-----BEGIN PUBLIC KEY-----
MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBjcY6JpyoqzANrbflf8EBL
HG6PBsxjBwl22YZgCrMiWyexjh3G7Rx+VPNFdDhpCuedYmYswO7JWLoVUxSTfshy
BFnxC2AxA3pmp5xfP/j4tdQEWZSD1P66seAejCfz3yUGlP4ZO7CAumTy5qIHMGZl
p/mU9yoGdHXZleukBvYKhtrOLpPDPFQwekBzwTYRNIpCyZC9Ot9hFW1/xHVo5/Rj
ebhylaFZZUF4ViTMq92cx51DTjB7mFBSykIYgOhxR456nEjopwRIQ2j8hAlUBF2t
tAgNGgVh82SMYAHI5LG5hbzSUt8UPMkrSUOdtxW+tP/O940Wx/IL/sm/GdncBBNP
AgMBAAE=
-----END PUBLIC KEY-----

The format is formally specified in RFC 7468.

Your code is like this:

var x5c = "MIIDBTCCAe2gAwIBAgIQdRnV9VlJ0JZDXnbfp+XqZjANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE5MDcxNTAwMDAwMFoXDTIxMDcxNTAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOvLcdnJzn5Lx3+9OXPmSGX14ssROnPS6sVUA4yLPvQ27wxCO+Od5GYvbb0GM7JCRXQZQ/DGLlYV/AaYv2FBRfHqCdTxQtv/NrA4RfpjSe7D62LIDCQC9638zikGqcd5vUT0vtfCgGToPkiA8GzXKw5ua2MOaF4to2zuHLSs0Sj94857xw3i5ywk3JwxpDAkQbhDSboMIe6B47RqYdS97zaSNpa6Adxytk3A9TK+XGE3K3fo+m5pPC0XsCwiY4qWcJrtw4luP5EZ4oMPDuQZmIDGJFmexpdOPCgWS/uz8h0wF2+7TKfRXSX1mPl7vSgfWsgFvOBmwjCe6qKI8KAg290CAwEAAaMhMB8wHQYDVR0OBBYEFCle84Tr3/8aZbTs2jryx2w21ANZMA0GCSqGSIb3DQEBCwUAA4IBAQAZsQq6JX4IFDXjfV9UnauPP2E5OUMQvqnNasAATucYctaeW307aQEhB4OQgFDKKUpcN4RHOLqxG4phqUhI72PzW8kNVjGvgSL+uXO7P0mYi0N+ujGXYi92ZzH9tODODQ2147ZDLDe0kiRB9KXwFLdJcY6dbkj0wVmIy4D5JtB9zTRj4R5ymWXCXz3ecN4DhjeZnjnZfxaqJJA6lbWLIcjenKjRXoW95WgtdSu2gpjaJCt4zITTw1cFL6sdHrcsT24j23EpNxUld8C/3IY8ac72HKMR5AloTRlXxwXM8XUwLcrUCVp0c61VNY6U2J0TXYdSvJHwSQ98wSbiSryT2SUk";
context.setVariable("public.publickey", "-----BEGIN PUBLIC KEY-----" + x5c + "-----END PUBLIC KEY-----");

And you said,

This Approach helps in saving the configurations in api , but however at run time we get " Invalid Public key" though we are passing the correct one provided the token provider .

But the result of that code has zero newlines and not even a whitespace between the begin line and the encoded data. That's not gonna work. It does not comply with RFC 7468.

I suppose you could add a little more logic into your JS to split it up nicely. Add the newlines - RFC 7468 says:

  • you should use no more than 64 characters on each of the encoded data lines.
  • the BEGIN line should end in end-of-line (that's why they call it a line)
  • likewise the END line

You should be able to achieve what you want with more smarts in the JS.

But there's one more twist. A Certificate is not a public key. If the data you have in x5c is the encoded Certificate data, then you need to bracket it with "BEGIN CERTIFICATE" and "END CERTIFICATE" and not "BEGIN PUBLIC KEY" and "END PUBLIC KEY". The two things are not the same. So you probably want to change that in your JS also.

Finally, I think hardcoding your x5c into the JS is a weird thing to do. If the JWT issuer publishes its public key, it's usually done in a JWKS. And the VerifyJWT policy accepts a JWKS URI. You can just specify it like.

<PublicKey> 
  <JWKS uri='https://my.jwks.endpoint/jwks.json'/>
</PublicKey>

And then you don't need to perform surgery in JS on the textual representation of the public key or certificate. If you don't have a URI, but you receive the JWKS in some other way, then you can do it this way:

<PublicKey> 
  <JWKS ref='variable.containing.jwks.content'/>
</PublicKey>

It's possible the x5c is coming from the JWT itself, which is fine, and in which case I suppose you need to do what you're doing.

View solution in original post

8 REPLIES 8

What is the reason of use Javascript here?

Did you try KVM(encrypted) to store the key and retrieving it at the proxy level using KVM policy?

Hi Siddharth ,

As I mentioned earlier we are verifying the external JWT token , so I am getting the public key i.e certificate by making call to client that has provided us x5c in the response as shown below .

Hence I am extracting this value and setting in the variable to reference it in the Verify JWT policy .



{ "keys": [{ "kty": "RSA", "use": "sig", "kid": "ie_qWCXhXxt1zIEsu4c7acQVGn4", "x5t": "ie_qWCXhXxt1zIEsu4c7acQVGn4", "n": "68tx2cnOfkvHf705c-ZIZfXiyxE6c9LqxVQDjIs-9DbvDEI7453kZi9tvQYzskJFdBlD8MYuVhX8Bpi_YUFF8eoJ1PFC2_82sDhF-mNJ7sPrYsgMJAL3rfzOKQapx3m9RPS-18KAZOg-SIDwbNcrDm5rYw5oXi2jbO4ctKzRKP3jznvHDeLnLCTcnDGkMCRBuENJugwh7oHjtGph1L3vNpI2lroB3HK2TcD1Mr5cYTcrd-j6bmk8LRewLCJjipZwmu3DiW4_kRnigw8O5BmYgMYkWZ7Gl048KBZL-7PyHTAXb7tMp9FdJfWY-Xu9KB9ayAW84GbCMJ7qoojwoCDb3Q", "e": "AQAB", "x5c": ["MIIDBTCCAe2gAwIBAgIQdRnV9VlJ0JZDXnbfp+XqZjANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE5MDcxNTAwMDAwMFoXDTIxMDcxNTAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOvLcdnJzn5Lx3+9OXPmSGX14ssROnPS6sVUA4yLPvQ27wxCO+Od5GYvbb0GM7JCRXQZQ/DGLlYV/AaYv2FBRfHqCdTxQtv/NrA4RfpjSe7D62LIDCQC9638zikGqcd5vUT0vtfCgGToPkiA8GzXKw5ua2MOaF4to2zuHLSs0Sj94857xw3i5ywk3JwxpDAkQbhDSboMIe6B47RqYdS97zaSNpa6Adxytk3A9TK+XGE3K3fo+m5pPC0XsCwiY4qWcJrtw4luP5EZ4oMPDuQZmIDGJFmexpdOPCgWS/uz8h0wF2+7TKfRXSX1mPl7vSgfWsgFvOBmwjCe6qKI8KAg290CAwEAAaMhMB8wHQYDVR0OBBYEFCle84Tr3/8aZbTs2jryx2w21ANZMA0GCSqGSIb3DQEBCwUAA4IBAQAZsQq6JX4IFDXjfV9UnauPP2E5OUMQvqnNasAATucYctaeW307aQEhB4OQgFDKKUpcN4RHOLqxG4phqUhI72PzW8kNVjGvgSL+uXO7P0mYi0N+ujGXYi92ZzH9tODODQ2147ZDLDe0kiRB9KXwFLdJcY6dbkj0wVmIy4D5JtB9zTRj4R5ymWXCXz3ecN4DhjeZnjnZfxaqJJA6lbWLIcjenKjRXoW95WgtdSu2gpjaJCt4zITTw1cFL6sdHrcsT24j23EpNxUld8C/3IY8ac72HKMR5AloTRlXxwXM8XUwLcrUCVp0c61VNY6U2J0TXYdSvJHwSQ98wSbiSryT2SUk"], "issuer": "https://host.com/d6d49420-f39b-4df7-a1dc-d59a935871db/v2.0" }] }

Regards,
Vaibhav

That payload is a JWKS. You can verify JWT with the VerifyJWT policy just by specifying the JWKS.

<PublicKey>
  <JWKS ref="variable.containing.jwks.payload"/>
</PublicKey> 

You do not need to perform surgery yourself on that payload.

Don't do that.

Hi Dino ,

Thanks for Quick turn around . We are able to verify by using JWKS ref variable .

Regards,
Vaibhav

Awesome! Glad to hear it.

Check the documentation on the VerifyJWT policy . Thats not a valid public key format. The public key format you want is something like this:

-----BEGIN PUBLIC KEY-----
MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBjcY6JpyoqzANrbflf8EBL
HG6PBsxjBwl22YZgCrMiWyexjh3G7Rx+VPNFdDhpCuedYmYswO7JWLoVUxSTfshy
BFnxC2AxA3pmp5xfP/j4tdQEWZSD1P66seAejCfz3yUGlP4ZO7CAumTy5qIHMGZl
p/mU9yoGdHXZleukBvYKhtrOLpPDPFQwekBzwTYRNIpCyZC9Ot9hFW1/xHVo5/Rj
ebhylaFZZUF4ViTMq92cx51DTjB7mFBSykIYgOhxR456nEjopwRIQ2j8hAlUBF2t
tAgNGgVh82SMYAHI5LG5hbzSUt8UPMkrSUOdtxW+tP/O940Wx/IL/sm/GdncBBNP
AgMBAAE=
-----END PUBLIC KEY-----

The format is formally specified in RFC 7468.

Your code is like this:

var x5c = "MIIDBTCCAe2gAwIBAgIQdRnV9VlJ0JZDXnbfp+XqZjANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE5MDcxNTAwMDAwMFoXDTIxMDcxNTAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOvLcdnJzn5Lx3+9OXPmSGX14ssROnPS6sVUA4yLPvQ27wxCO+Od5GYvbb0GM7JCRXQZQ/DGLlYV/AaYv2FBRfHqCdTxQtv/NrA4RfpjSe7D62LIDCQC9638zikGqcd5vUT0vtfCgGToPkiA8GzXKw5ua2MOaF4to2zuHLSs0Sj94857xw3i5ywk3JwxpDAkQbhDSboMIe6B47RqYdS97zaSNpa6Adxytk3A9TK+XGE3K3fo+m5pPC0XsCwiY4qWcJrtw4luP5EZ4oMPDuQZmIDGJFmexpdOPCgWS/uz8h0wF2+7TKfRXSX1mPl7vSgfWsgFvOBmwjCe6qKI8KAg290CAwEAAaMhMB8wHQYDVR0OBBYEFCle84Tr3/8aZbTs2jryx2w21ANZMA0GCSqGSIb3DQEBCwUAA4IBAQAZsQq6JX4IFDXjfV9UnauPP2E5OUMQvqnNasAATucYctaeW307aQEhB4OQgFDKKUpcN4RHOLqxG4phqUhI72PzW8kNVjGvgSL+uXO7P0mYi0N+ujGXYi92ZzH9tODODQ2147ZDLDe0kiRB9KXwFLdJcY6dbkj0wVmIy4D5JtB9zTRj4R5ymWXCXz3ecN4DhjeZnjnZfxaqJJA6lbWLIcjenKjRXoW95WgtdSu2gpjaJCt4zITTw1cFL6sdHrcsT24j23EpNxUld8C/3IY8ac72HKMR5AloTRlXxwXM8XUwLcrUCVp0c61VNY6U2J0TXYdSvJHwSQ98wSbiSryT2SUk";
context.setVariable("public.publickey", "-----BEGIN PUBLIC KEY-----" + x5c + "-----END PUBLIC KEY-----");

And you said,

This Approach helps in saving the configurations in api , but however at run time we get " Invalid Public key" though we are passing the correct one provided the token provider .

But the result of that code has zero newlines and not even a whitespace between the begin line and the encoded data. That's not gonna work. It does not comply with RFC 7468.

I suppose you could add a little more logic into your JS to split it up nicely. Add the newlines - RFC 7468 says:

  • you should use no more than 64 characters on each of the encoded data lines.
  • the BEGIN line should end in end-of-line (that's why they call it a line)
  • likewise the END line

You should be able to achieve what you want with more smarts in the JS.

But there's one more twist. A Certificate is not a public key. If the data you have in x5c is the encoded Certificate data, then you need to bracket it with "BEGIN CERTIFICATE" and "END CERTIFICATE" and not "BEGIN PUBLIC KEY" and "END PUBLIC KEY". The two things are not the same. So you probably want to change that in your JS also.

Finally, I think hardcoding your x5c into the JS is a weird thing to do. If the JWT issuer publishes its public key, it's usually done in a JWKS. And the VerifyJWT policy accepts a JWKS URI. You can just specify it like.

<PublicKey> 
  <JWKS uri='https://my.jwks.endpoint/jwks.json'/>
</PublicKey>

And then you don't need to perform surgery in JS on the textual representation of the public key or certificate. If you don't have a URI, but you receive the JWKS in some other way, then you can do it this way:

<PublicKey> 
  <JWKS ref='variable.containing.jwks.content'/>
</PublicKey>

It's possible the x5c is coming from the JWT itself, which is fine, and in which case I suppose you need to do what you're doing.

Hi Dino ,


Thanks for Inputs .

<PublicKey><JWKSref='variable.containing.jwks.content'/></PublicKey> this approach of verifying worked .

However , we also tried below approach, though not sure whether it's correct or good approach .


<PublicKey><Value ref='cert'/></PublicKey>

where cert was set as below .
x5c = extracted from JWKS
context.setVariable("cert", "----BEGIN CERTIFICATE----"+ x5c +"---END CERTIFICATE---");

and it worked even though below guidelines were not followed .

  • you should use no more than 64 characters on each of the encoded data lines.
  • the BEGIN line should end in end-of-line (that's why they call it a line)
  • likewise the END line

Regards,
Vaibhav

I'm glad it worked for you.

The latter approach may work now, but it is not a RFC 7468-compliant format. It's not guaranteed to continue working forever.

The former approach is better.