How to create REST API with security token?
Sometimes we need a simple security mechanism for our REST API and oftentimes we search complicated solutions, but why? The implementation of security token is so easy.
Definition files
Create a definition file tokens.js
:
- this definition file willhandle creating default tokens
- database checks whether the token exists (Total.js +v2.4)
function create(token, name) {
NOSQL('tokens').insert({ token: token, name: name, created: F.datetime }, true).where('token', token);
}
create('d88ad6cd-1112-4fc9-a20a-6ff75ed4d2da', 'Android');
create('5df4b659-bc1d-4e4d-9e37-0fa2ad70f8d1', 'iOS');
Create a definition file auth.js
:
const SESSION = {};
F.onAuthorize = function(req, res, flags, callback) {
// We read the X-Token header from the current request
var token = req.headers['x-token'];
if (!token)
return callback(false);
// We check whether the token exists in the current session
if (SESSION[token]) {
// Extends expiration time
SESSION[token].ticks = F.datetime;
return callback(true, SESSION[token]);
}
// Try to find the token in NoSQL database
NOSQL('tokens').find().make(function(builder) {
builder.where('token', token);
builder.first();
builder.callback(function(err, response) {
if (response) {
response.ticks = F.datetime;
SESSION[token] = response; // We create a session
callback(true, response);
} else
callback(false);
});
});
};
// Removes older sessions
F.on('service', function(counter) {
if (counter % 5 !== 0)
return;
var ticks = F.datetime.add('-10 minutes');
Object.keys(SESSION).forEach(function(token) {
if (SESSION[token].ticks < ticks)
delete SESSION[token];
});
});
Usage
Now we can use our token mechanism in a controller, for example:
exports.install = function() {
// `F.onAuthorize` will be called for each of the following routes
F.route('/api/users/', json_query, ['*User', 'authorize']);
F.route('/api/products/', json_query, ['*Products', 'authorize']);
F.route('/api/orders/', json_query, ['*Orders', 'authorize']);
};
function json_query() {
this.$query(this.query, this.callback());
}