Search code examples
wso2wso2-api-managerwso2-enterprise-integrator

How to add a custom sequence or doing chain before APIs in WSO2 Publisher


I am using WSO2 Publisher and need to add a custom sequence that runs before specific APIs. The goal is to handle some pre-processing logic like adding a user ID from WSO2 IS response from this endpooint /oauth2/introspect header before the API call reaches the backend.

I know it's possible to create sequences in Integration Studio and invoke them from APIs defined there. However, I have some APIs defined directly in the Publisher UI and need to invoke a sequence for those.

I tried checking the WSO2 Publisher documentation but could not find clear examples on how to invoke a custom sequence before APIs defined in the Publisher UI.

My ideal solution would be:

  1. Create a sequence in Integration Studio or api defined in publisher to add the custom user ID header

  2. Configure this sequence to execute before any APIs defined in the Publisher UI that need the processing

Does anyone have examples or suggestions on the best way to call a custom sequence before APIs configured in the Publisher UI? Or is there another recommended approach to run pre-processing logic before API calls in WSO2 Publisher?

Also what is the best practice to make backend knows which is the user doing the call?.

Note

  • In my example I am using WSO2 IS to secure WSO2 AM.
  • I am trying to do that to avoid make the Backends services or the frontend applications to do that from their side

Versions

  • wso2 am 4.1.0
  • wso2 is 6.1.0

Any help or pointers are appreciated!


Solution

  • I'm super clear on your requirements. But if your intention is to pass the JWT to the backend which has necessary user attributes the approach is different.

    Having said that, you can execute a custom mediation sequence before the API request goes to the backend. For this, you need to create a custom policy as described here. The easiest way is to go to this URL https://localhost:9443/publisher/policies/ and then open an existing policy and download one. Then change the artifacts in it accordingly. Once updated you can upload the policy and engage it to the API.

    Following is a reference sequence you can refer to. The following will generate an OAuth token and add it as a header before calling the backend. One key thing to note here is saving and responding the request-body which ensures the initial request body is sent to the backend.

    <?xml version="1.0" encoding="UTF-8"?>
    <sequence name="oauth2-sequence" xmlns="http://ws.apache.org/ns/synapse">
        <!-- token generation to the oauth server's token endpoint -->
        <!-- add the base64 encoded credentials -->
        <property name="client-authorization-header" scope="default" type="STRING" value="MDZsZ3BTMnh0enRhOXBsaXZGUzliMnk4aEZFYTpmdE4yWTdLcnE2SWRsenBmZ1RuTVU1bkxjUFFh" />
        <property name="request-body" expression="json-eval($)" scope="default" type="STRING" />
        <property name="resource" expression="get-property('axis2', 'REST_URL_POSTFIX')" scope="default" type="STRING" />
    
        <!-- creating a request payload for client_credentials -->
        <payloadFactory media-type="xml">
            <format>
                <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
                    <soapenv:Body>
                        <root xmlns="">
                            <grant_type>client_credentials</grant_type>
                        </root>
                    </soapenv:Body>
                </soapenv:Envelope>
            </format>
            <args></args>
        </payloadFactory>
    
        <!-- set related headers to call the token endpoint -->
        <header name="Authorization" expression="fn:concat('Basic ', get-property('client-authorization-header'))" scope="transport" />
        <header name="Content-Type" value="application/x-www-form-urlencoded" scope="transport" />
        <property name="messageType" value="application/x-www-form-urlencoded" scope="axis2" type="STRING" />
        <property name="REST_URL_POSTFIX" value="" scope="axis2" type="STRING" />
    
        <!-- change the token endpoint -->
        <call blocking="true">
            <endpoint>
                <http method="POST" uri-template="https://localhost:9443/oauth2/token" />
            </endpoint>
        </call>
    
        <!-- append the acquired access token and make the call to the backend service -->
        <property name="bearer-token" expression="json-eval($.access_token)" scope="default" type="STRING" />
        <property name="REST_URL_POSTFIX" expression="get-property('resource')" scope="axis2" type="STRING" />
        <header name="Authorization" expression="fn:concat('Bearer ', get-property('bearer-token'))" scope="transport" />
        <payloadFactory media-type="json">
            <format>$1</format>
            <args>
                <arg evaluator="xml" expression="get-property('request-body')" />
            </args>
        </payloadFactory>
    </sequence>