How to concatenate strings using only Apigee policies?

How to use JWT from ServiceCallout without custom JS code.

Hi, Community!

Target API requires JWT Authentication & in the proxy, I'm having "ServiceCallout" to the JWT service to get this token.

Then I use "ExtractVariable" policy to extract JWT from ServiceCallout.

JWT service developed the way that it returns JWT text without the beginning "Bearer" prefix.

Then I have to send this JWT to the Target API in the "authentication" request header.
At this step, I have to add the missing "Bearer" prefix & I'm using JS concatenation for that.

My question is, how can I accomplish concatenating joining "Bearer" text with the rest of the JWT text I received from the JWT service using only Apigee policies, without JS custom code?

JWT service responds with tokens as "blahblahblah".

Target API requires request header "authorization" as "Bearer blahblahblah".

And I'm curious how to add this "Bearer" to the "blahblahblah" using only Apigee policies.

thanks, BR, 
Optimism

 

Solved Solved
0 1 658
1 ACCEPTED SOLUTION

Mr Optimism! I like your handle.

I'm sorry it's not easier to discover these things, but yes there's a very simple way to do that kind of thing. Apigee has a thing called a "message template" that allows you to do what you describe. Message templates are used in various places in various policies, but the most obvious and accessible place is in the AssignMessage policy. As an example, injecting or replacing an authorization header into the current message, with a value that consists of the string "Bearer" followed by the value of some variable, might look like this :

 

<AssignMessage name='AM-Apply-Authorization'>
  <Set>
    <Headers>
      <Header name='authorization'>Bearer {variable-containing-token}</Header>
    </Headers>
  </Set>
</AssignMessage>

 

In message templates, any variable name within curly braces is replaced with the value of the named variable at runtime. Sometimes in my proxies I include this in the Response PostFlow to inject a response header telling the caller which proxy handled the request.

 

<AssignMessage name='##'>
  <Set>
    <Headers>
      <Header name='apiproxy'>{apiproxy.name} r{apiproxy.revision}</Header>
    </Headers>
  </Set>
</AssignMessage>

 

But you can do more than just set headers. This works with the Payload too of course:

 

<AssignMessage name='AM-Response'>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <Set>
    <Payload contentType='application/json'>{
  "token" : "{variable-containing-token-here}"
}</Payload>
    <StatusCode>200</StatusCode>
  </Set>
</AssignMessage>

 

And you can also set arbitrary variables via templates:

 

<AssignMessage name='AM-Formatted-Time'>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <AssignVariable>
    <Name>iso8601Format</Name>
    <Value>yyyy-MM-dd'T'HH:mm:ss'Z'</Value>
  </AssignVariable>
  <AssignVariable>
    <Name>formattedTime</Name>
    <Template>{timeFormatUTCMs(iso8601Format,system.timestamp)}</Template>
    <!-- eg, 2020-10-02T15:59:26Z -->
  </AssignVariable>
</AssignMessage>

 

The above example shows off a static function that is available within the Template, in this case the function is timeFormatUTCMs, which accepts a format and a value of milliseconds-since-epoch and returns a formatted time string. There are other functions for substring, replacing text, computing SHA256 digests, calculating HMACs, evaluating xpath or jsonpath... Pretty nice set of capabilities.

The jsonpath function means that in your case you should be able to eliminate the ExtractVariables policy, and do what you want with two AssignVariable elements within AssignMessage:

 

<AssignMessage name='AM-Inject-Header'>
  <AssignVariable>
    <Name>json-path-1</Name>
    <Value>$.access_token</Value>
  </AssignVariable>
  <AssignVariable>
    <Name>extracted-token</Name>
    <Value>BADDBEEF</Value>
    <Template>{jsonPath(json-path-1,responseMessage.content)}</Template>
  </AssignVariable>
  <Set>
    <Headers>
      <Header name='authorization'>Bearer {extracted-token}</Header>
    </Headers>
  </Set> 
</AssignMessage>

 

And (this is a bit meta) you can also refer to templates by variable name. So, you can do this:

 

