How to use RSA key for generating and verifying JWT Token in assymetric way?

abhinabanag92
Participant III
  1. We are planning to Generate a public/private key pair. Expose the public key to business client while storing the private key in an encrypted KVM. Use the private key for generating JWT Token.
  2. Another public/private key pair will be generated for another api proxy, while verifying the JWT Token and calling end service of the business client.
  3. We will expose only the public keys over network during transaction.

Please suggest how to achieve it using RSA keys.

2 10 2,052
10 REPLIES 10

As for your first task:

Well it sounds like you know how to create keypairs for RSA. I use openssl, like this:

# To generate the key pair using the new format (PKCS#8), without encryption
openssl genpkey  -algorithm rsa -pkeyopt rsa_keygen_bits:2048 -out keypair.pem
# to extract the public key from the above
openssl pkey -pubout -inform PEM -outform PEM \
    -in keypair.pem \
    -out public-key.pem

That gives you two text files. keypair.pem looks like:

-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDG9e74AzhZPuHW
4JnRPlxgz2bjSyPtWFdRtyW+wyuEBYJjfUtdhZd0DR5Mq7QaIu58HoxSmX+WBZP3
...
J4jXK47ZcPoD+0gf4keo5CAgp8kKMkzJylWY0B2fMYOhVZ3tFiRsjb6mfTJLGg5x
T1lEQmNEw9YwhULrMlg8Ys9H
-----END PRIVATE KEY-----

and public-key.pem looks like:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxvXu+AM4WT7h1uCZ0T5c
YM9m40sj7VhXUbclvsMrhAWCY31LXYWXdA0eTKu0GiLufB6MUpl/lgWT9zFKXS7m
D0ABcu4Gs2nLqh/lytSphZOV4Hz9h/fyvtkrfkjsQu4aAAP7iWMju2HOsbQOXJdg
Tx/swvBOWD1qTexE3HTxl08z4bgmFsvf+vKbPrIi83iVcpVkpGYknciQiyeI1yuO
2XD6A/tIH+JHqOQgIKfJCjJMycpVmNAdnzGDoVWd7RYkbI2+pn0ySxoOcZGOuEL1
oFLqGg5/e6d2RGm8K+39M6diWQWitYVeH6mTKT6WiUcBQO8A9Lb0UY8zBN5k38DF
MQIDAQAB
-----END PUBLIC KEY-----

(Obviously the base64 characters there will vary when you generate your own keys)

It sounds like you also know how to load the private key into the KeyValue Map. You can do it with the Apigee UI, and just "paste" the text into the browser. You can also do it with the Admin API for Apigee. Whichever route you choose, keep the newlines! Use a known string for the "key" for the key-value-map, something like "rsa_private_key".

Then at runtime you need 2 policies:

  • KeyValueMapOperations to retrieve the private key from the encrypted KVM
  • GenerateJWT to generate the JWT.

Important: The KVM policy needs to populate a variable with the prefix "private." This is because you are using the encrypted kvm. So:

<KeyValueMapOperations name='KVM-GetKey' mapIdentifier='secrets'>
  <Scope>environment</Scope>
  <ExpiryTimeInSecs>300</ExpiryTimeInSecs>
  <Get assignTo='private.privatekey'>
    <Key>
      <Parameter>rsa_private_key</Parameter>
    </Key>
  </Get>
</KeyValueMapOperations>

Then the GenerateJWT policy:

<GenerateJWT name='GJWT-1'>
  <Algorithm>RS256</Algorithm>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <PrivateKey>
    <Value ref="private.privatekey"/>
  </PrivateKey>
  <Subject ref="jwt_subject" />
  <Issuer>My-apigee-proxy</Issuer>
  <Audience>audience-here</Audience>
  <ExpiresIn>30m</ExpiresIn>
  <OutputVariable>output_jwt</OutputVariable>
</GenerateJWT>

This latter policy references the variable "private.privatekey" which holds the contents of the "keypair.pem" thing you generated in the preparatory step. Please be aware: the "private." prefix means this variable will not be visible in the Trace UI !! You will not see it. If you trace this proxy, you will have to infer that the variable has been set correctly.

If you want to provide yourself a warm-and-fuzzy feeling, use a subsequent AssignMessage policy to assign the value of the private.privatekey variable to some other variable name, like "tmp". That assignment will appear in Trace.

If everything goes well, the result of the GenerateJWT will be an RSA-signed JWT placed into the variable "output_jwt". You will then need to embed this in the response message in some way, probably using an AssignMessage policy.

You will need to configure that GenerateJWT policy with the appropriate values for Subject, Issuer, Audience, etc. And make sure the expiry is set properly. and so on. Check the documentation for more details on that.


as for your second task:

Another public/private key pair will be generated for another api proxy, while verifying the JWT Token and calling end service of the business client.

I don't understand what you want here. But maybe you can figure it out yourself with what I've explained above.

I want to verify the JWT from the another proxy like Diffie-Hellman key exchange

and I am looking for how to achieve that in this scenario and not just generate JWT using RSA signing keys. Please guide.

I am new to Apigee . Please bare me with my questions .

How can we generate Key pair for Apigee Saas applications ?

We dont have our Apigee installed on any server. Where to run the openssl command ?

openssl is a command-line tool.

You run that on a developer workstation.

You then load the generated keys into the store of your choice, like an Apigee KVM.

Can we do the same for Production as well ? How to differentiate keys for each Env ? If we run on the command line tool keys will be downloaded to local right ? Is it advisable to use locally generated keys in Production ?

openssl is a tool that runs on the command line. On your development workstation.

It can generate keys. When you generate the keys, they get stored in filesystem files on your development workstation.

It's then up to you to provision those keys into Apigee, as you see fit. Whether you provision these keys into a KVM or something else, is up to you. Whether you provision the keys into a production org or a non-production org, is up to you.

Does this help?

Yes Thank you .. I have to generate 3 different keys for Test Stage and Prod . If i run Openssl in my local . Will i be able to generate 3 different set of Keys ? Do i need to change the command or Will i get different set of keys for each run ?

Each time you run the openssl command to generate a private key, it will generate a new key.

# To generate the key pair using the new format (PKCS#8), without encryption
openssl genpkey -algorithm rsa -pkeyopt rsa_keygen_bits:2048 -out keypair.pem
# to extract the public key from the above
openssl pkey -pubout -inform PEM -outform PEM \
    -in keypair.pem \
    -out public-genpkey.pem
<br>

If you want three sets of keys, I suppose you'd want to use a different filename for each invocation. And it would be up to you to manage those keys - to store them appropriately, and so on.

Thank you ... this helps