Skip to content
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

Add a refresh token request #101

Merged
merged 10 commits into from
Mar 4, 2018
27 changes: 27 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"homepage": "https://github.com/foundersandcoders/OTP-Data-Entry#readme",
"dependencies": {
"aws-sdk": "^2.186.0",
"axios": "^0.17.1",
"body-parser": "^1.18.0",
"compression": "^1.7.1",
"cookie-parser": "^1.4.3",
Expand Down
20 changes: 12 additions & 8 deletions src/controllers/OAuth/token.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,38 @@ module.exports = (req, res) => {
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
redirect_uri: process.env.REDIRECT_URI,
grant_type: 'authorization_code'
grant_type: 'authorization_code',
};

const options = {
method: 'POST',
uri: oauthTokenBaseURL,
body: queryString.stringify(tokenQueries),
headers: {
'content-type': 'application/x-www-form-urlencoded'
}
'content-type': 'application/x-www-form-urlencoded',
},
};

if (req.query.state !== process.env.STATE) {
return res.redirect('error', {
statusCode: 400,
errorMessage: 'Something went wrong with your login information! please try again.'
errorMessage:
'Something went wrong with your login information! please try again.',
});
} else {
Request(options, (error, responseToken, body) => {
if (error || responseToken.statusCode !== 200) {
return res.redirect('error', {
statusCode: 500,
errorMessage: 'Server error!'
errorMessage: 'Server error!',
});
} else {
const parsedBody = JSON.parse(body);
const token = jwt.sign(parsedBody.access_token, process.env.JWT_SECRET);
res.cookie('token', token, {maxAge: 604800000});
const { access_token, refresh_token } = JSON.parse(body);
const token = jwt.sign(
{ access_token, refresh_token },
process.env.JWT_SECRET,
);
res.cookie('access', token, { maxAge: 604800000 });

if (req.cookies && req.cookies.referredUrl) {
res.redirect(req.cookies.referredUrl);
Expand Down
73 changes: 39 additions & 34 deletions src/controllers/events/delete_event.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,48 @@ const { eventsURL } = require('../../constants/urls.json');
const jwt = require('jsonwebtoken');

module.exports = (req, res) => {
if (req.cookies && req.cookies.token) {
jwt.verify(req.cookies.token, process.env.JWT_SECRET, (error, decodedToken) => {
if (error) {
return res.render('error', {
statusCode: 500,
errorMessage: res.locals.localText.serverError
});
} else {
const reqOptions = {
url: `${eventsURL}/${req.params.id}`,
method: 'DELETE',
auth: {
'bearer': decodedToken
}
};
Request(reqOptions, (error, response) => {
if (error) {
return res.render('error', {
statusCode: 500,
errorMessage: res.locals.localText.serverError
});
}
if (response.statusCode !== 204) {
return res.render('error', {
statusCode: 400,
errorMessage: res.locals.localText.badRequest
});
} else {
res.redirect(`/${req.params.lang}/events`);
}
});
}
});
if (req.cookies && req.cookies.access) {
jwt.verify(
req.cookies.access,
process.env.JWT_SECRET,
(error, decodedToken) => {
if (error) {
return res.render('error', {
statusCode: 500,
errorMessage: res.locals.localText.serverError,
});
} else {
const reqOptions = {
url: `${eventsURL}/${req.params.id}`,
method: 'DELETE',
auth: {
bearer: decodedToken.access_token,
},
};

Request(reqOptions, (error, response, body) => {
if (error) {
return res.render('error', {
statusCode: 500,
errorMessage: res.locals.localText.serverError,
});
}
if (response.statusCode !== 204) {
return res.render('error', {
statusCode: 400,
errorMessage: res.locals.localText.badRequest,
});
} else {
res.redirect(`/${req.params.lang}/events`);
}
});
}
},
);
} else {
return res.redirect('error', {
statusCode: 500,
errorMessage: res.locals.localText.serverError
errorMessage: res.locals.localText.serverError,
});
}
};
70 changes: 43 additions & 27 deletions src/controllers/events/modify_content.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const Request = require('request');
const { eventsURL } = require('../../constants/urls.json');
const checkCookie = require('../../helpers/check_cookie.js');
const OTP = require('../../otp_sdk');

module.exports = (req, res) => {
const apiBody = {
Expand Down Expand Up @@ -32,43 +32,59 @@ module.exports = (req, res) => {
if (error) {
return res.status(500).send(res.locals.localText.serverError);
}
let url, urlEndpoint, correctResponseStatusCode, auth;
let headers;
const tools = {};
switch (req.body._method) {
case 'post':
url = eventsURL;
urlEndpoint = 'events';
correctResponseStatusCode = 201;
tools.url = eventsURL;
tools.urlEndpoint = 'events';
tools.correctResponseStatusCode = 201;
break;
case 'put':
url = `${eventsURL}/${req.params.id}`;
urlEndpoint = `event/${req.params.id}`;
correctResponseStatusCode = 200;
auth = {
bearer: decodedToken,
tools.url = `${eventsURL}/${req.params.id}`;
tools.urlEndpoint = `event/${req.params.id}`;
tools.correctResponseStatusCode = 200;
headers = {
Authorization: 'Bearer ' + decodedToken,
};
break;
default:
return res.status(500).send(res.locals.localText.serverError);
}

// adds the redirectUrls to the tools
tools.redirectUrl = JSON.stringify({
redirectUrl: `/${req.params.lang}/${tools.urlEndpoint}`,
});

const reqOptions = {
url,
url: tools.url,
method: req.body._method,
body: apiBody,
json: true,
auth,
data: apiBody,
responseType: 'json',
headers,
};
Request(reqOptions, (error, apiResponse, apiResponseBody) => {
if (error) {
return res.status(500).send(res.locals.localText.serverError);
} else if (apiResponse.statusCode !== correctResponseStatusCode) {
return res
.status(apiResponseBody.statusCode)
.send(apiResponseBody.message);
} else {
res.end(
JSON.stringify({ redirectUrl: `/${req.params.lang}/${urlEndpoint}` }),
);
}
});

OTP.events
.modify(reqOptions, tools)
.then(() => res.send(tools.redirectUrl))
.catch(err => {
if (err.Unauthorized) {
OTP.auth
.getRefreshToken(req.cookies)
.then(tokens => {
res.clearCookie('access');
res.cookie('access', tokens.token, { maxAge: 604800000 });
reqOptions.headers = {
Authorization: 'Bearer ' + tokens.access_token,
};
OTP.events
.modify(reqOptions, tools)
.then(() => res.send(tools.redirectUrl))
.catch(e => res.status(500).send('Server Error'));
})
.catch(e => res.status(500).send('Server Error'));
}
});
});
};
6 changes: 3 additions & 3 deletions src/helpers/check_cookie.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
const jwt = require('jsonwebtoken');

const checkCookie = (req, cb) => {
if (req.cookies && req.cookies.token) {
jwt.verify(req.cookies.token, process.env.JWT_SECRET, (error, decoded) => {
if (req.cookies && req.cookies.access) {
jwt.verify(req.cookies.access, process.env.JWT_SECRET, (error, decoded) => {
if (error) cb(error);
else {
cb(null, decoded);
cb(null, decoded.access_token);
}
});
} else {
Expand Down
15 changes: 15 additions & 0 deletions src/helpers/verify_token.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const jwt = require('jsonwebtoken');

module.exports = reqCookiesObject => {
const { access } = reqCookiesObject && reqCookiesObject;

return new Promise((resolve, reject) => {
jwt.verify(access, process.env.JWT_SECRET, (error, decoded) => {
if (error) {
return reject(error);
} else {
return resolve(decoded);
}
});
});
};
17 changes: 7 additions & 10 deletions src/middleware/checkLoggedIn.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,17 @@
// referredUrl to know where to go back to after looged in!

const jwt = require('jsonwebtoken');
const verifyToken = require('../helpers/verify_token.js');

module.exports = (req, res, next) => {
const token = req.cookies && req.cookies.token;
const access = req.cookies && req.cookies.access;

if (token) {
jwt.verify(token, process.env.JWT_SECRET, (error) => {
if (error) {
return res.redirect(`/${req.params.lang}/login`);
} else {
return next();
}
});
if (access) {
verifyToken(req.cookies)
.then(() => next())
.catch(err => res.redirect(`/${req.params.lang}/login`));
} else {
res.cookie('referredUrl', req.url, {maxAge: 300000});
res.cookie('referredUrl', req.url, { maxAge: 300000 });
return res.redirect(`/${req.params.lang}/login`);
}
};
14 changes: 14 additions & 0 deletions src/otp_sdk/events.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const axios = require('axios');

module.exports.modify = (options, tools) => {
return new Promise(async (resolve, reject) => {
try {
await axios(options);
resolve();
} catch (error) {
error.response.data.error === 'Unauthorized'
? reject({ Unauthorized: true })
: reject();
}
});
};
41 changes: 41 additions & 0 deletions src/otp_sdk/get_refresh_token.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const verifyToken = require('../helpers/verify_token.js');
const axios = require('axios');
const qs = require('querystring');
const jwt = require('jsonwebtoken');
const { oauthTokenBaseURL } = require('../constants/urls.json');

module.exports = reqCookiesObject => {
const requestToken = async token => {
const tokenQueries = {
grant_type: 'refresh_token',
refresh_token: token.refresh_token,
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
redirect_uri: process.env.REDIRECT_URI,
};

const options = {
method: 'post',
baseURL: oauthTokenBaseURL,
data: qs.stringify(tokenQueries),
};
try {
const apiTokenResponse = await axios(options);
const { access_token, refresh_token } = apiTokenResponse.data;
const token = await jwt.sign(
{ access_token, refresh_token },
process.env.JWT_SECRET,
);
return { access_token, token };
} catch (e) {
return e;
}
};

return new Promise((resolve, reject) => {
verifyToken(reqCookiesObject)
.then(requestToken)
.then(tokens => resolve(tokens))
.catch(reject);
});
};
5 changes: 5 additions & 0 deletions src/otp_sdk/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports.events = require('./events.js');

module.exports.auth = {
getRefreshToken: require('./get_refresh_token.js'),
};