Tuesday, March 25, 2014

OAuthV2 Policy Nuances

Few points to keep in mind while working with OAuthV2 policy.

1.  The XML elements in the OAuthV2 policy take references instead of values

In AssignMessage and other policies, variable references are specified using a Ref tag or Ref attribute.

 <QueryParam name="local_grant_type" Ref="grant_type">password</QueryParam>

The content of the QueryParam tag above is a literal value password. Consider the following OAuthV2 policy

 <GrantType>password</GrantType>
 <SupportedGrantTypes>
        <GrantType>password</GrantType>
  </SupportedGrantTypes>

The outer GrantType tag content is a reference to a variable named password and not a literal value. The inner GrantType tag contains password as literal value. All the tags outside SupportedGrantTypes & Attributes tags assume their content as variable references
This has been mentioned in the documentation too - however it's easy to miss because of the difference in behaviour with respect to other policies.


2. Password tag in OAuthV2 policy is <PassWord>variable_containing_password</PassWord> - note the capitalization of W in password.


3. Value content inside Attribute tag is either variable name or literal content.


  • <Attribute>{phone}</Attribute>  
  • <Attribute>phone: {phone}</Attribute>


In the first case the value of the variable phone is stored as the attribute of the access token. However, in the second case no variable interpolation of the phone variable occurs. The attribute will have the literal value phone:{phone} .JavaScript Policy is one of the options to build such a mixed content string.



Tuesday, March 18, 2014

Target Endpoint Validation Caveats

Validation failures in target endpoint xml files result in error messages that do not detail the root cause. In proxy xml files single quote around conditions is not valid. Consider the following example
<TargetEndpoint name="routetobackend">
  <Flows>
        <Flow name="login">
            <Request>
               <Step>
                    <Name>extract_accept_header</Name>
                </Step>
                 <Step>
                    <Condition>!(local_accept := 'application/json') </Condition>
                    <Name>fault_accept_json_not_found</Name>
                </Step>
            </Request>
            <Response/>
        </Flow>
  </Flows>
  <HTTPTargetConnection>
      <LoadBalancer>
         <Algorithm>RoundRobin</Algorithm>
         <RetryEnabled>true</RetryEnabled>
         <Server name="Some_Target">
            <IsEnabled>true</IsEnabled>
         </Server>
      </LoadBalancer>
    <Path>/some/path</Path>
  </HTTPTargetConnection>
</TargetEndpoint>
The single quote around application/json in the Condition tag is not valid. In this case, the error is obtained during runtime only (not deploy time) even though this is a static validation issue. The runtime error is as follows.

{"fault":{"faultstring":"Unable to send the request to the identified target","detail":{"errorcode":"messaging.runtime.TargetMissing"}}}

As i mentioned earlier the error is not descriptive of the root cause. Hence, in case of routing errors like above, its good to do a recheck on the content of the target endpoint xml before looking into network issues related to the backend.

Monday, March 10, 2014

Generating Password based OAuth Access Token In Response Flow

At times, it's required to generate access token in response flow based some custom validation performed with the backend API. In my scenario, I needed refresh token to be generated too. So I could not use implicit OAuth token generation. The best option in my case was to use password based access token generation.

Consider the following oauth policy to generate password based access token.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 enabled="true" continueOnError="false" async="false" name="generateAccessToken">
    <Operation>GenerateAccessToken</Operation>
    <AppEndUser>Srikanth</AppEndUser>
    <UserName>sriki</UserName>
    <PassWord>sriki</PassWord>
    <GrantType>grant_type</GrantType>
    <ClientId>sriki_client_id</ClientId>
    <SupportedGrantTypes>
        <GrantType>password</GrantType>
    </SupportedGrantTypes>
</OAuthV2>

Above policy continued to fail with 401 UnAuthorized error even though I had specified correct parameters. The solution for such a scenario (found on discussions with internal experts) is the need for an Authorization request header.

The Authorization header should contain Basic Base64-encoded (clientid:client secret). Following Javascript policy step prior to OAuth access token generation will solve the issue.

var client_id = context.getVariable("local_clientid");
var client_secret = context.getVariable("local_secret");
context.setVariable("request.header.Authorization","Basic "+CryptoJS.enc.Base64.stringify(CryptoJS.enc.Latin1
                                      .parse(client_id + ':' + client_secret)));


Tuesday, March 4, 2014

JSON Payload generation with variables

Apigee Edge has an AssignMessage policy to generate custom payload. Variable delimiter in policies is curly brace {}. Example: {username}

As expected the curly brace {} is also JSON object delimiter. So generating JSON payload with variables would require change of variable prefix and suffix for Edge variables. The example below shows sample snippet to generate JSON response.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="buildUserDetailsResponse">
    <Set>
        <Payload contentType="text/json" variablePrefix="#" variableSuffix="%">
            {
            "name":"#username%",
            "email":"#email%"
            "adddress":#address%
            }
        </Payload>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

Please note the  variablePrefix and  variableSuffix attributes of the payload tag. Further, variablePrefix and  variableSuffix cannot be identical.