Skip to content

Commit ea276a7

Browse files
committed
[core] autorize
--added function to check token expiration --added function to extend token --fix in token manager view(hide current auth token) --logged in token - life span based on configs
1 parent 4fb2469 commit ea276a7

File tree

5 files changed

+133
-6
lines changed

5 files changed

+133
-6
lines changed

api/utils/authorizer.js

+64-1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,68 @@ var crypto = require("crypto");
8282
options.db.collection("auth_tokens").findOne({_id:options.token}, options.callback);
8383
};
8484

85+
/**
86+
* Checks if token is not expired yet
87+
* @param {object} options - options for the task
88+
* @param {object} options.db - database connection
89+
* @param {string} options.token - token to rvalidate
90+
* @param {function} options.callback - function called when reading was completed or errored, providing error object as first param, true or false if expired as second, seconds till expiration as third.(-1 if never expires, 0 - if expired)
91+
*/
92+
authorizer.check_if_expired =function(options){
93+
options.db = options.db || common.db;
94+
options.token = options.token;
95+
options.db.collection("auth_tokens").findOne({_id:options.token},function(err, res){
96+
var expires_after = 0;
97+
var valid=false;
98+
if(res) {
99+
if(res.ttl>0 && res.ends >= Math.round(Date.now()/1000)){
100+
valid = true;
101+
expires_after = res.ends - Math.round(Date.now()/1000);
102+
}
103+
else if(res.ttl==0) {
104+
valid=true;
105+
expires_after=-1;
106+
}
107+
}
108+
options.callback(err,valid,expires_after);
109+
});
110+
}
111+
112+
/**
113+
* extent token life spas
114+
* @param {object} options - options for the task
115+
* @param {object} options.db - database connection
116+
* @param {string} options.token - token to extend
117+
* @param {string} options.extendBy - extend token by given time(in ms)(optional) You have to provide extedBy or extendTill. extendBy==0 makes it never die
118+
* @param {string} options.extendTill - extend till given timestamp. (optional) You have to provide extedBy or extendTill
119+
* @param {function} options.callback - function called when reading was completed or errored, providing error object as first param and true as second if extending successful
120+
*/
121+
authorizer.extend_token = function(options) {
122+
if(!options.token || options.token=="") {
123+
if(typeof options.callback === "function")
124+
options.callback(Error("Token not provided"),null);
125+
return;
126+
}
127+
options.db = options.db || common.db;
128+
var updateArr ={ttl:0,ends:0};
129+
if( options.extendBy){
130+
updateArr["ends"] = Math.round((options.extendBy+Date.now())/1000);
131+
updateArr["ttl"] = options.extendBy;
132+
}
133+
else if(options.extendTill) {
134+
updateArr["ends"] = Math.round(options.extendTill/1000);
135+
updateArr["ttl"] = 1;
136+
}
137+
else {
138+
if(typeof options.callback === "function")
139+
options.callback(Error("Please provide extendTill or extendBy"),null);
140+
return;
141+
}
142+
options.db.collection("auth_tokens").update({_id:options.token},{$set:updateArr},function(err, res){
143+
if(typeof options.callback === "function")
144+
options.callback(err,true);
145+
});
146+
}
85147
/**
86148
Token validation function called from verify and verify return
87149
*/
@@ -90,7 +152,8 @@ var crypto = require("crypto");
90152
options.token = options.token;
91153

