JWT validation error - "cannot instantiate public key"

Recently I've started to get JWT validation error. JWT public key is stored as developer attribute.

This was working for a while. What happened to Apigee JWT validation?

,

Recently I've started to get an error while validation JWT token. Public key is stored as developer property. It was working for a while. What happened to Apigee JWT validation?

1 3 1,559
3 REPLIES 3

I'm sorry for the difficulty and the problems you're experiencing. There have been changes to how keys get deserialized. You may be able to solve this problem on your own.

The public key is not a secret. Can you share it here, in its exact format?

The correct format looks like this;

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq/c4uCIU3UVFy7ezonkJ
WVp2HkyZutia5Vg3T6lnWMySLeux34pWEiQdnNomWJvxY1wUc3PDUD8m4dF86Lvd
Vr9dXisYtWpoaxy+nLGWmkSXv3pv77OfpEmaESbDEN4NlrQQsqnHH21fr8IQGp1e
IetYOcUkBl97QXETV7fS5gSM2PuqMh7PNKeQot9LAf+0ANLzpCXa7Tx26TXoib2C
RG5wD2+JDp3wlQtDTmNaHDgz7GDB1HsLYLY+JEFEi0hPY0zzUwxoH8UTlQmHHHWy
5ewmAAQZ3yasIG0csDM38nKSHcZJMorg3tcJzO/7RS+a/sU8oEJWLkUcGawM33cc
CQIDAQAB
-----END PUBLIC KEY-----

The older version of the JWT policy was pretty lenient about de-serializing keys. You could post your key like this:

 -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq/c4uCIU3UVFy7ezonkJ WVp2HkyZutia5Vg3T6lnWMySLeux34pWEiQdnNomWJvxY1wUc3PDUD8m4dF86Lvd Vr9dXisYtWpoaxy+nLGWmkSXv3pv77OfpEmaESbDEN4NlrQQsqnHH21fr8IQGp1e IetYOcUkBl97QXETV7fS5gSM2PuqMh7PNKeQot9LAf+0ANLzpCXa7Tx26TXoib2C RG5wD2+JDp3wlQtDTmNaHDgz7GDB1HsLYLY+JEFEi0hPY0zzUwxoH8UTlQmHHHWy 5ewmAAQZ3yasIG0csDM38nKSHcZJMorg3tcJzO/7RS+a/sU8oEJWLkUcGawM33cc CQIDAQAB -----END PUBLIC KEY-----

(with all newlines replaced by spaces) ... and the OLD policy would successfully deserialize the key.

But the relevant specification says that

  • the header and footer should be on separate lines
  • the base64-encoded data portion should consist of lines of text no more than 64 characters in length.

The newer policy expects things to be formatted as the specification describes.

We're aware of some of the problems de-serializing keys formatted with "non-standard" PEM encoding. We're trying to fix the problems. (The real bug is actually that the OLDER implementation of the policy was much too lenient, but I understand you have working proxies now and expect them to continue to work)

You can solve the problem with the new policy, yourself, by examining and possibly modifying the format of the PEM.

Be careful in ensuring that newlines are encoded properly into the PEM text. If you use the UI to paste in the PEM text, you may not be transferring the newlines as intended. (If this is happening, then it is a bug in the UI). In that case, try using the administrative API to upload your PEM file as an attribute. Keep in mind the UI may not display newlines even if they are present.

If you need specific assistance using the API, let me know.

I'm sorry for the difficulty and the problems you're experiencing. We're working to make the current policy as lenient as the old. In the meantime, you may be able to help yourself.

This post definitely saved us some valuable time during our production OPDK upgrade from 19.01 to 4.50 BUT JWT policy validation still DOES NOT adhere to specifications format which basically led to PoP Token validation failures in the middle of our upgrade process during the RMP upgrade phase.

This key was working before the upgrade:

-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq/c4uCIU3UVFy7ezonkJ\n
WVp2HkyZutia5Vg3T6lnWMySLeux34pWEiQdnNomWJvxY1wUc3PDUD8m4dF86Lvd\n
Vr9dXisYtWpoaxy+nLGWmkSXv3pv77OfpEmaESbDEN4NlrQQsqnHH21fr8IQGp1e\n
IetYOcUkBl97QXETV7fS5gSM2PuqMh7PNKeQot9LAf+0ANLzpCXa7Tx26TXoib2C\n
RG5wD2+JDp3wlQtDTmNaHDgz7GDB1HsLYLY+JEFEi0hPY0zzUwxoH8UTlQmHHHWy\n
5ewmAAQZ3yasIG0csDM38nKSHcZJMorg3tcJzO/7RS+a/sU8oEJWLkUcGawM33cc\n
CQIDAQAB-----END PUBLIC KEY-----

