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

How to access App custom attributes within Microgateway?

The client's use case is that they would like to store custom attributes on the App, product or developer and access those custom attributes from Microgateway. I reviewed the previous community post and also the Microgateway FAQs, which discuss this topic. The FAQ's provide a high-level approach to this. I will document the implementation of this high-level approach

Solved Solved
4 10 2,310
1 ACCEPTED SOLUTION

When Microgateway starts it downloads all the proxies (prefixed with edgemicro_), products, and apps and caches that data locally. However, you are not able to access custom attributes on those products. I was able to access the custom attributes on an Apigee App by injecting them as custom claims into the JWT when it is created. If you use access token validation, then you can access the custom claims on every request to Microgateway, which is similar to assigning custom attributes to an Apigee access token in Edge.

0) Add a custom attributes to the App.

3249-screen-shot-2016-07-27-at-124127-pm.png

1) Modify the edgemicro-auth proxy, by saving it as a new revision

a) Add an Extract Variable policy to the Preflow to retrieve the client ID from the JSON payload - client credential request.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExtractVariables async="false" continueOnError="false" enabled="true" name="Extract-Client-ID">
    <DisplayName>Extract-Client-ID</DisplayName>
    <Properties/>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <JSONPayload>
        <Variable name="client_id">
            <JSONPath>$.client_id</JSONPath>
        </Variable>
    </JSONPayload>
    <Source clearPayload="false">request</Source>
    <VariablePrefix>flw.apigee</VariablePrefix>
</ExtractVariables>
	

b) Add an Access Entity policy to the Preflow to lookup the app custom attributes based on the client Id extracted in the previous step.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AccessEntity async="false" continueOnError="false" enabled="true" name="Access-Entity-1">
    <DisplayName>Access-Entity-1</DisplayName>
    <Properties/>
    <EntityIdentifier ref="flw.apigee.client_id" type="consumerkey"/>
    <EntityType value="app"/>
</AccessEntity>

c) Now you have to replace the content of api/controllers/volos-oauth.js file with the content from the volos-auth.js.txt file attached to this post.

I had to make some minor changes to this file for it to work. It is easier for you to download the attached file and copy it into your proxy, rather than explain what you need to change. Summary of changes below:

The first change I made was to add apigee-access, which allows a Node.js proxy to access Apigee Edge flow variables.

var apigee = require('apigee-access'); 

I also added the added the custom_attribute to the JWT payload, which references the Access Entity policy variable that is created when the policy executes.

var token = {
    application_name: apigeeToken.application_name,
    client_id: apigeeToken.client_id,
    scopes: apigeeToken.scope ? apigeeToken.scope.split(' ') : [],
    api_product_list: apigeeToken.api_product_list ? apigeeToken.api_product_list.slice(1, -1).split(',') : [],
    custom_attribute: apigee.getVariable(req, 'AccessEntity.ChildNodes.Access-Entity-1.App.Attributes.Attribute.4.Value')
  };


You may need to send an API request to determine the flow variable name of your App's custom attribute. In my case, it was stored in the variable below. You could also include an assign message policy to change the variable name to a more friendly version.

AccessEntity.ChildNodes.Access-Entity-1.App.Attributes.Attribute.4.Value

d) Save your changes.

e) When you submit an Access Token request via the microgateway cli, you will receive a JWT. Execute this command from the [path to edgemicro]/cli directory.

./edgemicro token get -o orgname -e env -i client_id -s secret

f) You can view the contents of the JWT with jwt.io and you should see the custom attribute(s) that you added once you decode the token.

2) Now you need to retrieve the value from the JWT when the request is submitted to Microgateway.

Microgateway will automatically validate and decode the token so that you can access the payload of the token from a custom plugin.

a) First you need to create a custom plugin; you can learn how to do this here, but I have already created it so you can download the extract-custom-claims.zip file and place it in your [path to microgateway]/plugins directory.

b) The last step is to update the {org}-{env}-config.yaml file, which holds Microgateway configuration. I have extracted a portion of that file below.

Notice that the "extract-custom-claims" plugin was added to the plugins - sequence section. This will make sure that our plugin executes after the OAuth plugin.

You can access the JWT custom attributes as shown below.

req.headers[header] =  req.token.custom_attribute;

Also notice that the "extract-custom-claims" is also added as a top-level item in the {org}-{env}-config.yaml file. This allows you to set values in the config file that are accessible from the plugin during run-time.

edgemicro:
  port: 8000
  max_connections: 1000
  max_connections_hard: 5000
  restart_sleep: 500
  restart_max: 50
  max_times: 300
  logging:
    level: info
    dir: /var/tmp
    stats_log_interval: 60
    rotate_interval: 24
  plugins:
    sequence:
      - oauth
      - extract-custom-claims
headers:
  x-forwarded-for: true
  x-forwarded-host: true
  x-request-id: true
  x-response-time: true
  via: true
oauth:
  allowNoAuthorization: false
  allowInvalidAuthorization: false
extract-custom-claims:
  username_header: x-username
  basic_auth_service_acct_user: serviceuser
  basic_auth_service_acct_pw: servicepassword

This is a snipet of the plugin code, which is also included in the attached zip.

//extract the username and password from the config file
var uname = config.basic_auth_service_acct_user;
var p = config.basic_auth_service_acct_pw;

If you send a request to Microgateway with a valid JWT token, then you should see some of the values print on the console, but they will also be injected into the request as custom headers to the target service.

Example of Microgateway request:

curl -i -H "Authorization: Bearer {valid_jwt}" "http://localhost:8000/edgemicro_hello/ping"

View solution in original post

10 REPLIES 10