SailsJS CSRF mismatch error customize - sails.js

I need to customise the error that shows up when someone did not send the CSRF code with the POST request.
So that no one will know what happened with the error and they will not even try to hack in to the CSRF mechanism.
Hope this is clear

For now Sails.js CSRF hook uses res.forbidden() function to handle wrong CSRF token.
It uses it with this message:
return res.forbidden("CSRF mismatch");
So you could rewrite this response by placing a new file with name forbidden.js into /api/responses
Actually you cound copy this one: https://github.com/balderdashy/sails/blob/master/lib/hooks/responses/defaults/forbidden.js
And add condition to check data before production mode check:
...
else sails.log.verbose('Sending 403 ("Forbidden") response');
if (data == 'CSRF mismatch') {
//Return another response for example:
return res.jsonx(500, {/* data here */});
}
// Only include errors in response if application environment
// is not set to 'production'. In production, we shouldn't
// send back any identifying information about errors.
if (sails.config.environment === 'production') {
...
Anyway as long as you will use development mode for sails. You will see all errors when getting 500 or any other error from sails. But in production mode all error messages will be hidden. And your users wouldn't get any error details. Except of error code.
So in production mode without any changes you will get only HTTP 403 code.

Related

How to test that a element is not in the screen while a http request is made?

I have an application using React and axios, and I want to this the following behvior:
Fill a form
submit form
Success message shows
Fill the form again
submit form
While the request is made, the success message should not be showing**
request finish, success message shows again
**the problem is to test this step (6)
I'm using axios-mock-adapter to mock axios. I tried the following approach:
axiosMock
.onPost('/api/auth/alteracaoSenha').replyOnce(204)
.onPost('/api/auth/alteracaoSenha').replyOnce(() => {
expect(screen.queryByText('Success message')).not.toBeInTheDocument()
return [204]
})
When I try this, it works fine. But, if I remove the code that reset the success message to see if the test broke, the test continues to pass.
What I found is that the expect throws an error, but the axios mock catch this error and just return it to the API :/ So the expect line that should file, did not break the test.
Is there any other option to do that test?

Integrate extent reports with jmeter for test reporting

I would like to uses jmeter for api functional testing, the jmeter dashboard reporting is not ideal for functional testing.
I have attempted to integrate extent 2.41.2 reporting with groovy script that validates responses (http and expected response code).
I have attempted to use the idea given in Using extentreports for jmeter test results
However that has failed. I used a js2322 assertion to check for valid responses, but then I get errors whenever attempt to run.
I'm not sure whether it should be setup as post processor step instead of an assertion.
Has anyone got any ideas on how this can be achieved?
You can assert result by using prev which is SampleResult:
prev - (SampleResult) - gives access to the previous SampleResult (if any)
Here's example of checking token exists in response and if not return relevant assertion:
import org.apache.jmeter.assertions.AssertionResult;
boolean assertToken = prev.getResponseDataAsString().contains("token");
prev.setSuccessful(assertToken);
if (!assertToken) {
AssertionResult assertionResult = new AssertionResult("Assertion expected to contain token")
assertionResult.setFailureMessage("Assertion failure message: Test failed: text expected to contain /token/");
assertionResult.setFailure(true);
prev.addAssertionResult(assertionResult);
}

Empty response on long running query SailsJS

I'm currently running SailsJS on a Raspberry Pi and all is working well however when I execute a sails.models.nameofmodel.count() when I attempt to respond with the result I end up getting a empty response.
getListCount: function(req,res)
{
var mainsource = req.param("source");
if(mainsource)
{
sails.models.gatherer.find({source: mainsource}).exec(
function(error, found)
{
if(error)
{
return res.serverError("Error in call");
}
else
{
sails.log("Number found "+found.length);
return res.ok({count: found.length});
}
}
);
}
else
{
return res.ok("Error in parameter");
}
},
I am able to see in the logs the number that was found (73689). However when responding I still get an empty response. I am using the default stock ok.js file, however I did stick in additional logging to try to debug and make sure it is going through the correct paths. I was able to confirm that the ok.js was going through this path
if (req.wantsJSON) {
return res.jsonx(data);
}
I also tried adding .populate() to the call before the .exec(), res.status(200) before I sent out a res.send() instead of res.ok(). I've also updated Sails to 11.5 and still getting the same empty response. I've also used a sails.models.gatherer.count() call with the same result.
You can try to add some logging to the beginning of your method to capture the value of mainsource. I do not believe you need to use an explicit return for any response object calls.
If all looks normal there, try to eliminate the model's find method and just evaluate the request parameter and return a simple response:
getListCount: function(req, res) {
var mainsource = req.param("source");
sails.log("Value of mainsource:" + mainsource);
if (mainsource) {
res.send("Hello!");
} else {
res.badRequest("Sorry, missing source.");
}
}
If that does not work, then your model data may not actually be matching on the criteria that you are providing and the problem may lie there; in which case, your response would be null. You mentioned that you do see the resulting count of the query within the log statement. If the res.badRequest is also null, then you may have a problem with the version of express that is installed within sailsjs. You mention that you have 11.5 of sailsjs. I will assume you mean 0.11.5.
This is what is found in package.json of 0.11.5
"express": "^3.21.0",
Check for any possible bugs within the GitHub issues for sailsjs regarding express and response object handling and the above version of express.
It may be worthwhile to perform a clean install using the latest sailsjs version (0.12.0) and see if that fixes your issue.
Another issue may be in how you are handling the response. In this case .exec should execute the query immediately (i.e. a synchronous call) and return the response when complete. So there should be no asynchronous processing there.
If you can show the code that is consuming the response, that would be helpful. I am assuming that there is a view that is showing the response via AJAX or some kind of form POST that is being performed. If that is where you are seeing the null response, then perhaps the problem lies in the view layer rather than the controller/model.
If you are experiencing a true timeout error via HTTP even though your query returns with a result just in time, then you may need to consider using async processing with sailjs. Take a look at this post on using a Promise instead.

Grails withForm, reset token on error?

Currently using grails 2.2.2
I've been trying to implement tokens into my application and have come up with this issue. We try to avoid re-rendering pages because it can be very slow so we return JSON instead. The following is a basic controller call that we use but I'm not sure what I should be doing to reset/get a new token.
public saveThing(ThingCommand cmd) {
Map model = [:]
withForm {
try {
thingService.saveThing(cmd)
model.success = true
} catch (Exception e) {
model.error = true //any validation errors or anything else
// RESET TOKEN HERE/GET NEW TOKEN?
}
}.invalidToken {
model.invalidToken = true
}
render model as JSON
}
From my understanding the token is thrown away once the withForm closure is executed. This causes an issue since I don't actually re-render the form which seems to be the normal way of generating a new token. How could I do this manually or is there an easier way to do this (plugin?)
Thanks!
Form tokens through withForm are not designed to be used with AJAX requests. They are designed to be used with HTML forms and POST requests which re-render the form and generate a new token for the form.
In order to make them work with JSON/AJAX requests you will need to implement your own token generation when you process the request and reject it. A good starting place would be to look at the old tests which test withForm. This should give you an idea on how tokens are created and stored.

CSRFGuard - request token does not match session token

I am trying to incorporate the CSRFGuard library in order to rectify some CSRF vulnerabilties in an application. However after configuring as specified here I am now getting the below messages in the log, when I navigate the application:
WARNING: potential cross-site request forgery (CSRF) attack thwarted (user:<anonymous>, ip:169.xx.x.xxx, uri:/myapp/MyAction, error:request token does not match session token)
Through including the:
<script src="/sui/JavaScriptServlet"></script>
On my main.jsp page the links have all been built incorporating the CSRFGuard token, e.g.
......./myapp/MyAction?CSRFTOKEN=BNY8-3H84-6SRR-RJXM-KMCH-KLLD-1W45-M18N
So I am unable to understand what I'm doing wrong that could cause the links to pass a token other than the expected value.
Please let me know if any additional information would make it easier to understand.
In case anyone stumbles across a similar issue:
Turned out that accessing the app using IE wasn't passing a token to an AJAX call, this would in turn result in the tokens being refreshed but the links in the already rendered page remained, causing the mismatch when clicked.
Found out the issue by building CSRFGuard myself from source and adding extra logging.
The primefaces commandlink and commandbutton seem to cause the csrfguard javascript to malfunction, if you have use these two component with ajax set to true (which is the default), it can prevent the token being injected after the ajax call
One of the possible fixes is to change the following 2 lines in Owasp.CsrfGuard.js file.
Change
function injectTokenForm(form, tokenName, tokenValue, pageTokens) {
var action = form.attribute("action");
To
function injectTokenForm(form, tokenName, tokenValue, pageTokens) {
var action = form.attributes["action"].value;
AND
Change
function injectTokenAttribute(element, attr, tokenName, tokenValue, pageTokens) {
location = element.getAttribute(attr);
To
function injectTokenAttribute(element, attr, tokenName, tokenValue, pageTokens) {
var location = null;
if (attr == "action") {
location = element.attributes[attr].value;
} else {
location = element.getAttribute(attr);
}