92154
if(!options.token || options.token=="") {
93-
options.callback(false);
155+
if(typeof options.callback === "function")
156+
options.callback(false);
94157
return;
95158
}
96159
else {

api/utils/requestProcessor.js

+16
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,22 @@ const processRequest = (params) => {
14701470
}
14711471
case '/o/token': {//returns all my tokens
14721472
switch (paths[3]) {
1473+
case 'check':
1474+
if (!params.qstring.token) {
1475+
common.returnMessage(params, 400, 'Missing parameter "token"');
1476+
return false;
1477+
}
1478+
1479+
validateUser(params, function(){
1480+
authorize.check_if_expired({token:params.qstring.token,db:common.db,callback: (err,valid,time_left)=>{
1481+
if(err)
1482+
common.returnMessage(params,404,err.message);
1483+
else
1484+
common.returnMessage(params,200,{valid:valid,time:time_left});
1485+
}
1486+
});
1487+
});
1488+
break;
14731489
case 'list':
14741490
validateUser(params, function(){
14751491
common.db.collection("auth_tokens").find({"owner":params.member._id+""}).toArray(function(err, res){

frontend/express/app.js

+25-5
Original file line numberDiff line numberDiff line change
@@ -442,9 +442,29 @@ app.get(countlyConfig.path+'/', function (req, res, next) {
442442
res.redirect(countlyConfig.path+'/login');
443443
});
444444

445-
445+
var getSessionTimeoutInMs = function(req) {
446+
var myTimeoutValue = parseInt(plugins.getConfig("frontend", req.session && req.session.settings).session_timeout)*1000*60;
447+
if(myTimeoutValue>2147483647) //max value used by set timeout function
448+
myTimeoutValue = 1800000;//30 minutes
449+
return myTimeoutValue;
450+
}
446451
var extendSession = function(req, res, next){
447-
req.session.expires = Date.now() + parseInt(plugins.getConfig("frontend", req.session && req.session.settings).session_timeout)*1000*60;
452+
req.session.expires = Date.now() + getSessionTimeoutInMs(req);
453+
if(req.session.auth_token) {
454+
var ChangeTime = getSessionTimeoutInMs(req);
455+
if(ChangeTime>0) {
456+
authorize.extend_token({token:req.session.auth_token,db: countlyDb,extendTill:Date.now() + ChangeTime},function(err,res) {
457+
if(err)
458+
console.log(err);
459+
});
460+
}
461+
else { //changed to not expire
462+
authorize.extend_token({token:req.session.auth_token,db: countlyDb,extendBy:0},function(err,res) {
463+
if(err)
464+
console.log(err);
465+
});
466+
}
467+
}
448468
};
449469
var checkRequestForSession = function(req, res, next){
450470
if(parseInt(plugins.getConfig("frontend", req.session && req.session.settings).session_timeout)){
@@ -905,7 +925,7 @@ app.post(countlyConfig.path+'/setup', function (req, res, next) {
905925
req.session.gadm = !0;
906926
req.session.email = member[0].email;
907927
req.session.install = true;
908-
authorize.save({db:countlyDb,multi:true,owner:req.session.uid,purpose:"LoggedInAuth",callback:function(err,token){
928+
authorize.save({db:countlyDb,multi:true,owner:req.session.uid,purpose:"LoggedInAuth", ttl: getSessionTimeoutInMs(req),callback:function(err,token){
909929
if(err){console.log(err);}
910930
if(token)
911931
{
@@ -925,7 +945,7 @@ app.post(countlyConfig.path+'/setup', function (req, res, next) {
925945
req.session.email = member[0].email;
926946
req.session.install = true;
927947

928-
authorize.save({db:countlyDb,multi:true,owner:req.session.uid,purpose:"LoggedInAuth",callback:function(err,token){
948+
authorize.save({db:countlyDb,multi:true,owner:req.session.uid,purpose:"LoggedInAuth", ttl: getSessionTimeoutInMs(req), callback:function(err,token){
929949
if(err){console.log(err);}
930950
if(token)
931951
{
@@ -1047,7 +1067,7 @@ app.post(countlyConfig.path+'/login', function (req, res, next) {
10471067
});
10481068
}
10491069
//create token
1050-
authorize.save({db:countlyDb,multi:true,owner:req.session.uid,purpose:"LoggedInAuth",callback:function(err,token){
1070+
authorize.save({db:countlyDb,multi:true,owner:req.session.uid, ttl: getSessionTimeoutInMs(req), purpose:"LoggedInAuth",callback:function(err,token){
10511071

10521072
if(err){console.log(err);}
10531073
if(token)

frontend/express/public/javascripts/countly/countly.views.js

+4
Original file line numberDiff line numberDiff line change
@@ -4533,6 +4533,10 @@ window.TokenManagerView = countlyView.extend({
45334533
if(dataChanged) {
45344534
$.when(countlyTokenManager.initialize()).then(function () {
45354535
var tableData = countlyTokenManager.getData();
4536+
for(var i=0; i<tableData.length; i++){
4537+
if(tableData[i]._id == countlyGlobal['auth_token'])
4538+
tableData.splice(i,1);
4539+
}
45364540
CountlyHelpers.refreshTable(self.dtable, tableData);
45374541
self.add_scripts_to_table();
45384542
});

plugins/plugins/api/api.js

+24
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,16 @@ var plugin = {},
149149
}
150150
}
151151
if(Object.keys(data).length > 0){
152+
if(data["frontend"] && typeof data['frontend']['session_timeout']!== "undefined") {
153+
var updateArr ={"ttl":0,"ends":0};
154+
if( data['frontend']['session_timeout']){
155+
updateArr["ends"] = data['frontend']['session_timeout']*60+Math.round(Date.now()/1000);
156+
updateArr["ttl"] = data['frontend']['session_timeout']*60;
157+
}
158+
common.db.collection("auth_tokens").update({"owner":ob.params.member._id+"","purpose":"LoggedInAuth"},{$set:updateArr},function(err, res1){
159+
if(err){console.log(err);}
160+
});
161+
}
152162
plugins.dispatch("/systemlogs", {params:params, action:"change_configs", data:{before:plugins.getAllConfigs(), update:data}});
153163
plugins.updateAllConfigs(common.db, data, function(){
154164
plugins.loadConfigs(common.db, function(){
@@ -192,6 +202,20 @@ var plugin = {},
192202
}
193203
}
194204
if(Object.keys(data).length > 0){
205+
if(data["frontend"] && typeof data['frontend']['session_timeout']!== "undefined") {
206+
var updateArr ={"ttl":0,"ends":0};
207+
if( data['frontend']['session_timeout']){
208+
updateArr["ends"] = data['frontend']['session_timeout']*60+Math.round(Date.now()/1000);
209+
updateArr["ttl"] = data['frontend']['session_timeout']*60;
210+
}
211+
212+
if(params.member.settings && params.member.settings["frontend"] && typeof data['frontend']['session_timeout']!== "undefined") {}
213+
else {//if not set member value
214+
common.db.collection("auth_tokens").update({"owner":ob.params.member._id+"","purpose":"LoggedInAuth"},{$set:updateArr},function(err, res1){
215+
if(err){console.log(err);}
216+
});
217+
}
218+
}
195219
plugins.updateUserConfigs(common.db, data, params.member._id, function(){
196220
common.returnOutput(params, plugins.getUserConfigs(params.member.settings));
197221
});

0 commit comments

Comments
 (0)