S2

Introduction


S1 was a pretty basic service. Let's try protecting our service using key security by enforcing all incoming request to provide a key in the headers.

When we say key, we actually mean tenant external key, check out Key Security for more details.

S2 is a service located in soajs.jsconf repository, It is another example of how a service can be protected.

The S2 service is composed of two files:

  • index.js: contains the code of the service that implements the APIs.
  • config.js: contains the configuration used by the IMFV.


Same as before, let's make sure that the controller service is still on, but this time we need to add an environment variable to the terminal window running the controller service.

Stop the controller service and enter the following in its terminal window:

# export necessary environment variable
export SOAJS_PROFILE=/opt/soajs/node_modules/soajs.utilities/data/jsconf/profile.js

# run the service
node .

Now let's fire up service S2 in a new terminal window:

# go to correct directory
cd /opt/soajs/node_modules/soajs.jsconf/services/s2

# export necessary environment variables
export SOAJS_PROFILE=/opt/soajs/node_modules/soajs.utilities/data/jsconf/profile.js
export SOAJS_ENV=test
export SOAJS_SRVIP=127.0.0.1

# run the service
node .

Code Walkthrough


This page shows you how to interact with the s2 service after you install it and run it.

The code walkthrough is located in a sub page and explained in depth. Click here to learn more about how the code works.


Interacting with S2 service


Let's try a few things with S2:

curl -X GET "http://test-api.mydomain.com/jsconf2/hello?email=team@soajs.org"

We expect this to fail. Why? if we check the code explanation, we can see that extKeyRequired is set to true, meaning an external key is required, and since we have not provided any such key, the framework does not allow this API hit.

Response
{"result":false,"errors":{"codes":[132],"details":[{"code":132,"message":"A valid key is needed to access any API."}]}}

Let's try the request again, however this time we will add a key in the headers field:

curl -X GET -H "key: 9ee308d7b67d2e58a8770b99c8c0320c8d7262a72fc9516e09395bfa39f91b95190bfde9986f4e902ad5ba9de35573dbc5d087c1699c36632c1fccb91663c77529f633c8247366074d399ab326bfdeaa7211ce8c63b968c73cea7aab46296629" "http://test-api.mydomain.com/jsconf2/hello?email=team@soajs.org"
Response
{"result":true,"data":"John Doe <team@soajs.org> "}

Now that we have secured our service, let's bring Mongo into the equation.

If you notice in index.js, our service has two routes, a get route which we just saw above, and a post route. Let's see what this post route does:

curl -X POST -H "key: d1e3b418bb1a18f35954c590d0cf06ff2d9e1f0b46b5c7d540f038efcde4430862a4ef9f71e74d8d45401441397b1c0be7e765b13266d63f509de3cd72cff059d048b2957d4aff259340f0b14f60823631a39ee57ce242fada8ee6741b594931" -H "Content-Type: application/json" -d '{"name": "Mike Hajj","username": "mike","email":[{"email": "team@soajs.org","primary": true}]}' "http://test-api.mydomain.com/jsconf2/standalone/add"

Response
{"result":false,"errors":{"codes":[173],"details":[{"code":173,"message":"Validation failed for field: email -> The parameter 'email' failed due to: instance[0].address is required"}]}}

We get an error. This is also an IMFV issue, we can see that in the body of our request the key "email" is an array of objects, and inside the first object we have a key called "email". This is a mistake. The config file tells us that the expected key is "address" and as such, if we change this value we will see that our request will become successful:

curl -X POST -H "key: d1e3b418bb1a18f35954c590d0cf06ff2d9e1f0b46b5c7d540f038efcde4430862a4ef9f71e74d8d45401441397b1c0be7e765b13266d63f509de3cd72cff059d048b2957d4aff259340f0b14f60823631a39ee57ce242fada8ee6741b594931" -H "Content-Type: application/json" -d '{"name": "Mike Hajj","username": "mike","email":[{"address": "team@soajs.org","primary": true}]}' "http://test-api.mydomain.com/jsconf2/standalone/add"
Response
{"result":true,"data":true}

But what if we try passing identical inputs to this request? In the config file, we see a key "uniqueItems" set to true. This means that the IMFV will reject this input and that will result in a failed request:

curl -X POST -H "key: d1e3b418bb1a18f35954c590d0cf06ff2d9e1f0b46b5c7d540f038efcde4430862a4ef9f71e74d8d45401441397b1c0be7e765b13266d63f509de3cd72cff059d048b2957d4aff259340f0b14f60823631a39ee57ce242fada8ee6741b594931" -H "Content-Type: application/json" -d '{"name": "Mike Hajj","username": "mike","email":[{"address": "team@soajs.org","primary": true},{"address": "team@soajs.org","primary": true}]}' "http://test-api.mydomain.com/jsconf2/standalone/add"
Response
{"result":false,"errors":{"codes":[173],"details":[{"code":173,"message":"Validation failed for field: email -> The parameter 'email' failed due to: instance contains duplicate item"}]}}

Conclusion


This example shows us how we can secure our service using key security as well as use the IMFV to validate the input a service receives.