Implement token renewal authentication while calling an Oauth2 backend

Here is an other limitation of this product: it does not deal with Oauth authentication so you need to create your own sequence to deal with it. Let's call it auth_oauth.

Before you call any resource that require oauth authentication, run the following sequence.

<sequence name="auth_oauth" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
    <enrich description="store">
        <source clone="true" type="body"/>
        <target property="payload" type="property"/>
    </enrich>
    <propertyGroup description="REG retrieval">
        <property expression="get-property('SYSTEM_TIME')" name="now" scope="default" type="STRING"/>
        <property expression="get-property('registry','gov:/endpoints/some_token/valid_until')" 
        name="valid_until" scope="default" type="STRING"/>
        <property expression="get-property('registry','gov:/endpoints/some_token/access_token')" 
        name="access_token" scope="default" type="STRING"/>
    </propertyGroup>
    <property action="remove" name="TRANSPORT_HEADERS" scope="axis2"/>
    <filter xpath="$ctx:access_token='' or $ctx:now  > $ctx:valid_until">
        <then>
            <log description="TOKEN GEN">
                <property name="projectName" value="rsa2wayzz"/>
                <property name="action" value="tokenRenewal"/>
            </log>
            <property name="DISABLE_CHUNKING" scope="axis2" type="STRING" value="true"/>
            <header expression="fn:concat('Basic ', base64Encode(fn:concat($ctx:client_id,':',$ctx:client_secret)))" 
            name="Authorization" scope="transport"/>
            <payloadFactory description="i" media-type="text">
                <format>grant_type=password&amp;username=$1&amp;password=$2</format>
                <args>
                    <arg evaluator="xml" expression="$ctx:user"/>
                    <arg evaluator="xml" expression="$ctx:password"/>
                </args>
            </payloadFactory>
            <call blocking="true">
                <endpoint>
                    <http method="post" uri-template="https://some/api/token">
                        <suspendOnFailure>
                            <initialDuration>-1</initialDuration>
                            <progressionFactor>-1</progressionFactor>
                            <maximumDuration>0</maximumDuration>
                        </suspendOnFailure>
                        <markForSuspension>
                            <retriesBeforeSuspension>0</retriesBeforeSuspension>
                        </markForSuspension>
                    </http>
                </endpoint>
            </call>
            <property expression="json-eval($.expires_in)" name="expires_in" scope="default" type="STRING"/>
            <script language="js">
            <![CDATA[var sum = (parseInt(mc.getProperty("expires_in")) - 3) * 1000 + parseInt(mc.getProperty("now")) ;     
            var sum = mc.setProperty("valid_until",sum.toString());]]>
            </script>
            <propertyGroup description="set token">
                <property expression="json-eval($.access_token)" 
                name="gov:/endpoints/some_token/access_token" scope="registry" type="STRING"/>
                <property expression="$ctx:valid_until" 
                name="gov:/endpoints/some_token/valid_until" scope="registry" type="STRING"/>
            </propertyGroup>
        </then>
        <else/>
    </filter>
    <enrich description="restore">
        <source clone="true" property="payload" type="property"/>
        <target type="body"/>
    </enrich>
</sequence>

The general idea is the following. First, store the payload with enrich, to avoid it to be send to the token renewal url instead of the endpoint you'll call later on. Then, look for the reg:.../valid_until value that this very same sequence might have written earlier. Compare it with SYSTEM_TIME (a.k.a. $ctx:now) during the filter phase. Either the token is still valid, and you are good to go or you need to renew the token.

Depending on the API, this phase might change from one API to another. In this example, the API needs both base64(client_id:client_secret) in the Authorization: Basic header and some user and password to issue a token. The successful response looks like this:

{
    "access_token": "some_token",
    "valid_until": 9000
}

The access_token will be the one used while calling for the resource later on.

<header description="Set Authorization" expression="fn:concat('Bearer ',$ctx:access_token)" name="Authorization" scope="transport"/>

But to be really useful, we'll need to store this token along with the precise moment when it will be outdated. We need to compute this based on SYSTEM_TIME (which is in milliseconds: thus * 1000). This is where the script mediator is required. Last but not least, store both valid_until and access_token in registry variables