I am using Express to proxy requests to a separate API server which is protected by OAuth 2 access tokens. When a token expires, the server will return a 401 which I am now handling in my router middleware to then go and refresh the access token associated with the clients session (I am using express-session
).
Here is my code:
router.js
app.use('/api', require('./routes.js'));
routes.js
var express = require('express'),
router = express.Router(),
routesController = require('./routes.controller.js');
router.route('/*')
.get(routesController.fetch);
routes.controller.js
module.exports.fetch = function(req, res, next) {
var options = helpers.buildAPIRequestOptions(req);
request(options, function(err, response, body){
if(response.statusCode === 401) {
authController.refreshToken(req, res, next);
} else {
res.status(response.statusCode).send(body);
}
});
};
authController
module.exports.refreshToken = function(req, res, next) {
var formData = {
grant_type: 'refresh_token',
refresh_token: req.session.refreshToken,
scope: 'PRODUCTION'
},
headers = {
'Authorization' : 'Basic ' + consts.CLIENT_KEY_SECRET_BASE64_DEV
};
request.post({url:consts.ACCESS_TOKEN_REQUEST_URL_DEV, form:formData, headers: headers, rejectUnauthorized: false}, function(err, response, body){
var responseBody = JSON.parse(body);
if (response.statusCode === 200) {
req.session.accessToken = responseBody.access_token;
req.session.refreshToken = responseBody.refresh_token;
next();
//How to recall the original request made from fetch controller function after this point?
} else {
console.log('SOMETHING ELSE HAPPENED!');
}
});
};
After updating the token, I would like to re-issue the original API request that I am triggering using the request
module in my fetch controller.
I'm a bit stumped how I actually go about doing this, is there an elegant way to achieve this?
I would turn the auth controller from middleware into a promise. Then make fetch
recursive.
routes.controller.js
module.exports.fetch = fetch;
function fetch(req, res, next) {
var options = getSavedOptsFromRequest(req) || helpers.buildAPIRequestOptions(req);
request(options, function(err, response, body){
if(response.statusCode === 401) {
saveOptsToRequest(req, options)
authController.refreshToken(req)
.then(function authOk(){
fetch(req, res, next);
})
.catch(function authKo(){
res.status(500).send('something');
});
} else {
res.status(response.statusCode).send(body);
}
});
};
function saveOptsToRequest(req, options){
req.requestedOptions = options;
}
function getSavedOptsFromRequest(req){
return req.requestedOptions;
}
authController
module.exports.refreshToken = function(req) {
var refreshTokenPromise = new Promise(function (resolve, reject){
var formData = {
grant_type: 'refresh_token',
refresh_token: req.session.refreshToken,
scope: 'PRODUCTION'
},
headers = {
'Authorization' : 'Basic ' + consts.CLIENT_KEY_SECRET_BASE64_DEV
};
request.post({url:consts.ACCESS_TOKEN_REQUEST_URL_DEV, form:formData, headers: headers, rejectUnauthorized: false}, function(err, response, body){
var responseBody = JSON.parse(body);
if (response.statusCode === 200) {
req.session.accessToken = responseBody.access_token;
req.session.refreshToken = responseBody.refresh_token;
resolve();
//How to recall the original request made from fetch controller function after this point?
} else {
console.log('SOMETHING ELSE HAPPENED!');
reject(new Error("Something!!!!"));
}
});
});
return refreshTokenPromise;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With