0
votes

We're implementing WSO2-AM to handle access to some internal APIs from our Moodle LMS we wish to expose to the internet.

I am configuring the access to this LMS via WSO2 but I've run into an issue I can't resolve.

I realise WSO2 documentation is extensive, but I'be not been able to actually find a specific instance of this configuration.

Background: Moodle itself has implemented its APIs in a very non-standard manner. They call them REST, but they are not truly restful. Some of the parameters, such as a users token, are passed in the URL query string rather than using headers in the body of the query itself.

To start with, I have two APIs configured in WSO2, one to request a user token from Moodle (Moodle requires this to permit access to the API for a specific user) and another to get the users enrolled course list.

The first request to get the user token from Moodle via WSO2 proceeds as expected. I pass in the username/password/service parameters via the header as you would expect (so that they are encrypted over HTTPS) to WSO2, which it pushes to Moodle, as a POST. The response from Moodle via WSO2 is as expected, a JSON payload containing a token which my client then parses to use in subsequent requests.

The next request is then calling a more useful service in Moodle, to get a users enrolled courses. There are two issues noted here which I'm unsure how to resolve.

The problems: Moodle expects GET or POST parameters for the call to the web-service. When I'm using GET, which is handy for testing, the parameters passed from the client to WSO2 are either wrong (in the case of the 'userid') or missing (in the case of the wstoken field, which is in the post body).

In API publisher I have the API in WSO2 configured for POST with a URL pattern of {version}/courses/{userid} The API definition is configured as below: API Definition

API Endpoint configuration is: API Endpoint Configuration

URL: http://(moodleurl)/webservice/rest/server.php?wstoken={uri.var.wstoken}&wsfunction=core_enrol_get_users_courses&moodlewsrestformat=json&userid={uri.var.userid}

GET URL as received by Apache hosting Moodle is: xx.xx.xx.xx - - [09/Aug/2016:10:36:03 +0930] "POST /webservice/rest/server.php?wstoken=&wsfunction=core_enrol_get_users_courses&moodlewsrestformat=json&userid=6/6 HTTP/1.1" 200 270

So, the two issues are the missing 'wstoken' parameter (which is in the post body provided to WSO2, and the 'userid' being doubled up with a slash between the items.

I have run the client via a proxy and the data appears to be sent correctly to WSO2: Client->WSO2 Proxy

So I'm wondering what I can do about these problems:

Is there a different URL parameter I can use to correctly include a posted body param in the URL out to the service API address?

Is there some specific configuration problem I've made that's causing the userid parameter to break in this manner?

The posted parameters from the client do appear to be included in the post to Moodle by WSO2; so it is likely they can be stripped from the URL and simply included in the post body to Moodle by WSO2, meaning that it's likely only the issue with the userid parameter that needs to be resolved to allow this to work - unfortunately I'm not sure how to place a proxy between WSO2 and Moodle itself to validate the parameters that are posted to the API, short of using Wireshark.

1

1 Answers

1
votes

The 'userid' being doubled up with a slash between the items because the URI template of the API's resource is automatically appended to the end of the HTTP endpoint at runtime. For an example in your case you defined the endpoint url as:

http://(moodleurl)/webservice/rest/server.php?wstoken={uri.var.wstoken}&wsfunction=core_enrol_get_users_courses&moodlewsrestformat=json&userid={uri.var.userid} 

Then url pattern (/{userid}) appends to the endpoint url by default. To overcome this issue you can use the following mediator setting to remove the URL postfix from the backend endpoint:

<property name="REST_URL_POSTFIX" scope="axis2" action="remove"/>

For more on this please refer the link given in [1].

You can read the variables in the resources (urls) during mediation runtime using property values with the "uri.var." prefix. For example, in your case HTTP endpoint gets the wstoken and userid as the uri variables. But wstoken contains in the body section of the request. Therefore you cannot add it by introducing wstoken={uri.var.wstoken} as a query paramter to the endpoint. One way that you can overcome this issue is by defining wstoken as a query parameter by changing the parameter Type to query. The other way is you can define it in the header of the incoming request.

[1]. https://docs.wso2.com/display/AM190/Map+the+Parameters+of+your+Backend+URLs+with+the+API+Publisher+URLs