0
votes

I am working to put an API behind WSO2 API Manager installed on premise. I designed the API, added the endpoint and add a first mediation sequence which add Authorization header at runtime. And it works fine.

Now I am improving that mediation sequence in other to obtain a token if it doesn't exist and to renew it when it expires. The obtained token is stored in the registry. To do that, I use https://medium.com/@athiththan11/wso2-api-manager-oauth2-protected-endpoint-aa51c62f0ad7 and https://medium.com/@menakajayawardena/wso2-how-to-using-oauth2-protected-back-ends-with-api-manager-5d7e234c61c posts as reference.

My sequence is as follow:

<?xml version="1.0" encoding="UTF-8"?>
<sequence name="bapi_in_dev" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
    <property description="Retrieve stored token data" expression="get-property('registry','gov:/bapi/token_data')" name="stored_token_data" scope="default" type="STRING"/>
    <property description="Retrieve the time token_data was generated" expression="get-property('registry', 'gov:/bapi/token_generation_time')" name="token_generation_time" scope="default" type="STRING"/>
    <filter description="Renouveller le token tmoney si il est vieux de plus d'une heure" xpath="fn:number(get-property('SYSTEM_TIME')) - fn:number(get-property('token_generation_time')) > fn:number(360000)">
        <then>
            <property description="Sauvegarde du body de la requete" expression="json-eval($)" name="client_request_body" scope="default" type="STRING"/>
            <property description="Sauvegarde de la resource demandée" expression="get-property('axis2', 'REST_URL_POSTFIX')" name="client_request_resource" scope="default" type="STRING"/>
            <payloadFactory description="Body de la requete d'obtention de token" media-type="json">
                <format>{
    "nomUtilisateur": "username",
    "motDePasse": "password"
}</format>
                <args/>
            </payloadFactory>
            <header description="Header requis par bapi" name="Content-Type" scope="transport" value="application/json"/>
            <property description="Suppression  initialisation de la resource avant demande de token" name="REST_URL_POSTFIX" scope="axis2" type="STRING" value=""/>
            <call blocking="true" description="Demande de token">
                <endpoint>
                    <http method="post" statistics="enable" trace="enable" uri-template="https://bapi.domain.tld/login">
                        <suspendOnFailure>
                            <initialDuration>-1</initialDuration>
                            <progressionFactor>-1</progressionFactor>
                            <maximumDuration>0</maximumDuration>
                        </suspendOnFailure>
                        <markForSuspension>
                            <retriesBeforeSuspension>0</retriesBeforeSuspension>
                        </markForSuspension>
                    </http>
                </endpoint>
            </call>
            <property description="Extraction du token" expression="json-eval($.data.token)" name="tm_resp_data" scope="default" type="STRING"/>
            <property description="Enregistrement du token" expression="get-property('tm_resp_data')" name="gov:/bapi/token_data" scope="registry" type="STRING"/>
            <property description="Enregistrement heure a laquelle code a ete genere" expression="get-property('SYSTEM_TIME')" name="gov:/bapi/token_generation_time" scope="registry" type="LONG"/>
            <property description="Configuration de la resource pour effectuer la requete de l'user" expression="get-property('client_request_resource')" name="REST_URL_POSTFIX" scope="axis2" type="STRING"/>
            <header description="Ajout du token dans le header" expression="get-property('tm_resp_data')" name="Authorization" scope="transport"/>
            <payloadFactory description="Reconstruction du body de requete user" media-type="json">
                <format>$1</format>
                <args>
                    <arg evaluator="xml" expression="get-property('client_request_body')"/>
                </args>
            </payloadFactory>
        </then>
        <else>
            <header description="Ajout de Authorization header sauvegardé" expression="get-property('stored_token_data')" name="Authorization" scope="transport"/>
        </else>
    </filter>
</sequence>

I add this mediation to the API's inflow. But when I query it, it daes not enter the then part of the sequence then not updating the token.

Can you help me see why the filter is working that way and what I should do to correct it?

Thanks beforehand.

1
Looks there is no issue with the filter mediator. But can you do the following? 1. Log to check the content of the "token_generation_time" property 2. Check is 'gov:/bapi/token_generation_time' correct and content is validruks

1 Answers

1
votes

In your filter condition, you basically check whether the stored time is greater then 3600.

<filter description="Renouveller le token tmoney si il est vieux de plus d'une heure" xpath="fn:number(get-property('SYSTEM_TIME')) - fn:number(get-property('token_generation_time')) > fn:number(360000)">

But, initially, the token_generation_time is not set.

And also, stored_token_data is not set in the sequence. (it's only being read from the registry resource

<property description="Retrieve stored token data" expression="get-property('registry','gov:/bapi/token_data')" name="stored_token_data" scope="default" type="STRING"/>

So, I propose the below changes to fix the sequence.

  1. Since all the values are not set in the initial run, check the stored_token_data as well.
<filter description="" xpath="get-property('SYSTEM_TIME') - get-property('generated-time') > 3600000 or get-property('access_token') = ''">
        <then>
...
  1. If the stored token data is not found, generate the token, and store the token and the generated time in the registry resource.

You can use the property mediator with registry scope to set the value.

<property description="generated Time Setter" expression="get-property('SYSTEM_TIME')" name="gov:/pizzaOrderingAPI/generated_Time" scope="registry" type="LONG"/>
<property description="generated_token" expression="json-eval($.access_token)" name="generated-access-token" scope="default" type="STRING"/>
<property description="new Token setter" expression="get-property('generated-access-token')" name="gov:/pizzaOrderingAPI/access_Token" scope="registry" type="STRING"/>

ref: https://medium.com/@menakajayawardena/wso2-how-to-using-oauth2-protected-back-ends-with-api-manager-5d7e234c61c