Could a developer-app use the same consumer key to access APIs in different organizations of the same environment?

We have created a new organization (org2) in an environment where we had org1. There are some Developer Apps that access APIs deployed in org1 and will need access to APIS in org2.

We wanted to know if the consumer Apps could send the same credentials they are using with the APIs in org1. But we undenstand that they will have to send different credentials (because of the answer to question https://community.apigee.com/questions/44184/not-able-to-create-same-custom-app-key-for-differe.html).

In case that the Developer App sent the same key with a prefix, what's the way to transform it (remove the prefix) before verifying it?

Thanks in advance

0 1 116
1 REPLY 1

Yes -

Nominally, the uniqueness constraint is that the clientid (aka consumer key) must be unique in the org. But .... apparently the constraint is more strict than that. The clientid must be unique in its storage layer, which may handle multiple organizations. Hence the reason for the restriction described in the question you referenced.

My suggestion is that the client can send the same key.

Let me illustrate by example. Suppose each API Proxy in the below uses VerifyAPIKey for credential verification and the client sends the key in a header called "apikey". The same approach also works for OAuth2 tokens and client_credentials grant, and other grant types... but it's simpler to discuss with VerifyAPIKey.

client1 connects to an API Proxy in org1, sends key "abc". The API Proxy in org1 uses AssignMessage to apply its "key prefix", which results in a transformed key value stored in variable "effective_key".

<AssignMessage name='AM-ApplyPrefixToSetEffectiveKey'>
  <AssignVariable> 
    <Name>effective_key</Name>
    <Template>{prefix}-{request.header.apikey}</Template>
  </AssignVariable>
</AssignMessage>

Suppose the key prefix for org1 is "org1". (Maybe this prefix is retrieved from a KVM, or maybe it is just the organization name, or it is a value derived from some other place. It doesn't matter where it comes from. The important thing is that the prefix is unique for this org among all orgs). In this case the effective key for client1 in org1 is "org1-abc". Then the API proxy in org1 uses VerifyAPIKey like this:

<VerifyAPIKey name='VK-1'>
    <APIKey ref='effective_key'/>
</VerifyAPIKey>

client2 connects to an API Proxy in org2, sends key "abc". This is the same key as client1 used with the apiproxy in org1. The API Proxy in org2 does exactly the same thing as above, but the prefix for org2 is unique for that org. (Perhaps it is the org name). The effective key for client2 in org2 is "org2-abc". The API Proxy also uses the same VerifyAPIKey policy with the effective_key variable.

Some notes

  • when importing the key (Credential) into the org, you must import the keyvalue with the prefix. If I use the UI to display the credentials, then it must show "prefix-keyvalue". The actual value stored in the KMS must have the prefix. (The actual value stored in Apigee's key management system must reflect the value of the effective_key variable at runtime.) This has implications to your devportal, if you use one. You would need to strip the prefix from the devportal before displaying it to the user. You can do this with a drupal hook or with some custom script in the integrated dev portal.
  • Not all orgs need a prefix. One of the orgs may have no prefix at all, and that's fine. (Blank prefix). The logic is the same. Each prefix must be unique. At most one org can have a blank prefix.
  • If you want to get fancy, you can use the AM-ApplyPrefixToSetEffectiveKey conditionally, if and only if the needed prefix is not already present on the inbound key. The logic would be like this:

    <Step>
      <Name>AM-ApplyPrefixToSetEffectiveKey</Name>
      <Condition>NOT (request.header.apikey ~~ "org1-.*")</Condition>
    </Step>
    <Step>
      <Name>AM-UseActualKeyAsEffectiveKey</Name>
      <Condition>request.header.apikey ~~ "org1-.*"</Condition>
    </Step>
    	

    And the AM-UseActualKeyAsEffectiveKey looks like this:

    <AssignMessage name='AM-UseActualKeyAsEffectiveKey'>
      <AssignVariable> 
        <Name>effective_key</Name>
        <Template>{request.header.apikey}</Template>
      </AssignVariable>
    </AssignMessage>
    	

    Or, you could implement that conditional logic and variable assignment in a JS script step, if that seems easier to you.