Sails.js CORS for post method - sails.js

I was able to use CORS for a specific controller using a GET request like the following:
'get /url': {
controller: 'somecontroller',
action: 'someaction',
cors: true
},
However if I try using POST like the following, I get "Access Denied" error:
'post /url': {
controller: 'somecontroller',
action: 'someaction',
cors: true
},
How do I setup cors for a post method?

in config/routes.js before declaring routes put :
'OPTIONS /*': function(req, res) {
res.send(200);
},
and in config/cors.js try to put :
module.exports.cors = {
allRoutes: true,
origin: '*',
credentials: true,
methods: 'GET, POST, PUT, DELETE, OPTIONS, HEAD',
headers: 'content-type, access-control-allow-origin, authorization'
};

With my limited research I found out that simply adding "cors: true" to the controller doesn't solve the problem. Sails is still expecting a csrf token for the post method. In the bootstrap.js file under config folder, I added the following code at the bottom to disable csrf token on the route by using the following:
sails.config.csrf.routesDisabled = '/url';
If you have better solutions, please post them here. Thanks!
Edit: You can also change this in the config/csrf.js file. Change module.exports.csrf = true; to:
module.exports.csrf = {
routesDisabled: '/url',
};
You might have to use it for your apis
module.exports.csrf = {
routesDisabled: '/api/*',
};

Related

How can I reach the 'Retry-After' response header using axios?

I'm building a simple Vue2 app with Auth section, which makes requests to REST API service.
So, I have my axios instance:
const instance = axios.create({
baseURL: BASE_URL,
timeout: DEFAULT_TIMEOUT,
withCredentials: true,
headers: {
accept: 'application/json',
},
});
To make authorization requests I use a separate module:
const auth = (api) => ({
submitPhoneNumber({ userPhone }) {
return api.get(`auth/${userPhone}`);
},
});
And set it all up together like this:
export default {
auth: auth(instance),
};
Then I add my api to Vue as a plugin:
export default {
install(Vue) {
const vueInstance = Vue;
vueInstance.prototype.$api = api;
},
};
In the component I access my api-plugin and make a request, extracting status and headers from it:
const { status, headers } = await this.$api.auth.submitPhoneNumber({
userPhone: this.userPhone,
});
When I look through the response in chrome devtools, I clearly see a "retry-after" header with number of seconds, after which I can make another request.
Upon receiving the response, I would like to save this number of seconds to some variable and then render a warning message like "Please wait { seconds } to make another submit".
The problem is that in my code I have no such header in the response (while I can see it in devtools, a I said):
see the screenshot
So, when logging the headers from my response, there are just these:
{content-length: '19', content-type: 'application/json; charset=utf-8'}
What is the problem with that?
Try var retrysec = error.response.data.retry_after that worked for me

X-XSRF-TOKEN header with axios

Do I have to set anything to send X-XSRF-TOKEN header if I set a XSRF-TOKEN cookie server side?
https://github.com/axios/axios/blob/master/lib/defaults.js#L74
https://github.com/axios/axios/blob/master/dist/axios.js#L1072
It reads like I don't, but I'm not seeing one go out.
I'll add that I have set withCredentials to true, so I do meet the first check in the OR:
var xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ?
cookies.read(config.xsrfCookieName) :
undefined;
if (xsrfValue) {
requestHeaders[config.xsrfHeaderName] = xsrfValue;
}
so if config.xsrfCookieName is a default.....
Update:
So, my OPTIONS preflight CORS is working, as is the POST now, but no X-XSRF-TOKEN being sent.
methods: {
onSubmit(e) {
this.axios
.post(
e.target.action,
{ data: this.form },
{
withCredentials: true,
xsrfCookieName: "XSRF-TOKEN",
xsrfHeaderName: "X-XSRF-TOKEN"
}
)
.then(res => {
console.log(res)
})
.catch(err => {
this.errors.push(err)
})
}
}
Thanks.
I had the same issue and was about the "secure" flag on the cookie as can be seen on the cookies tab of the request, but is not showing on the cookies under "application" tab:
In my case, I had to ask the backend to set it down.
This happens because, as secure, you cannot access to it via javascript.
document.cookie // is empty

Cache-control directive (only-if-cached) changed by dev-tools?

