Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Use public key in flow variable to VerifyJWT policy

We are trying to use a flow variable containing the public key to use in JWTVerify policy.

We use the Cloud Code extension in VS Code.  When deploying to the emulator we get this error:

03/12/2025 11:45 AM EMULATOR INFO Deploying environment local, to Container apigee-emulator (1.9.2)
03/12/2025 11:45 AM EMULATOR ERROR Code   : messaging.config.validation.ValidatorFailed
03/12/2025 11:45 AM EMULATOR ERROR Message: Bean validator failed with error null
03/12/2025 11:45 AM EMULATOR ERROR File   : c:\Users\xxxxxx\Source\apigee-platform\src\main\apigee\apiproxies\TokenTest-V1\apiproxy\policies\JWT-Verify.xml:2:30
03/12/2025 11:45 AM EMULATOR ERROR Environment local deployment, to Container apigee-emulator (1.9.2) failed with Error: 400
03/12/2025 11:45 AM EMULATOR ERROR Deploy to Container apigee-emulator (1.9.2), failed with Error: Environment local deployment, to Container apigee-emulator (1.9.2) failed with Error: 400

AssignMessage...

    <AssignVariable>
        <Name>auth.jwt.cert</Name>
        <Value>
-----BEGIN CERTIFICATE-----
cert goes here
-----END CERTIFICATE-----
        </Value>
    </AssignVariable>
 
VerifyJWT policy 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VerifyJWT name="JWT-Verify">
    <Algorithm>RS256</Algorithm>  <!-- Algorithm from JWT Header -->
    <Source>request.header.authorization</Source>  <!-- JWT from Authorization Header -->

    <!-- Provide the public key to verify the signature -->
    <PublicKey>
        <Certificate ref="auth.jwt.cert"/>
    </PublicKey>

    <Issuer>xxxxx</Issuer>

</VerifyJWT>
Solved Solved
1 1 113
1 ACCEPTED SOLUTION

Hmm, that is a discouraging situation.

The Bean Validator is saying "failed with error null". An unhelpful error message like that is a bug in the Validator. If it's going to fail, then it should tell you why it's failing. Secondly: The policy configuration is valid. So it shouldn't be failing to validate anyway.

I looked into it further and filed a bug on your behalf; the internal reference is b/403014469 .

You won't be able to "see" anything with that reference, but if you opened a support ticket you would be able to give them that, and the support team could look it up for you and tell you the status. This is something that will be simple to fix, but... I don't know how long it would take to get a fix for you. If it's urgent, filing a support ticket and escalating might help.

The problem is the policy is incorrectly validating the ref attribute on the Certificate element.

 

<VerifyJWT name='VerifyJWT-101'>
  <Source>variable-name-here</Source>
  <Algorithm>PS256</Algorithm>
  <PublicKey>
    <Certificate ref='some-variable'/> <!-- this -->
  </PublicKey>
  <Issuer>xxxxx</Issuer>
</VerifyJWT>

 

The Validator is saying that's not valid, when it actually is valid.

There are some workarounds available for you...

  1. "hard-code" the Certificate right in the policy, OR,
  2. do not use a Certificate. Use a PEM-encoded public key, eg

      <PublicKey>
        <Value ref='some-variable'/>
      </PublicKey>
      ...
    

    This assumes you can modify your proxy to use an encoded public key, and not an encoded certificate. (I mean your variable should hold -----BEGIN PUBLIC KEY----- ....)

  3. Lastly, ... you may be able to get your configuration to work by just replacing the Element named Certificate in your policy, with the name Value. In other words, use the configuration I just showed above, but DO NOT change the proxy to use an encoded public key. I believe the PublicKey/Value element ... can actually tolerate a Certificate. This is not documented, and it may "go away" at some point. But I believe the behavior of the policy at runtime is to first try to de-serialize a PublicKey from the ref, and then if that fails, try to de-serialize the referenced variable as an X509 Certificate. This will be confusing to anyone who examines the policy, and so in my opinion, it's not great to do, but if it still behaves that way, it will be sort of an easy back-door to getting where you want to go.