But after the upgrade we started getting the following error -- "cannot instantiate public key"

The fix was to add the \n delimiter after the header and before the footer.

-----BEGIN PUBLIC KEY-----\n
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq/c4uCIU3UVFy7ezonkJ\n
WVp2HkyZutia5Vg3T6lnWMySLeux34pWEiQdnNomWJvxY1wUc3PDUD8m4dF86Lvd\n
Vr9dXisYtWpoaxy+nLGWmkSXv3pv77OfpEmaESbDEN4NlrQQsqnHH21fr8IQGp1e\n
IetYOcUkBl97QXETV7fS5gSM2PuqMh7PNKeQot9LAf+0ANLzpCXa7Tx26TXoib2C\n
RG5wD2+JDp3wlQtDTmNaHDgz7GDB1HsLYLY+JEFEi0hPY0zzUwxoH8UTlQmHHHWy\n
5ewmAAQZ3yasIG0csDM38nKSHcZJMorg3tcJzO/7RS+a/sU8oEJWLkUcGawM33cc\n
CQIDAQAB\n
-----END PUBLIC KEY-----

We found that the following, with the public key in a single line without spaces or any delimiters, also works:

-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq/c4uCIU3UVFy7ezonkJWVp2HkyZutia5Vg3T6lnWMySLeux34pWEiQdnNomWJvxY1wUc3PDUD8m4dF86LvdVr9dXisYtWpoaxy+nLGWmkSXv3pv77OfpEmaESbDEN4NlrQQsqnHH21fr8IQGp1eIetYOcUkBl97QXETV7fS5gSM2PuqMh7PNKeQot9LAf+0ANLzpCXa7Tx26TXoib2CRG5wD2+JDp3wlQtDTmNaHDgz7GDB1HsLYLY+JEFEi0hPY0zzUwxoH8UTlQmHHHWy5ewmAAQZ3yasIG0csDM38nKSHcZJMorg3tcJzO/7RS+a/sU8oEJWLkUcGawM33ccCQIDAQAB-----END PUBLIC KEY-----

Mudit, thanks for that comment.

Yes, we changed the logic for reading the Public Key to be more strict. That has caused some policies to stop working.

The correct format is

HEADER (newline)
(many lines of base64-encoded data, max 64 characters)
FOOTER (newline)

In other words, when you changed your PEM format,.... you converted it to a legal, valid form. Previously the JWT policy read invalid forms. But now that's no longer the case.

The form in which you have the header, followed by no newline, all the base64 data, and then again no newline followed by the footer.... is also invalid. the JWT policy tries really hard to handle invalid forms, and sometimes it succeeds. Better to use the regular PEM formatting.

  1. Header on its own line.
  2. base64 data in successive lines, each limited to 64 chars
  3. footer on its own line.

Just to be completely clear, the \n in your text is not explicitly required. It's intended to indicate where the newlines are. The actual text for a public key should look like this:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA15PZNNSa4RkH9eAeJ8ph
57WhvUmANpBEDqP0SuHzNl3HmxbEiUPBoBNQAtRpVlOWM0t+FltMORjGXtntjSBs
/8do3kaPbKN4Ua0O/wRpe15wHnRBNT+V5qonUDy0R+gfBqBpMNVIn2b1x5EWih10
sMCU+rjnUvBYtCGHmbQlUcZOZbXLSWfV3ukoRaGG2KV9V2zNXWjTZiKSFRFJZSeW
4sT+s9twcmx+QF60xkpqe4/DvrqanKb3bKGQoViC0wl67vzv+QfaLtku/WAsBeLm
I3DFmXb0ny3uCUCfCRtHnpAU0gfjWBiwkZ/R2OhZOW877GGcNMKVTnFT6911gGMi
SwIDAQAB
-----END PUBLIC KEY-----

That thing needs to be, either explicitly in the JWT policy, or in the KVM (WITH THE NEWLINES), or in an AssignMessage policy (WITH THE NEWLINES0), or in some other place where you store non-secrets.