<AssignMessage name='AM-Variable-From-Template'>
  <AssignVariable>
    <Name>new-variable</Name>
    <Template ref='variable-containing-template'/>
    <Value>unset</Value>
  </AssignVariable>
</AssignMessage>

 

With this approach, you can define a template in an environment-scoped KVM, or in a properties file, and then refer to the variable containing that template like this. The new-variable gets set with the value resulting from evaluating the template stored in variable-containing-template .

The message template thing is pretty handy. Check it out.

View solution in original post

1 REPLY 1

Mr Optimism! I like your handle.

I'm sorry it's not easier to discover these things, but yes there's a very simple way to do that kind of thing. Apigee has a thing called a "message template" that allows you to do what you describe. Message templates are used in various places in various policies, but the most obvious and accessible place is in the AssignMessage policy. As an example, injecting or replacing an authorization header into the current message, with a value that consists of the string "Bearer" followed by the value of some variable, might look like this :

 

<AssignMessage name='AM-Apply-Authorization'>
  <Set>
    <Headers>
      <Header name='authorization'>Bearer {variable-containing-token}</Header>
    </Headers>
  </Set>
</AssignMessage>

 

In message templates, any variable name within curly braces is replaced with the value of the named variable at runtime. Sometimes in my proxies I include this in the Response PostFlow to inject a response header telling the caller which proxy handled the request.

 

<AssignMessage name='##'>
  <Set>
    <Headers>
      <Header name='apiproxy'>{apiproxy.name} r{apiproxy.revision}</Header>
    </Headers>
  </Set>
</AssignMessage>

 

But you can do more than just set headers. This works with the Payload too of course:

 

<AssignMessage name='AM-Response'>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <Set>
    <Payload contentType='application/json'>{
  "token" : "{variable-containing-token-here}"
}</Payload>
    <StatusCode>200</StatusCode>
  </Set>
</AssignMessage>

 

And you can also set arbitrary variables via templates:

 

<AssignMessage name='AM-Formatted-Time'>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <AssignVariable>
    <Name>iso8601Format</Name>
    <Value>yyyy-MM-dd'T'HH:mm:ss'Z'</Value>
  </AssignVariable>
  <AssignVariable>
    <Name>formattedTime</Name>
    <Template>{timeFormatUTCMs(iso8601Format,system.timestamp)}</Template>
    <!-- eg, 2020-10-02T15:59:26Z -->
  </AssignVariable>
</AssignMessage>

 

The above example shows off a static function that is available within the Template, in this case the function is timeFormatUTCMs, which accepts a format and a value of milliseconds-since-epoch and returns a formatted time string. There are other functions for substring, replacing text, computing SHA256 digests, calculating HMACs, evaluating xpath or jsonpath... Pretty nice set of capabilities.

The jsonpath function means that in your case you should be able to eliminate the ExtractVariables policy, and do what you want with two AssignVariable elements within AssignMessage:

 

<AssignMessage name='AM-Inject-Header'>
  <AssignVariable>
    <Name>json-path-1</Name>
    <Value>$.access_token</Value>
  </AssignVariable>
  <AssignVariable>
    <Name>extracted-token</Name>
    <Value>BADDBEEF</Value>
    <Template>{jsonPath(json-path-1,responseMessage.content)}</Template>
  </AssignVariable>
  <Set>
    <Headers>
      <Header name='authorization'>Bearer {extracted-token}</Header>
    </Headers>
  </Set> 
</AssignMessage>

 

And (this is a bit meta) you can also refer to templates by variable name. So, you can do this:

 

<AssignMessage name='AM-Variable-From-Template'>
  <AssignVariable>
    <Name>new-variable</Name>
    <Template ref='variable-containing-template'/>
    <Value>unset</Value>
  </AssignVariable>
</AssignMessage>

 

With this approach, you can define a template in an environment-scoped KVM, or in a properties file, and then refer to the variable containing that template like this. The new-variable gets set with the value resulting from evaluating the template stored in variable-containing-template .

The message template thing is pretty handy. Check it out.