Skip to content

Commit

Permalink
[ENG-1037] - Improved Authorization Code Grant to be true SSO one-click
Browse files Browse the repository at this point in the history
  • Loading branch information
Phara0h committed Sep 18, 2019
1 parent f6cf3a3 commit ba84e61
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 28 deletions.
12 changes: 6 additions & 6 deletions include/redis/memory/tokenstore.js
Expand Up @@ -8,25 +8,25 @@ class TokenStore {
this.tokens = {};
}

async set(user_id, type, token, expiration, name = '') {
async set(secret, type, id, expiration, name = '') {

setTimeout(()=>{
this.destroy(token);
this.destroy(id);
},expiration);

this.tokens[token] = {user_id,type,expires: new Date(expiration), name};
this.tokens[type+':'+id] = {id:type+':'+id, expires: new Date(expiration), name};

return this.tokens[token];
return this.tokens[type+':'+id];
}

async get(token, type) {

return this.tokens[token];
return this.tokens[type+':'+token];
}

async destroy(token, type) {
try {
delete this.tokens[token];
delete this.tokens[type+':'+token];
return true;
} catch(_){}
return false;
Expand Down
12 changes: 6 additions & 6 deletions include/redis/tokenstore.js
Expand Up @@ -9,22 +9,22 @@ class RedisTokenStore {
this.redis = redis;
}

async set(user_id, type, token, expiration, name = '') {
var nToken = {user_id,type,expires: new Date(expiration), name};
await this.redis.set(token, JSON.stringify(nToken), 'PX', expiration);
return token;
async set(secret, type, id, expiration, name = '') {
var nToken = {id:type+':'+id, secret, expires: new Date(expiration), name}
await this.redis.set(nToken.id, JSON.stringify(nToken), 'PX', expiration);
return nToken;
}

async get(token, type) {
var fToken = await this.redis.get(token);
var fToken = await this.redis.get(type+':'+token);
if(fToken) {
fToken = JSON.parse(fToken);
}
return fToken;
}

async destroy(token, type) {
await this.redis.del(token);
await this.redis.del(type+':'+token);
}
}

Expand Down
37 changes: 27 additions & 10 deletions include/routes/v1/auth.js
Expand Up @@ -246,13 +246,26 @@ module.exports = function(app, opts, done) {

// Authorization Code Grant
app.get('/auth/oauth/authorize', (req,res) =>{
TokenHandler.getRandomToken().then(token=>{
res.setCookie('trav:codecheck', token , {
expires: new Date(Date.now() + 12000),
secure: config.https,
path: '/travelling/api/v1/auth/oauth/authorize',
});
res.sendFile('index.html');

TokenHandler.isOAuthCodeExist(req.session.data.user.id, req.query.client_id).then(async token=>{
if(token || !config.token.code.authorizeFlow) {
if(!token) {
token = await TokenHandler.getOAuthCode(req.session.data.user.id, req.query.client_id);
}
var code = Buffer.from(`${token.id}:${token.secret}`, 'ascii').toString('base64');

res.redirect(encodeURI(req.query.redirect_uri+`?code=${code}&state=${req.query.state}&client_id=${req.query.client_id}`))
}
else {
TokenHandler.getRandomToken().then(token=>{
res.setCookie('trav:codecheck', token , {
expires: new Date(Date.now() + 12000),
secure: config.https,
path: '/travelling/api/v1/auth/oauth/authorize',
});
res.sendFile('index.html');
})
}
})
})

Expand All @@ -273,12 +286,16 @@ module.exports = function(app, opts, done) {
return
}


// check client_id
//if(!req.query.client_id || )

try {
token = await TokenHandler.getOAuthToken(req.session.data.user.id, 'code', req.query.client_id || null);
token = {client_id: token.name || token.id, client_secret: token.secret};
token = await TokenHandler.getOAuthCode(req.session.data.user.id, req.query.client_id);
token = {client_id: token.id, client_secret: token.secret};
var code = Buffer.from(`${token.client_id}:${token.client_secret}`, 'ascii').toString('base64');

res.redirect(encodeURI(req.query.redirect_uri+`?code=${code}&${req.req.url.split('?')[1]}`))
res.redirect(encodeURI(req.query.redirect_uri+`?code=${code}&state=${req.query.state}&client_id=${req.query.client_id}`))
return;
} catch (e) {
res.code(400).send({
Expand Down
56 changes: 50 additions & 6 deletions include/token/index.js
Expand Up @@ -15,7 +15,7 @@ class TokenHandler {
}


static async checkTempToken(token, expiration) {
static async checkTempToken(token, expiration, type) {
try {
var dToken = (await CookieToken.decrypt(token.replace(/-/g, '+').replace(/_/g, '\/'))).split('|');

Expand All @@ -26,7 +26,7 @@ class TokenHandler {
3 = userId
*/

var t = await TokenStore.get( await this._hashToken(dToken[3],dToken[0]));
var t = await TokenStore.get( await this._hashToken(dToken[3],dToken[0]), type);

if(t.user_id == dToken[3] && t.type == dToken[2] && Date.now() - Number(dToken[1]) < expiration) {
return dToken; // secret;
Expand Down Expand Up @@ -89,6 +89,35 @@ class TokenHandler {
});
}


static getOAuthCode(user_id, client_id, name = null) {
return new Promise((resolve, reject)=>{
crypto.randomBytes(32, async (err, secret) => {

if (err) {
reject(err);
return;
}

if(regex.safeName.exec(name) == null) {
reject(true);
return;
}

if(name) {
var fToken = await TokenStore.get(user_id+":"+client_id, 'code')
resolve(fToken);
return;
}

resolve(await TokenStore.set(secret.toString('hex'), 'code', user_id+":"+client_id, config.token.code.expiration * 60000)); // min to ms);
});
});
}




static getAccessToken(token) {
return new Promise((resolve, reject)=>{
crypto.randomBytes(16, async (err, secret) => {
Expand Down Expand Up @@ -122,7 +151,7 @@ class TokenHandler {
}

static async checkRandomToken(token) {
var token = await TokenStore.get(token);
var token = await TokenStore.get(token, 'random');

if(!token) {
return false;
Expand All @@ -133,7 +162,7 @@ class TokenHandler {
}

static async checkAccessToken(token) {
var token = await TokenStore.get(token);
var token = await TokenStore.get(token, 'access');

if(!token) {
return false;
Expand All @@ -157,17 +186,32 @@ class TokenHandler {
return token[0];
}

static async checkOAuthCode(id, secret) {
var token = await TokenStore.get(id, 'code');

if(!token || token.secret != secret) {
return false;
}

return token;
}

static async isOAuthCodeExist(user_id, client_id) {
var token = await TokenStore.get(user_id+":"+client_id, 'code');
return token || false;
}

static async deleteOAuthToken(id, user_id) {
var token = (await Token.deleteAllBy(regex.uuidCheck(id) ? {id, user_id} : {name:id, user_id}))[0];
return token;
}

static async checkRecoveryToken(token) {
return await this.checkTempToken(token, config.email.recovery.expiration * 1000)
return await this.checkTempToken(token, config.email.recovery.expiration * 1000, 'recovery')
}

static async checkActivationToken(token) {
return await this.checkTempToken(token, config.email.activation.expiration * 1000)
return await this.checkTempToken(token, config.email.activation.expiration * 1000, 'activation')
}

static async getRecoveryToken(userId) {
Expand Down
4 changes: 4 additions & 0 deletions include/utils/config.js
Expand Up @@ -76,6 +76,10 @@ const config = {
token: {
access: {
expiration: misc.isSetDefault(Number(process.env.TRAVELLING_TOKEN_ACCESS_EXPIRATION), 1440) //minutes
},
code: {
expiration: misc.isSetDefault(Number(process.env.TRAVELLING_TOKEN_CODE_EXPIRATION), 5), //minutes
authorizeFlow: misc.isSetDefault(misc.stringToBool(process.env.TRAVELLING_TOKEN_CODE_AUTHORIZE_FLOW), true),
}
},
pg: {
Expand Down

0 comments on commit ba84e61

Please sign in to comment.