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

Implementation of idempotency in apigeex

I have requirement where client is sending x-encryption-key in headers based on x-encryption-key I will have to implement Idempotency.Please guide me how to implement it. Is there any proxy in Github for reference @DChiesa Please suggest...

0 4 346
4 REPLIES 4

based on x-encryption-key I will have to implement Idempotency.

say more about this?  In the context of API requests, I understand idempotent to have the meaning provided in IETF RFC 9110: A request method is considered "idempotent" if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.

Apigee isn't the persistence layer in a typical API request.  (The obvious exception is when you configure your proxy to generate or invalidate an OAuth2 access token) .  In the typical case, the upstream system is storing or retrieving data.  THAT is the system that implements idempotency, or not.   Not Apigee.

But maybe you are referring to something else. Please elaborate.

Hi @dino,

We have asymmetric(RSA+AES) encryption/decryption implemented at apigee.X-encryption key will have AES key encrypted with RSA Public key. We will decrypt AES key using RSA private key and use this AES key for payload decryption. Right now If we have created one x-encryption-key and encrypted payload using AES key it will allow all requests using same AES key to restrict using same x-encryption-key we will have implement idempotency using x-encryption-key.It should be allowed only once not all the times to prevent replay attacks. Can you please suggest us how we can achieve this. 

 

 

 

 


@Madhavikrishna wrote:

We have asymmetric(RSA+AES) encryption/decryption implemented at apigee


ok got it.  That's a a common pattern -  RSA encryption WRAPS an AES encryption. This is because there's a limited payload size with RSA crypto, whereas there is no such limit with AES, which is a block cipher.  the size limit with RSA is enough to encrypt a symmetric key.  so the typical pattern is: Use RSA crypto to encrypt a generated symmetric key, then use the generated symmetric key to encrypt many blocks of a large payload.  Then transmit both the AEs-encrypted payload, along with the RSA-encrypted symmetric key.  

And the receiver just needs the RSA private key to RSA- decrypt the symmetric key, and then can use that symmetric key to AES-decrypt the payload.   Is that what you're doing? 


@Madhavikrishna wrote:

Right now If we have created one x-encryption-key and encrypted payload using AES key it will allow all requests using same AES key to restrict using same x-encryption-key we will have implement idempotency using x-encryption-key.It should be allowed only once not all the times to prevent replay attacks. Can you please suggest us how we can achieve this. 


Yes - well, I have some suggestions. One is to use the JWT standard. Many people understand JWT to always involve digital signatures. But JWT is not limited to signatures. In fact there is an encrypted variant of JWT, and it supports RSA+AES crypto, just in the way you described.  By generating an encrypted JWT using an RSA crypto, you will generate a random AES key, use the RSA public key to encrypt that, and then use the AES key to encrypt the JWT payload. and then wrap up the encrypted AES key and the encrypted payload as one unit. 

This screencast covers all of JWT: https://youtu.be/9Vl8gM5XPLk

This one talks about encrypted JWT in Apigee: https://youtu.be/uWsQkN1fY7Y

Why use JWT? Well part of the standard includes an expiration claim. Which means you can stipulate that app clients must generate a JWT and send their payload using that form, and encoded into the JWT would be an expiry of .... 15 seconds, or 30 seconds, or whatever you like. The VerifyJWT policy in Apigee will enforce the JWT expiration automatically, and can also enforce the "maximum lifetime", which is the difference between issue time and expiry time.  this combination of enforcements will effectively mitigate replay attacks in most cases. It's not a strict guarantee that the AES key used is unique, but ... it shrinks the window of potential re-use to an interval that works for you.  As I said, 15 seconds, 30 seconds, etc . 

If you re-work your protocol to require encrypted JWT, then your client applications will need to generate the encrypted JWT. Most JWT libraries and tools that support encrypted JWT  , will generate a random AES key, each time a new JWT is generated. In fact I don't know of one that does not behave this way. So typically you will get distinct keys , for each payload, from bonafide (not malicious) clients.

Malicious clients, I suppose, could try to contrive an encrypted JWT payload using a re-used AES key.  You could configure your Apigee proxy to inspect the AES key, and store the hash in some persistent store, and then reject future uses of that same key.  The builtin VerifyJWT policy does not perform this check automatically, but you could add it by populating the Apigee cache with the hash of the AES key, and then checking the cache with each new JWT that is sent in. You'd set the cache TTL  to ... 5 minutes or 30 minutes... whatever time frame you would like to use, to enforce uniqueness of AES keys.  If for some reason you did not want to use the built-in Apigee cache to store AES keys, then you could rely on some other external store - an external database, or an external redis, or ... something else that would track key usage. 

OK, now stepping back - you could do the same thing with checking the AES keys in the Apigee cache , if you are NOT using encrypted JWT.  

The reason you'd want to use encrypted JWT, rather than "rolling your own" crypto, is that the encrypted JWT standard has been tightly reviewed and approved as secure, w.r.t. padding, key generation and transmission, initialization vectors, AES modes, key wrapping, and all the other details that seem esoteric but which can have significant impact on the inherent integrity of the encryption system if not handled properly. 

 

why not cache the header `x-encryption-key` and every time the client makes a request based on that header you don't make an affect because the client already called you and you did the change the first time. @Madhavikrishna