Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Extracting OAuth 2.0 token in response to request by ServiceCallout

hi guys I am new to this, I have been searching for a long time to find a method for my proxy to send a request to another that uses Auth 2.0 for verification, I am doing it by a service callout , however I am successfully receiving the token in the response but am not able to extract the token from it using extract variable but the variable remains empty, if i define the source in the EV it says that the message is not available to the EV policy . Then saw it in one of the documentation that the extract variable works only on "application/json" and not "application/x-www-form-urlencoded" so i attached a javascript policy to do so but still unsuccessful in retrieving the token from the response, i would appreciate some guidance on it.

SC policy

<ServiceCallout name="SC-GetOAuthToken">
  <DisplayName>SC-GetOAuthToken</DisplayName>
  <Request variable="oauthRequest">
    <Set>
      <Verb>POST</Verb>
      <Headers>
        <Header name="Content-Type">application/x-www-form-urlencoded</Header>
      </Headers>
      <FormParams>
        <FormParam name="client_id">{CLIENT_ID}</FormParam>
        <FormParam name="client_secret">{CLIENT_SECRET}</FormParam>
        <FormParam name="grant_type">client_credentials</FormParam>
        <FormParam name="scope">{SCOPE}</FormParam>
      </FormParams>
    </Set>
  </Request>
  <Response variable="NewTokenVariable"/>
  <HTTPTargetConnection>
    <URL>{SERVICE_URL}</URL>
  </HTTPTargetConnection>
</ServiceCallout>

ev policy: 

<ExtractVariables name="EV-ExtractOAuthToken">
  <DisplayName>Extract OAuth Token</DisplayName>
  <JSONPayload>
    <Variable name="access_token" type="string">
      <JSONPath>$.access_token</JSONPath>
    </Variable>
    <Variable name="token_type" type="string">
      <JSONPath>$.token_type</JSONPath>
    </Variable>
    <Variable name="expires_in" type="integer">
      <JSONPath>$.expires_in</JSONPath>
    </Variable>
    <Variable name="consented_on" type="integer">
      <JSONPath>$.consented_on</JSONPath>
    </Variable>
    <Variable name="scope" type="string">
      <JSONPath>$.scope</JSONPath>
    </Variable>
  </JSONPayload>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
  <Source>NewTokenVariable</Source>
</ExtractVariables>

JS step:

var tokenResponse = context.getVariable("NewTokenVariable");
print("Token Response: " + tokenResponse);
if (tokenResponse) {
  var jsonResponse = JSON.parse(tokenResponse);
  var accessToken = jsonResponse.access_token;
  context.setVariable("extractedAccessToken", accessToken);
  print("Access Token Extracted: " + accessToken);
} else {
  print("NewTokenVariable is null or empty");
  context.setVariable("extractedAccessToken", "Token Not Found");
}

 

just for reference this is the type of response generated by my SC,  is something like this

{
"token_type": "Bearer",
"access_token": "{ACCESS_TOKEN}",
"expires_in": {EXPIRES_IN},
"consented_on": {CONSENTED_ON},
"scope": "{SCOPE}"
}

 



Solved Solved
0 5 411
1 ACCEPTED SOLUTION

In your ServiceCallout policy, use this: 

 

   ...
  </Request>
  <Response>NewTokenVariable</Response>
  <HTTPTargetConnection>
    ...

 

and not this: 

 

   ...
  </Request>
  <Response variable='NewTokenVariable'/> <!-- NO NO NO -->
  <HTTPTargetConnection>
    ...

 

I've filed a pull request for apigeelint to flag this kind of error. 

View solution in original post

5 REPLIES 5

Hey @HamzaJaffry,

It looks like you are on the right track with your setup.

The approach you're using with the ExtractVariables policy after the ServiceCallout is actually the recommended method in Apigee’s own documentation: ServiceCallout Usage. So, it's strange that this isn't working for you.

Are you sure that the ServiceCallout is executing properly? Have you tried running Apigee's Trace (Debug) Tool to check if the NewTokenVariable is getting populated correctly?

As for the JavaScript approach, I think the issue lies in how you're trying to parse the response. You're currently parsing the message object instead of the response body. What you should do is grab the body of the response using:

 

var tokenResponse = context.getVariable('NewTokenVariable.content'); // Focus on .content

 

This way, you’ll be able to parse the actual content of the message, and everything should work as expected.

Give it a shot and let me know how it goes!

thankyou sir i took your first advice and went with the recommended EV , it was a huge blunder in the XML structure

In your ServiceCallout policy, use this: 

 

   ...
  </Request>
  <Response>NewTokenVariable</Response>
  <HTTPTargetConnection>
    ...

 

and not this: 

 

   ...
  </Request>
  <Response variable='NewTokenVariable'/> <!-- NO NO NO -->
  <HTTPTargetConnection>
    ...

 

I've filed a pull request for apigeelint to flag this kind of error. 

Thankyou sir it was a great blunder I was making , however your videos have helped me a lot from the start, I'm honored.

haha, glad to help.  Not a great blunder. The system should alert you to such problems, should make it harder to trip over these things. Definitely check out apigeelint, it can help you avoid other similar problems. 

Top Solution Authors