We are working on a Progessive Web App, for which the service worker intercepts the network traffic (via the fetch event handler). We have noticed, that sometimes a certain request fails here, because Request.cache is only-if-cached and Request.mode is no-cors, but not same-origin.
So it is similar to this problem.
Then I've noticed, that this happens only when the Chrome (v 65) DevTools are not opened. Does anybody notice the same phenomenon and does anybody have an idea, why this happens this way?
Parts of the request:
bodyUsed: false,
cache: "only-if-cached",
credentials: "include",
destination: "unknown",
headers: Headers {},
integrity: "",
method: "GET",
mode: "no-cors",
redirect: "follow",
referrer: "",
referrerPolicy: "no-referrer-when-downgrade",
url: "https://example.com/path/to/app-name/#!
We are handling this problem like this, but I'm afraid, that this is not appropriate.
serviceWorkerGlobal.addEventListener('fetch', function(event)
{
if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') {
var oStrangeRequest = event.request.clone();
console.log('Fetch. Request cache has only-if-cached, but not same-origin.',
oStrangeRequest.cache, oStrangeRequest.mode,
'request redirect:',
oStrangeRequest.redirect, oStrangeRequest.url, oStrangeRequest);
return;
}
// ...
});
This is a bug. You can check the progress of the fix here: https://bugs.chromium.org/p/chromium/issues/detail?id=823392

Permissive CORS check in meanjs.org application during development?

I am using meanjs.org stack to develop a simple application. Now I am woking on the mobile client with ionic framework.
Current issue I have is the CORS check causes an error when testing the ionic app like is described here: http://blog.ionic.io/handling-cors-issues-in-ionic/
While I could set up a proxy as described in that link it also works if I add the response header to the server side like: res.header("Access-Control-Allow-Origin", "*");
Adding this to each endpoint doesn't feels good and I would like to find a solution to use during development where I could disable the CORS check.
I've also tried changing the lusca configuration on config/env/default.js setting xssProtection: false bit didn't work?
How can I, during development, enable the following response header res.header("Access-Control-Allow-Origin", "*"); in all endpoints, is it possible or the only viable solution using meanjs.org + ionic during development is setting up the proxy?
Thank you
For development you can set proxy to avoid CORS issues,
Set up your ionic.project file to be something like:
{
"name": "proxy-example",
"app_id": "",
"proxies": [{
"path": "/api",
"proxyUrl": "http://example.com/api"
}]
}
Then from controller call api like below,
.controller('MyController', function($http) {
$http.post('/api/getMoreDeatils',data)
.then(function (response) {
//do something
})
})
Hope this is helpful for you
Try to use a middleware like this in your server main file:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
After some time I finally got a hint on the meanjs.org forums and built a solution.
Create the following method on config/lib/express.js file:
/**
* Disable CORS check to be used during development with access from mobile clients (currently tested with ionic)
*/
module.exports.disableCORSForDev = function(app) {
app.all('/*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'POST');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
next();
}).options('*', function(req, res) {
res.end();
});
var corsOptionsDelegate = function(req, callback) {
var corsOptions = { credentials: true };
callback(null, corsOptions); // callback expects two parameters: error and options
};
app.use(cors(corsOptionsDelegate));
};
added the following to the method init on this same class just after declaration of var app = express();
var app = express();
this.disableCORSForDev(app);
Note: This is a server side solution to bypass cors during development and should not be used in production, many may prefer to setup a proxy on the ionic client instead as it's described in this ionic article.

AngularJS ngResrouce REST Authentication

I'm trying to learn AngularJS. I'm try to make a simple authenticated get request to a REST api. At this point, i'm just trying to get a response back. I keep getting invalid key because I can't seem to send the headers properly.
angular.module('App', ['ngResource']);
function AppCtrl($scope, $resource){
$scope.app = $resource('https://theapiurl.com/parameter=:action',
{action:'My Parameter works fine!'},
{method: 'GET'},
{headers: 'auth-key' : 'key'});
$scope.app.get();
}
I just can't seem to get the header to send. Thanks for reading.
If you are using angular-resource 1.1.x+ the following should work:
angular.module('App', ['ngResource']);
function AppCtrl($scope, $resource){
$scope.app = $resource('https://theapiurl.com/parameter=:action',
{
action:'My Parameter works fine!'
},
{
get: {
method: 'GET',
headers : { 'auth-key' : 'key' }
}
});
$scope.app.get();
}
If you are using 1.0.x branch this won't work. I believe the only alternative is to set global default headers in $httpProvider, or to user $http directly (not using $resource). Here's how you would set the headers globally:
$httpProvider.defaults.headers.get['auth-key'] = 'key';
To avoid setting the header in every resource you could use an interceptor:
app.config(function($httpProvider) {
$httpProvider.interceptors.push(function($q) {
return {
'request': function(config) {
config.headers['auth-key'] = 'key';
return $q.when(config);
}
};
});
});