JWT token using Amazon Web Service KMS

We are generating JWT using Generate JWT policy for integrating with Okta. In okta, app has been set up using public/private key method. Private key we are storing in KVM. 

We do not want to store private key in apigee(due to security restrictions raised by some team). Hence, we are generation public key using 'GetPublicKey' serivce of AWS. This public key is then stored in okta.

Now, using sign and verify service of AWS, we are getting signature for a message and using concept of JWT Serialization we are generating JWT token. This JWT token is then passed to /token endpoint of okta with SC policy using below parameters(client_assertion will have base64encode )

 <Set>
            <Path>{servicecallout.request.path}</Path>
            <Headers>
                <Header name="Content-Type">application/x-www-form-urlencoded</Header>
            </Headers>
            <FormParams>
                <FormParam name="client_id">0odefddfsd0KZDi0h8</FormParam>
                <FormParam name="grant_type">client_credentials</FormParam>
                <FormParam name="scope">okta.users.manage</FormParam>
                <FormParam name="client_assertion_type">urn:ietf:params:oauth:client-assertion-type:jwt-bearer</FormParam>
                
                <FormParam name="client_assertion">lYvdXYftA45liWd7cMNSWkFlmX0dNZwrDlXCCm2Q64H0Lxz3rYslXKDH8bpGjTck3yMsIj/mZ5hf/qMMCVnKqPo7C10Hs6UksniA63QvTKrpx9RaQqSN3jd/ylGRtJqddL0h0iP9X5YxAXbLeGvGNCmxD4Fe5alTD7TfSbOBk/0Kz1MFIyq6t+f4WAVkXEpcFcpPmf3vwW+WfrKe+CnqBcu8VodrD0r6BaXyfT/eRnSBwgf7HCIqDMWEczk34P5uDB6bvRLoxLaj6s0/J7PKFh/vFpzNMkcK7001jMVyUhBsIbduIKSr9mDuih65vz9W3DEEN0qZjzwMrjQ==</FormParam>
            </FormParams>
        </Set>

 Is this the correct way to get JWT token from AWS and then use it to get access_token from okta?

0 1 329
1 REPLY 1

I can try to help, but there are some things I don't understand.

We are generating JWT using Generate JWT policy for integrating with Okta. In okta, app has been set up using public/private key method. Private key we are storing in KVM.

I think you're talking about this - https://developer.okta.com/docs/guides/implement-oauth-for-okta-serviceapp/overview/. Basically you provision a service app at Okta, which generates a keypair. You register the public key with the "app" at Okta. Then you use a client (in this case Apigee) to generate a JWT and sign it with the private key. This represents the client assertion when making the call to Okta's /token endpoint.

We do not want to store private key in apigee(due to security restrictions raised by some team). ..

OK, that's going to present a problem for you. If Apigee is acting as the client that requests the token from Okta, then Apigee needs access to the private key. There's no way around that. If you don't want to STORE the key in Apigee, that's ok, but then you have to store it somewhere else and you have to transmit it to Apigee. Apigee needs to have the private key , in order to compute the signature required on the JWT.

Hence, we are generation public key using 'GetPublicKey' serivce of AWS. This public key is then stored in okta.

A new player has entered the game! I don't understand how "GetPublicKey" from AWS is going to get you a private key. I don't understand the AWS service, but if the name is meaningful, it retrieves a PUBLIC key. That's not suitable for signing a JWT. You need the private key.

Now, using sign and verify service of AWS, we are getting signature for a message and using concept of JWT Serialization we are generating JWT token.

OK, this is another new service. I don't know anything about this AWS service. If the output of that service is a JWT signed with the private key generated by Okta, then I guess you're ok.

This JWT token is then passed to /token endpoint of okta with SC policy using below parameters(client_assertion will have base64encode )

If I understand what you're saying, I think the encoding is unnecessary and inappropriate. the JWT format states that a signed is 3 segments of base64url-encoded data, concatenated with dots. There's no need to further base64 encode that. It's suitable in its original form for sending as a form parameter in an HTTP Request. I'm sure that's what Okta's /token endpoint expects and accepts.

You didn't ask me but, you've not solved the problem of information integrity, by disallowing Apigee from storing the private key. In your design, Apigee doesn't store the private key because "people are concerned."  But Apigee can contact the AWS service and ask for a signed JWT assertion, and .... that's equivalent. There's no semantic difference. You haven't make it "more secure".  You just made it more complicated. Let me say it a different way in case I'm not clear: Storing the private key in Apigee and allowing Apigee to generate a signature, is EXACTLY the same as allowing Apigee to call to some outside agent (like the AWS Service in your case) to request a signed assertion.  There's no informational difference. 

Good luck navigating this multi-party architecture!