Something to keep in mind if you use a Cert as the source of the public key: the policy, currently, does not check for validity of the cert. It does not check the expiry date, nor does it check whether the cert is trusted by looking through the TrustStore. So effectively you are not getting much out of using a Cert as the source for the public key. It's just a different packaging. I have filed a separate enhancement request to validate the cert against a Truststore. Internal reference: b/403033358 .

Oh, and one other thing - the Source Element. If you specify request.header.authorization for the Source, then the policy will not look for a Bearer prefix in the header. So it will probably fail at runtime. The Source for the policy is implicitly the Authorization header, but when you do not specify the Source element, then it uses the Authorization header AND strips the Bearer prefix. If you just specify Source, it won't do the stripping.

So, omit the Source element if you expect the Authorization header to hold something of the form Bearer TOKEN_VALUE_HERE .

View solution in original post

1 REPLY 1

Hmm, that is a discouraging situation.

The Bean Validator is saying "failed with error null". An unhelpful error message like that is a bug in the Validator. If it's going to fail, then it should tell you why it's failing. Secondly: The policy configuration is valid. So it shouldn't be failing to validate anyway.

I looked into it further and filed a bug on your behalf; the internal reference is b/403014469 .

You won't be able to "see" anything with that reference, but if you opened a support ticket you would be able to give them that, and the support team could look it up for you and tell you the status. This is something that will be simple to fix, but... I don't know how long it would take to get a fix for you. If it's urgent, filing a support ticket and escalating might help.

The problem is the policy is incorrectly validating the ref attribute on the Certificate element.

 

<VerifyJWT name='VerifyJWT-101'>
  <Source>variable-name-here</Source>
  <Algorithm>PS256</Algorithm>
  <PublicKey>
    <Certificate ref='some-variable'/> <!-- this -->
  </PublicKey>
  <Issuer>xxxxx</Issuer>
</VerifyJWT>

 

The Validator is saying that's not valid, when it actually is valid.

There are some workarounds available for you...

  1. "hard-code" the Certificate right in the policy, OR,
  2. do not use a Certificate. Use a PEM-encoded public key, eg

      <PublicKey>
        <Value ref='some-variable'/>
      </PublicKey>
      ...
    

    This assumes you can modify your proxy to use an encoded public key, and not an encoded certificate. (I mean your variable should hold -----BEGIN PUBLIC KEY----- ....)

  3. Lastly, ... you may be able to get your configuration to work by just replacing the Element named Certificate in your policy, with the name Value. In other words, use the configuration I just showed above, but DO NOT change the proxy to use an encoded public key. I believe the PublicKey/Value element ... can actually tolerate a Certificate. This is not documented, and it may "go away" at some point. But I believe the behavior of the policy at runtime is to first try to de-serialize a PublicKey from the ref, and then if that fails, try to de-serialize the referenced variable as an X509 Certificate. This will be confusing to anyone who examines the policy, and so in my opinion, it's not great to do, but if it still behaves that way, it will be sort of an easy back-door to getting where you want to go.

Something to keep in mind if you use a Cert as the source of the public key: the policy, currently, does not check for validity of the cert. It does not check the expiry date, nor does it check whether the cert is trusted by looking through the TrustStore. So effectively you are not getting much out of using a Cert as the source for the public key. It's just a different packaging. I have filed a separate enhancement request to validate the cert against a Truststore. Internal reference: b/403033358 .

Oh, and one other thing - the Source Element. If you specify request.header.authorization for the Source, then the policy will not look for a Bearer prefix in the header. So it will probably fail at runtime. The Source for the policy is implicitly the Authorization header, but when you do not specify the Source element, then it uses the Authorization header AND strips the Bearer prefix. If you just specify Source, it won't do the stripping.

So, omit the Source element if you expect the Authorization header to hold something of the form Bearer TOKEN_VALUE_HERE .