Apigee x - ServiceCallout set audience in GoogleIDToken for different environments

Hi,

we're transitioning from Apigee Edge to Apigee X. In Apigee Edge we used the Google Authentication extension to generate an ID Token to make a ServiceCallout to a cloudrun instance. We have different cloudrun instances running for different environments, so I need to set the right audience of the ID Token according to the Apigee environment. In Apigee Edge it was possible to use a variable as the audience in the authentication extension for that. When I set a variable in the audience element of the authentication block in my service callout in Apigee x, I get the error "The Audience element must not contain variables.". How is it possible to set different audiences for different environments in Apigee x?

Any help appreciated! Best,
Jonathan

Solved Solved
0 4 648
1 ACCEPTED SOLUTION

hmmm that seems like a bug to me.

Hmmm, wait a moment. The documented example configuration is this:

 

        <Authentication>
            <GoogleIDToken>
              <Audience ref="{variable}">{hostname}</Audience>
              <IncludeEmail ref="{variable}">true</IncludeEmail>
            </GoogleIDToken>
        </Authentication>

 

From the ServiceCallout reference.

That example is a little confusing because it shows the word "hostname" and the word "variable" within curly braces. The curlies suggest those things are treated as message templates, but that is not so. If you look a little further down the page, at the section that covers the Authentication element, it describes it as a STRING. So you need to specify a fixed string there. If you want something that's dynamically determined, then you need to use the ref= attribute. And the ref should refer to the name of a single variable.

So in your case the correct configuration would be something like this:

 

    <HTTPTargetConnection>
        <Properties/>
        <URL>https://{REPORTING_HOST}/v1/report</URL>
        <Authentication>
            <GoogleIDToken>
                <Audience ref='MY_AUDIENCE'/>
                <IncludeEmail>true</IncludeEmail>
            </GoogleIDToken>
        </Authentication>
    </HTTPTargetConnection>

 

But you need to make sure that the variable "MY_AUDIENCE" contains the entire audience string, including the scheme (https://) You can do that with an AssignMessage executed after your KVM GET. The AssignMessage should look something like this:

 

<AssignMessage name='AM-ApplyScheme'>
  <AssignVariable>
    <Name>MY_AUDIENCE</Name>
    <Template>https://{REPORTING_HOST}</Template>
  </AssignVariable>
</AssignMessage>

 

I'll file a bug on the example in the doc, asking to make it clearer.

View solution in original post

4 REPLIES 4

When I set a variable in the audience element of the authentication block in my service callout in Apigee x, I get the error "The Audience element must not contain variables.".

I'm not clear on what you're describing. Maybe you could show the configuration you are referring to.

And also, you may not need to solve this problem. There is a new feature in Apigee X that lets your proxy authenticate via a Service Account JSON key file. You don't need to use the "Authentication extension". Now it's much simpler.

Here's the documentation on the new feature. I'm not clear from your description if you are aware of this feature and are using it, or... ? But if not, check it out. If you ARE using it, show your configuration when you ask your question.

Hi Dino,
thanks for your reply! Sure, here is my configuration for the service callout (I'm already trying to use it with a service account)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ServiceCallout async="false" continueOnError="false" enabled="true" name="SC-Report">
    <DisplayName>SC-Report</DisplayName>
    <Properties/>
    <Request>
        <Set>
            <Headers>
                <Header name="Accept">application/json</Header>
            </Headers>
            <Verb>POST</Verb>
            <Payload contentType="application/json">{"user_id": "{user.id}", "amount": "{user.amount}"}</Payload>
        </Set>
        <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    </Request>
    <Response>calloutResponse</Response>
    <HTTPTargetConnection>
        <Properties/>
        <URL>https://{REPORTING_HOST}/v1/report</URL>
        <Authentication>
            <GoogleIDToken>
                <Audience>https://{REPORTING_HOST}</Audience>
                <IncludeEmail>true</IncludeEmail>
            </GoogleIDToken>
        </Authentication>
    </HTTPTargetConnection>
</ServiceCallout>

 

The variable REPORTING_HOST is read in before from a KVM with environmental scope.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<KeyValueMapOperations async="false" continueOnError="false" enabled="true" name="KVM-Target-Env" mapIdentifier="hosts_target_env">
    <Scope>environment</Scope>
    <Get assignTo="REPORTING_HOST" index="1">
        <Key>
            <Parameter>REPORTING_HOST</Parameter>
        </Key>
    </Get>
</KeyValueMapOperations>

 

When I try to save the proxy I get the error

jwill_0-1638784556655.png

 


Hope this helps.
Best
Jonathan
 

 

hmmm that seems like a bug to me.

Hmmm, wait a moment. The documented example configuration is this:

 

        <Authentication>
            <GoogleIDToken>
              <Audience ref="{variable}">{hostname}</Audience>
              <IncludeEmail ref="{variable}">true</IncludeEmail>
            </GoogleIDToken>
        </Authentication>

 

From the ServiceCallout reference.

That example is a little confusing because it shows the word "hostname" and the word "variable" within curly braces. The curlies suggest those things are treated as message templates, but that is not so. If you look a little further down the page, at the section that covers the Authentication element, it describes it as a STRING. So you need to specify a fixed string there. If you want something that's dynamically determined, then you need to use the ref= attribute. And the ref should refer to the name of a single variable.

So in your case the correct configuration would be something like this:

 

    <HTTPTargetConnection>
        <Properties/>
        <URL>https://{REPORTING_HOST}/v1/report</URL>
        <Authentication>
            <GoogleIDToken>
                <Audience ref='MY_AUDIENCE'/>
                <IncludeEmail>true</IncludeEmail>
            </GoogleIDToken>
        </Authentication>
    </HTTPTargetConnection>

 

But you need to make sure that the variable "MY_AUDIENCE" contains the entire audience string, including the scheme (https://) You can do that with an AssignMessage executed after your KVM GET. The AssignMessage should look something like this:

 

<AssignMessage name='AM-ApplyScheme'>
  <AssignVariable>
    <Name>MY_AUDIENCE</Name>
    <Template>https://{REPORTING_HOST}</Template>
  </AssignVariable>
</AssignMessage>

 

I'll file a bug on the example in the doc, asking to make it clearer.

Ok got it. Thanks for clarifying!