How to customize the response of GenerateAccessToken policy ?

Not applicable

By default, the access token that gets returned to the client looks something like this:

{
 "issued_at": "1420262924658",
 "scope": "READ",
 "application_name": "ce1e94a2-9c3e-42fa-a2c6-1ee01815476b",
 "refresh_token_issued_at": "1420262924658",
 "status": "approved",
 "refresh_token_status": "approved",
 "api_product_list": "[PremiumWeatherAPI]",
 "expires_in": "1799",
 "developer.email": "tesla@weathersample.com",
 "organization_id": "0",
 "token_type": "BearerToken",
 "refresh_token": "fYACGW7OCPtCNDEnRSnqFlEgogboFPMm",
 "client_id": "5jUAdGv9pBouF0wOH5keAVI35GBtx3dT",
 "access_token": "2l4IQtZXbn5WBJdL6EF7uenOWRsi",
 "organization_name": "docs",
 "refresh_token_expires_in": "0",
 "refresh_count": "0"
}

Can I change this? Add or remove properties? How?

Solved Solved
1 4 2,009
1 ACCEPTED SOLUTION

Not applicable

If you want to prevent all information from being returned in the response body, you can remove the <GenerateResponse/> element from the policy, or set it to false, like so:

<OAuthV2 name='OAuthV2-GenerateAccessToken'>
    <Operation>GenerateAccessToken</Operation>
     ....
    <GenerateResponse enabled='false'/>
</OAuthV2>

With that policy configuration, the policy will not return *any response* and the access token will be loaded into flow variables (aka context variables). You can then reference the flow variables to build your own response. The names of the flow variables depends on the name of the OAuthV2 policy, eg oauthv2accesstoken.{policy_name}.{variablename}. For the policy named 'OAuthV2-GenerateAccessToken', the variables are as follows:

oauthv2accesstoken.OAuthV2-GenerateAccessToken.access_token
oauthv2accesstoken.OAuthV2-GenerateAccessToken.token_type
oauthv2accesstoken.OAuthV2-GenerateAccessToken.expires_in
oauthv2accesstoken.OAuthV2-GenerateAccessToken.refresh_token
oauthv2accesstoken.OAuthV2-GenerateAccessToken.refresh_token_expires_in 
oauthv2accesstoken.OAuthV2-GenerateAccessToken.refresh_token_issued_at
oauthv2accesstoken.OAuthV2-GenerateAccessToken.refresh_token_status

For more information, see the boxed text under 'GenerateAccessToken' at the following link. http://apigee.com/docs/api-services/content/oauthv2-policy

Here is an example where the above approach has been implemented : https://github.com/apigee/api-platform-samples/tree/master/sample-proxies/oauth-advanced#howdo

View solution in original post

4 REPLIES 4

Not applicable

If you want to prevent all information from being returned in the response body, you can remove the <GenerateResponse/> element from the policy, or set it to false, like so:

<OAuthV2 name='OAuthV2-GenerateAccessToken'>
    <Operation>GenerateAccessToken</Operation>
     ....
    <GenerateResponse enabled='false'/>
</OAuthV2>

With that policy configuration, the policy will not return *any response* and the access token will be loaded into flow variables (aka context variables). You can then reference the flow variables to build your own response. The names of the flow variables depends on the name of the OAuthV2 policy, eg oauthv2accesstoken.{policy_name}.{variablename}. For the policy named 'OAuthV2-GenerateAccessToken', the variables are as follows:

oauthv2accesstoken.OAuthV2-GenerateAccessToken.access_token
oauthv2accesstoken.OAuthV2-GenerateAccessToken.token_type
oauthv2accesstoken.OAuthV2-GenerateAccessToken.expires_in
oauthv2accesstoken.OAuthV2-GenerateAccessToken.refresh_token
oauthv2accesstoken.OAuthV2-GenerateAccessToken.refresh_token_expires_in 
oauthv2accesstoken.OAuthV2-GenerateAccessToken.refresh_token_issued_at
oauthv2accesstoken.OAuthV2-GenerateAccessToken.refresh_token_status

For more information, see the boxed text under 'GenerateAccessToken' at the following link. http://apigee.com/docs/api-services/content/oauthv2-policy

Here is an example where the above approach has been implemented : https://github.com/apigee/api-platform-samples/tree/master/sample-proxies/oauth-advanced#howdo

I think that this approach has currently an issue, since if there is an error in the OAuth2 policy, no error is raised and there is no easy way, how to catch it.

Not applicable

Alternatively, you can use “ExtractVariable” policy to extract the required values from the “response” flow variable and use “AssignMessage” Policy to create your own payload with the extracted values.

There are two ways that I use:

1. Use GenerateResponse = false

<OAuthV2 name='OAuthV2-GenerateAccessToken'>
    <Operation>GenerateAccessToken</Operation>
     ....
    <GenerateResponse enabled='false'/>
</OAuthV2>

This sets context variables, such as:

oauthv2accesstoken.OAuthV2-GenerateAccessToken.access_token
oauthv2accesstoken.OAuthV2-GenerateAccessToken.token_type
oauthv2accesstoken.OAuthV2-GenerateAccessToken.expires_in
oauthv2accesstoken.OAuthV2-GenerateAccessToken.refresh_token
oauthv2accesstoken.OAuthV2-GenerateAccessToken.refresh_token_expires_in
oauthv2accesstoken.OAuthV2-GenerateAccessToken.refresh_token_issued_at
oauthv2accesstoken.OAuthV2-GenerateAccessToken.refresh_token_status

...and you can then use an AssignMessage policy to build whatever response you like. For example:

<AssignMessage name="AM-ValidToken">
  <Set>
    <StatusCode>200</StatusCode>
    <ReasonPhrase>OK</ReasonPhrase>
    <Payload contentType="application/json">{
  "success" : true,
  "token" : "{oauthv2accesstoken.OAuthV2-GenerateAccessToken.access_token}"
}
</Payload>
  </Set>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

2. Use a PostFlow step. This will be a JavaScript that modifies what gets sent back.

<OAuthV2 name='OAuthV2-GenerateAccessToken'>
    <Operation>GenerateAccessToken</Operation>
     ....
    <GenerateResponse enabled='true'/>
</OAuthV2>

And then the Javascript step (configure it to run after the GenerateAccessToken) :

<Javascript name='JS-GroomTokenResponse' timeLimit='200' >
  <IncludeURL>jsc://dateFormat.js</IncludeURL>
  <ResourceURL>jsc://groomTokenResponse.js</ResourceURL>
</Javascript>

And the JS code, which might look like this:

var b1 = JSON.parse(response.content),
    propertiesToRemove = ['status', 'refresh_token_status',
                          'token_type', 'organization_name', 'developer.email',
                          'scope', 'refresh_count',
                          'application_name'];


if (b1.access_token) {
  propertiesToRemove.forEach(function(item){
    delete b1[item];
  });

  // pretty-print JSON
  context.setVariable('response.content', JSON.stringify(b1, null, 2) + '\n');
}