Koajs: How to check current connection is over https or not? - https

I am using koajs, I have a router like the following and I want to detect if user is requesting via https, how can I achieve it?
router.get('/video', function(next){
if(request is over https) {
this.body = yield render('/video', {});
} else {
this.redirect('https://example.com/video');
}
});

You can use secure which is attached to the context's request object. It's also aliased onto the ctx itself.
Koa v1:
router.get('/video', function *(next) {
if (this.secure) {
// The request is over https
}
})
Koa v2:
router.get('/video', async (ctx, next) => {
if (ctx.secure) {
// The request is over https
}
})
ctx.secure is equivalent to checking that ctx.protocol === "https".
This is all mentioned in the Koa website docs, I would definitely recommend checking there first whenever you have a Koa-related question.

Related

Cypress blocks cookies sent from third party response when the same site attribute is not set. How to store such blocked cookie values and use them

We are trying to test a third party sign in (Single Sign On) flow using Cypress.
Cypress blocks cookies sent in third party response when the SameSite attribute is not set when tested with Electron V-94.
How to store such blocked cookie values and use them?
The same works when tested from normal browser with third party cookie even with no SameSite attribute set.
Is there a way to prevent cypress from blocking it or can the cookies received from third party can be stored and used? If so, how?
I've just been fighting the same issue, I resolved it by intercepting all requests, checking if they had a set-cookie header(s) and rewriting the SameSite attribute. There's probably a neater way to do it, as this does clutter up the cypress dashboard a little. You can add this as a command for easy reuse:
In your commands file:
declare namespace Cypress {
interface Chainable<Subject> {
disableSameSiteCookieRestrictions(): void;
}
}
Cypress.Commands.add('disableSameSiteCookieRestrictions', () => {
cy.intercept('*', (req) => {
req.on('response', (res) => {
if (!res.headers['set-cookie']) {
return;
}
const disableSameSite = (headerContent: string): string => {
return headerContent.replace(/samesite=(lax|strict)/ig, 'samesite=none');
}
if (Array.isArray(res.headers['set-cookie'])) {
res.headers['set-cookie'] = res.headers['set-cookie'].map(disableSameSite);
} else {
res.headers['set-cookie'] = disableSameSite(res.headers['set-cookie']);
}
})
});
});
Usage:
it('should login using third party idp', () => {
cy.disableSameSiteCookieRestrictions();
//add test body here
});
or alteratively, run it before each test:
beforeEach(() => cy.disableSameSiteCookieRestrictions());

Sails - Access Controller function(req,res) from Service

