Skip to content

HTTP basic authentication, more conf.json options, minor edits #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 77 additions & 19 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
process.env.NODE_ENV = 'production';
//process.env.NODE_ENV = 'development';

require('./logger.js');
logger.level = 'info';

var fs = require('fs');
var http = require('http');
var express = require('express');
Expand Down Expand Up @@ -67,7 +70,7 @@ global.randomValue = function (qty) {
return crypto.randomBytes(qty).toString(2);
};

var logDirectory = __dirname + '/log';
var logDirectory = global.logDir;

// ensure log directory exists
fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory);
Expand Down Expand Up @@ -117,7 +120,7 @@ if (use_clustering) {
cluster.fork();
});

db.connect(usedbhost, 3306, 'root', usedbpass, function (rsc) {
db.connect(usedbhost, 3306, usedbname, usedbuser, usedbpass, function (rsc) {
if (rsc == '1') {
cb.create(function (rsp) {
console.log(JSON.stringify(rsp));
Expand Down Expand Up @@ -149,7 +152,7 @@ if (use_clustering) {
// app.use(bodyParser.text({limit: '1mb', type: 'application/*+xml' }));


db.connect(usedbhost, 3306, 'root', usedbpass, function (rsc) {
db.connect(usedbhost, 3306, usedbname, usedbuser, usedbpass, function (rsc) {
if (rsc == '1') {
if(usesecure === 'disable') {
http.globalAgent.maxSockets = 1000000;
Expand Down Expand Up @@ -179,7 +182,7 @@ if (use_clustering) {
}
}
else {
db.connect(usedbhost, 3306, 'root', usedbpass, function (rsc) {
db.connect(usedbhost, 3306, usedbname, usedbuser, usedbpass, function (rsc) {
if (rsc == '1') {
cb.create(function (rsp) {
console.log(JSON.stringify(rsp));
Expand Down Expand Up @@ -457,6 +460,24 @@ function check_http_body(request, response, callback) {
}

function check_http(request, response, callback) {
// [TIM] if configured check authorization before checking other headers
var body_Obj = {};

if (authorization) {
auth.check_head_auth(request, response, function(rsc) {
if (rsc == '0') {
callback('0', body_Obj);
return '0';
} else {
_check_http(request, response, callback);
}
});
} else {
_check_http(request, response, callback);
}
}

function _check_http(request, response, callback) {
request.headers.rootnm = 'dbg';

var body_Obj = {};
Expand Down Expand Up @@ -1449,6 +1470,9 @@ var onem2mParser = bodyParser.text(
);
//var onem2mParser = bodyParser.text({ limit: '1mb', type: '*/*' });

// [TIM] import auth library and config it
const auth = require("./auth.js");
auth.init({onem2mParser:onem2mParser, responder:responder, crypto:crypto, db:db, db_sql:db_sql, logger:logger});

//////// contribution code
// Kevin Lee, Executive Director, Unibest INC, Owner of Howchip.com
Expand Down Expand Up @@ -1514,7 +1538,7 @@ app.post(onem2mParser, function (request, response) {
responder.error_result(request, response, 500, 5000, body_Obj['dbg']);
}
else if (rsc == '1') {
forward_http(body_Obj.forwardcbhost, body_Obj.forwardcbport, request, response);
forward_http(body_Obj, request, response);
}
else if (rsc == '2') {
responder.error_result(request, response, 500, 5000, 'forwarding with mqtt is not supported');
Expand Down Expand Up @@ -1580,7 +1604,7 @@ app.get(onem2mParser, function (request, response) {
responder.error_result(request, response, 500, 5000, body_Obj['dbg']);
}
else if (rsc == '1') {
forward_http(body_Obj.forwardcbhost, body_Obj.forwardcbport, request, response);
forward_http(body_Obj, request, response);
}
else if (rsc == '2') {
responder.error_result(request, response, 500, 5000, 'forwarding with mqtt is not supported');
Expand Down Expand Up @@ -1650,7 +1674,7 @@ app.put(onem2mParser, function (request, response) {
responder.error_result(request, response, 500, 5000, body_Obj['dbg']);
}
else if (rsc == '1') {
forward_http(body_Obj.forwardcbhost, body_Obj.forwardcbport, request, response);
forward_http(body_Obj, request, response);
}
else if (rsc == '2') {
responder.error_result(request, response, 500, 5000, 'forwarding with mqtt is not supported');
Expand Down Expand Up @@ -1719,7 +1743,7 @@ app.delete(onem2mParser, function (request, response) {
responder.error_result(request, response, 500, 5000, body_Obj['dbg']);
}
else if (rsc == '1') {
forward_http(body_Obj.forwardcbhost, body_Obj.forwardcbport, request, response);
forward_http(body_Obj, request, response);
}
else if (rsc == '2') {
responder.error_result(request, response, 500, 5000, 'forwarding with mqtt is not supported');
Expand All @@ -1744,15 +1768,17 @@ function check_csr(absolute_url, callback) {
body_Obj.forwardcbname = result_csr[0].cb.replace('/', '');
var poa_arr = JSON.parse(result_csr[0].poa);
for (var i = 0; i < poa_arr.length; i++) {
if (url.parse(poa_arr[i]).protocol == 'http:') {
var prot = url.parse(poa_arr[i]).protocol;
if (prot == 'http:' || prot == 'https:') {
body_Obj.forwardcbprot = prot;
body_Obj.forwardcbhost = url.parse(poa_arr[i]).hostname;
body_Obj.forwardcbport = url.parse(poa_arr[i]).port;

console.log('csebase forwarding to ' + body_Obj.forwardcbname);

callback('1', body_Obj);
}
else if (url.parse(poa_arr[i]).protocol == 'mqtt:') {
else if (prot == 'mqtt:') {
body_Obj.forwardcbmqtt = url.parse(poa_arr[i]).hostname;

callback('2', body_Obj);
Expand All @@ -1778,16 +1804,48 @@ function check_csr(absolute_url, callback) {
}


function forward_http(forwardcbhost, forwardcbport, request, response) {
var options = {
hostname: forwardcbhost,
port: forwardcbport,
path: request.url,
method: request.method,
headers: request.headers
};
function forward_http(body_Obj, request, response) {
// [TIM} manage localhost, http and https, assuming there is a proxy configured
var path = request.url.replace(body_Obj.csr, body_Obj.forwardcbname);
var uri = body_Obj.forwardcbprot+"//"+body_Obj.forwardcbhost+":"+body_Obj.forwardcbport+path;
var ssl = body_Obj.forwardcbprot.indexOf("https:")!==-1;
var _http = http;
if (ssl) {
var HttpsProxyAgent = require('https-proxy-agent');
console.log('[forward_https] uri: ' + uri);
var agent = new HttpsProxyAgent(process.env.https_proxy);
var options = {
hostname: body_Obj.forwardcbhost,
port: body_Obj.forwardcbport,
path: path,
method: request.method,
headers: request.headers,
agent: agent
};
_http = https;
} else {
console.log('[forward_http] uri: ' + uri);
if (process.env.http_proxy) {
var options = {
hostname: url.parse(process.env.http_proxy).hostname,
port: url.parse(process.env.http_proxy).port,
path: uri,
method: request.method,
headers: request.headers
};
} else {
var options = {
hostname: body_Obj.forwardcbhost,
port: body_Obj.forwardcbport,
path: request.url,
method: request.method,
headers: request.headers
};
}
_http = http;
}

var req = http.request(options, function (res) {
var req = _http.request(options, function (res) {
var fullBody = '';
res.on('data', function (chunk) {
fullBody += chunk.toString();
Expand Down
170 changes: 170 additions & 0 deletions auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/

var onem2mParser, responder, crypto, db, db_sql;


function check_head_auth(request, response, callback) {
// Check Authorization Header
var ip = request.headers['x-forwarded-for'] || request.connection.remoteAddress;
var agent = request.headers['user-agent'];
//logger.log("debug",'>>>>>>>ip:',ip, ip.indexOf("127.0.0.1"), request.url);

if (agent==undefined) {
// it happens when locally invoked
//logger.log("debug",'>>>>>>>NO user-agent!!!!!!!!!!!!');
callback('1');
return '1';
} else {
// external request
//logger.log("debug",'>>>>>>>user-agent:',agent);
}

if ((request.headers['authorization'] == null || request.headers['authorization'] == '')) {

request.headers.rootnm = 'dbg';
request.headers.usebodytype = 'json';

responder.error_result(request, response, 401, 4001, 'Authorization Header is null');
callback('0');
return '0';
} else {
// auth header present
var context = request.url.split(/[?#]/)[0].replace("/"+usecsebase+"/", "").split("/")[0];
var auth = request.headers['authorization'].replace("Basic ", "").trim();
auth = new Buffer(auth, 'base64').toString();
//logger.log("debug",'>>>>>>>auth: ',request.headers['authorization'],auth,"context:",context,"url:",request.url);
var usr_parts = auth.split(":");
//logger.log("debug",'>>>>>>>usr_parts: ',usr_parts);
if (usr_parts.length!=2) {
responder.error_result(request, response, 401, 4001, 'Unauthorized');
callback('0');
return '0';
}
// superadm_usr
if (usr_parts[0]==superadm_usr && usr_parts[1]==superadm_pwd) {
//logger.log("debug",'>>>>>>>user: SUPERADMIN');
callback('1');
return '1';
}
// check other users
if (request.url=="/"+usecsebase) {
// root not accessible for other users
responder.error_result(request, response, 401, 4001, 'Unauthorized');
callback('0');
return '0';
}
var pwd_hash = crypto.createHash('sha256').update(usr_parts[1]).digest('base64');
db_sql.get_user(usr_parts[0],
function (user_Obj) {
logger.log("debug",'>>>>>>>user: ',user_Obj);
if (user_Obj==null || (Array.isArray(user_Obj) && user_Obj.length==0)) {
// user not present
responder.error_result(request, response, 401, 4001, 'Unauthorized');
callback('0');
return '0';
} else if (user_Obj[0].password!=pwd_hash) {
// password not match
responder.error_result(request, response, 401, 4001, 'Unauthorized');
callback('0');
return '0';
} else {
logger.log("debug",'>>>>>>>user2: ',user_Obj,"url:",request.url);
// ok user present
if (user_Obj[0].role=="tenant") {
if (user_Obj[0].context.indexOf(context)!=-1 && context) {
// ok, context enabled fot this user
callback('1');
return '1';
} else {
// context not match
responder.error_result(request, response, 403, 4003, 'Forbidden');
callback('0');
return '0';
}
} else if (user_Obj[0].role=="guest") {
logger.log("debug",'>>>>>>>user: ',request.url, user_Obj);
var uris = user_Obj[0].context.split(","), test = false;
for (var k in uris) {
// if (request.url.indexOf(uris[k])==0) test = true;
if (request.url == uris[k]) {
test = true;
break;
} else if (match(request.url, uris[k])) {
test = true;
break;
}
}
if (test) {
// ok, context enabled fot this user
if (request.method=="POST") {
try {
var content_type = request.headers['content-type'].split(';');
}
catch (e) {
responder.error_result(request, response, 400, 4000, 'content-type is null');
callback('0');
return '0';
}
try {
var ty = content_type[1].split('=')[1];
}
catch (e) {
responder.error_result(request, response, 400, 4000, 'ty is null');
callback('0');
return '0';
}
if (ty=='4' || ty=='23') {
// ok, context and POST CIN, SUB enabled fot this guest
callback('1');
return '1';
} else {
responder.error_result(request, response, 415, 4015, 'You are not enabled to create resource of this type');
callback('0');
return '0';
}
} else if (request.method=="GET") {
callback('1');
return '1';
} else {
responder.error_result(request, response, 405, 4005, 'Method Not Allowed');
callback('0');
return '0';
}
} else {
// context not match
responder.error_result(request, response, 403, 4003, 'Forbidden');
callback('0');
return '0';
}

}
}
}
);
}

function match(txt, regularExpression) {
var re1 = new RegExp('^'+regularExpression+'/');
var re2 = new RegExp('^'+regularExpression+'?');
return re1.test(txt) || re2.test(txt);
}
}

module.exports = {};

module.exports.check_head_auth = check_head_auth;

module.exports.init = function(deps){
console.log('[auth].init');
// dependencies
onem2mParser = deps.onem2mParser;
responder = deps.responder;
crypto = deps.crypto;
db_sql = deps.db_sql;
db = deps.db;
logger = deps.logger;
}
18 changes: 17 additions & 1 deletion conf.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
{
"csebase": "onem2m",
"cseid": "/onem2m",
"csebaseport": "7579",
"dbpass": "dksdlfduq2"
"csetype": "in",
"dbhost": "localhost",
"dbuser": "mobius",
"dbpass": "mobius",
"dbname": "mobiusdb",
"superadm_usr": "superadmin",
"superadm_pwd": "f7c6c12d",
"pxymqttport": 7580,
"pxycoapport": 5683,
"pxywsport": 7577,
"tsagentport": 7582,
"mqttbroker": "localhost",
"secure": "disable",
"authorization": true,
"logDir": "./log"
}
Loading