I have a Controller method: DbController.create to create database entries. This is the following format:
create: function (req, res) {
var params = req.body;
Db.create({
...
There is a route for this Controller method:
'POST /createData': 'DbController.create'
I can use CURL to this URL with no problems (curl -X POST --data 'userId="testuser1"' http://localhost:1337/createData), and from my UI code I can call this using sails-io.js and io.socket.post(....).
The problem is that I want to use this from my Service now (DbService). I'm not sure how I can go about this, because simply using DbController.create requires a req and res parameter to be passed, but all I have is the data/params/body.
Thanks
The best way would be to move the create logic in some service method so that it can be used from anywhere in project. Once this is done, then invoke that method with necessary parameters from DbController.create as well as from some other service.
Sample:
// DBService:
createData: (params, callback) => {
Db.create(params)...
}
// DBController:
create: (req, res) => {
const params = req.body;
DBService.createData(params, (err, results) => {
if (err) {
return res.serverError(err);
}
return res.json(results);
});
}
// SomeOtherService:
someMethod: (params, callback) => {
DBService.createData(params, callback);
}
Another way (which will unnecessary make http request) is to make a HTTP call from service to the API endpoint of DbController.create from the service.

Sails.js: applying session and token authentication policies simultaniously

I am developing an application with sails.js. For the web application I use session authentication with passport. Now I also need to make my server accessibe from a mobile application, which requires token authentication. My question is the following: how can I define the policies so that sails accept SessionAuth or TokenAuth for certain routes?
The way sails handles policies, they are all applied one after another using AND logic. There is no way to combine them logically in other ways, like OR or more complicated combinations.
In your case, I would expect it would be fairly easy to write a third policy that handles the "SessionAuth or TokenAuth" all in one policy. Say you have existing SessionAuth.js and TokenAuth.js policies that look like this:
module.exports = function(req, res, next) {
if (req.isSessionAuthorized()) {
return next();
}
// handle rejected request
};
, and,
module.exports = function(req, res, next) {
if (req.isTokenAuthorized()) {
return next();
}
// handle rejected request
};
Then you just create a third policy called SessionOrTokenAuth.js:
module.exports = function(req, res, next) {
if (req.isSessionAuthorized() || req.isTokenAuthorized()) {
return next();
}
// handle rejected request
};
Then apply the newly created policy to the desired controller endpoints in /config/policies.js:
SomeController: {
'*': true,
'sessionOnlyEndpoint': ['SessionAuth'],
'tokenOnlyEndpoint': ['TokenAuth'],
'anyAuthEndpoint': ['SessionOrTokenAuth'],
}
The actual checks are likely a touch more complicated, but probably not by much. Hope this helps.

Node Express as proxy for a server that requires basic authentication

So I'm using express and express-http-proxy as a proxy to an API web server that requires basic authentication. Then in my app, I'll be issuing Ajax calls to these APIs. After some effort I got this working but I'm sure there's a better way out there, hence this post.
Initially I set up the express proxy as follows:
var express = require('express'),
app = express(),
proxy = require('express-http-proxy');
app.use('/apis', proxy("https://myserver", {
forwardPath: function(req, res) {
return "/apis" + require('url').parse(req.url).path;
}
}));
When calling a URL directly in the browser (not via Ajax), eg. https://myserver/apis/myapi.ashx, I would see the authentication dialog asking me for my credentials, and I could authenticate and see the result.
However, when accessing the same URL via an Ajax call in my app, I was not getting a popup. Why this difference of behavior?
So I decided I needed to add my own basic authentication middleware using request and basic-auth as follows:
var express = require('express'),
app = express(),
proxy = require('express-http-proxy'),
request = require('request'),
basicAuth = require('basic-auth');
var myAuth = function (req, res, next) {
function unauthorized(res) {
res.set('WWW-Authenticate', 'Basic realm=Rimes');
return res.sendStatus(401);
};
var user = basicAuth(req);
if (!user || !user.name || !user.pass) {
return unauthorized(res);
};
var connectUrl = 'https://'+user.name+':'+user.pass+'#myserver/apis/connect.ashx';
request.get(connectUrl, function(error, response, body) {
if (!error && response.statusCode == 200) {
return next();
} else {
return unauthorized(res);
}
});
};
app.use('/apis', proxy("https://myserver", {
forwardPath: function(req, res) {
return "/apis" + require('url').parse(req.url).path;
}
}));
This worked fine, showing me the authentication popup during the Ajax call.
The obvious disadvantage here is:
Credential verification for every API request, although there may be a way to cache valid credentials. But in its defence, this is only on the development environment.
So is there a better way of doing this? Would a different middleware package do a better job?

Detect Ajax and set layout null in SailsJs

I would implement pajax, i need to check server side if a request is ajax and set the layout to null to return the view without layout.
I know that the req object contain a 'xhr' property. How can i the layout to null automatically?
Thanks in advance!
EDIT: i find a solution! See here: https://stackoverflow.com/a/31571250/4870013
You can check req.wantsJSON object:
// True, if the request has a xhr polling origin. (via socket)
req.wantsJSON = req.xhr;
Example:
if (req.wantsJSON) {
res.view("yourView", { layout: null });
} else {
res.view("yourView");
}
you can use do this by detecting request
if(!Request.isAjax)
{
// your code with return Layout
}
else
{
// your code without return Layout
}
You can check request.headers if it contains HTTP_X_REQUESTED_WITH.
If HTTP_X_REQUESTED_WITH has a value of XMLHttpRequest then it is an ajax request.
Example:
if (request.headers["x-requested-with"] == 'XMLHttpRequest') {
//is ajax request
}
I find a solution! I use a policy to accomplish that result.
My policy:
module.exports = function(req, res, next) {
if (req.xhr) {
res.locals.layout = null;
}
return next();
};
And my policy config:
module.exports.policies = {
'*': 'isAjax'
};
Work like a charm!

Resources