Generating API tokens using node - node.js

I am writing an app that will expose an API. The application allows people to create workspaces and add users to them. Each user will have a unique token. When they make an API call, they will use that token (which will identify them as that user using that workspace.
At the moment I am doing this:
var w = new Workspace(); // This is a mongoose model
w.name = req.body.workspace;
w.activeFlag = true;
crypto.randomBytes(16, function(err, buf) {
if(err){
next(new g.errors.BadError503("Could not generate token") );
} else {
var token = buf.toString('hex');
// Access is the list of users who can access it. NOTE that
// the token is all they will pass when they use the API
w.access = { login: req.session.login, token:token, isOwner: true };
w.save( function(err){
if(err){
next(new g.errors.BadError503("Database error saving workspace") );
Is this a good way to generate API tokens?
Since the token is name+workspace, maybe I should do something like md5(username+workspace+secret_string) ...?

If you using mongodb just use ObjectId, othewise I recommend substack's hat module.
To generate id is simple as
var hat = require('hat');
var id = hat();
console.log(id); // 1c24171393dc5de04ffcb21f1182ab28

How does this code make sure your token is unique? I believe you could have collision of numbers with this code. I believe you need to have a sort of sequence number like in this commit from socket.io.
Also you could use npm projects like for example:
UUIID (v4)
hat
to ensure uniqueness.

I think the following are the best solution for Generating API tokens
JWT (Json web Token)
Speakeasy - This generate token based on timebased twofactor authentication like google authenticator
Speakeasy is more secure because this key is only available for a small time period (e.g, 30 second)

Why not just use UUIDv4 if you are looking for something unique? If you are interested in some other type of hashing (as mentioned previous hat is a good choice), you might look at speakeasy - https://github.com/markbao/speakeasy. It not only generates random keys but it can also create timebased twofactor authentication keys if you ever really want to layer on additional security strength.

Related

Building a Slack app that authenticates into external system using OAUTH

I am in the process of building a small test slack app and not clear on the architecture that is needed for authentication. This will be a NodeJS application that lives on Heroku.
When a user uses a /slash command, it is going to invoke logic that will query an external CRM system and return data. In order to authenticate into this external system, it would need to send the user through an OAUTH flow so that the access to the data is governed by the invoking users' permissions.
My confusion is to how to handle or persist these auth tokens/refresh tokens that we get back from the user authenticating during this process.
Example Steps:
Runs /user bob#gmail.com
Checks to see if user has authorized on this external system
If not, take the user through the external systems oauth flow
After authentication, we have the token that can be used to make callouts to the external systems API as that user.
Makes callout and returns data
How would I persist or check for the slack users auth/refresh token when they run the command to see if we already have it? If the token already existed, I wouldn't need to send them through the OAUTH flow again.
My Thoughts on the approach:
It almost seems like there needs to be a data store of some type that contains the slack user ID, auth token, and refresh token. When the user invokes the command, we check to see if that user is in the table and if so, we use their token to make the API call.
If they don't exist, we then send them through the OAUTH flow so we can store them.
Final Thoughts:
In terms of security, is having a table of tokens the correct way to do this? It almost seems like it's the equivalent of storing a plain text password if someone were to get that token.
Is there a better way to handle this or is this a common approach?
Your approach is right and the docs in slack API points out to this article that describe your use case where the third party is the Salesforce CRM.
In terms of security, is having a table of tokens the correct way to do this? ...
Yes, an attacher may steal your db data.
To avoid that you can store the tokens as encripted string.
In this way, a malicious user should:
steal your data from the db
steal your source code to understand what type of algorithm you are using to encript the tokens and the logic behind it
The approach is to spread all the info to get the clear token across system assuming
one or more systems can be compromised, not everyone!
Is there a better way to handle this or is this a common approach?
Usually the AES-256 is used, in detail aes-256-gcm or aes-256-cbc. There are some thread off
in performance and use cases you must deal with in order to prefer one or another.
Node.js supports both and an example logic could be:
const crypto = require('crypto')
const algorithm = 'aes-256-gcm'
const authTagByteLen = 16
const ivByteLen = 64
const keyByteLen = 32
const saltByteLen = 32
const oauthToken = 'messagetext'
const slackUserId = 'useThisAsPassword'
const salt = crypto.randomBytes(saltByteLen)
const key = crypto.scryptSync(
Buffer.from(slackUserId, 'base64').toString('base64'),
Buffer.from(salt, 'base64').toString('base64'),
keyByteLen)
const iv = crypto.randomBytes(ivByteLen)
const cipher = crypto.createCipheriv(algorithm, key, iv, { authTagLength: authTagByteLen })
let encryptedMessage = cipher.update(oauthToken)
encryptedMessage = Buffer.concat([encryptedMessage, cipher.final()])
const storeInDb = Buffer.concat([iv, encryptedMessage, cipher.getAuthTag()]).toString('base64')
/***
*
*/
const storeInDbBuffer = Buffer.from(storeInDb, 'base64')
const authTag = storeInDbBuffer.slice(-authTagByteLen)
const iv2 = storeInDbBuffer.slice(0, ivByteLen)
const toDencryptMessage = storeInDbBuffer.slice(ivByteLen, -authTagByteLen)
const decipher = crypto.createDecipheriv(algorithm, key, iv2, { authTagLength: authTagByteLen })
decipher.setAuthTag(authTag)
const messagetext = decipher.update(toDencryptMessage)
decipher.final()
const clearText = messagetext.toString()
console.log({
oauthToken,
storeInDb,
clearText
})
Notice:
the SALT logic will generate a new "storeInDb" string at every run without compromising the future reads
you may use the slack-user-id as password, so the attacher should know this information too
you must store the salt too or write an algorithm to generate it form the user id for example
the salt may be stored in a (redis) cache or other Services like S3, so the attaccher should break this other system to parse the tokens!
GCM example extrated by my module
You may find a CBC example here

Node JS: JWT verify vs redis query performance comparison?

I have implemented JWT token for authentication to my API which is served using node.js.
On every request sent to the server, I do a jwt.verify() but I'm wondering if this is more CPU intensive and therefore less scalable than storing the token in Redis, and retrieving the userId.
Example:
const jwt = require('jsonwebtoken')
const app = require('express')
app.get('/user',(req, res) => {
const { headers: { authorization } } = req
let token = null
if (authorization && authorization.split(' ')[0] === 'Bearer') {
token = authorization.split(' ')[1]
}
jwt.verify(token, process.env.TOKEN_SECRET, (err, decoded) => {
if(err || !decoded){
return res.json({success: false, message: `Not valid token`})
}
//
// Continue with my logic
//
})
})
So I'm wondering if anyone knows if it's better performance-wise to do jwt.verify() vs a redis.get()?
I think that's a subject to debate on but the answer heavily depends on what goals you are trying to achieve / which hardware do you use / how you plan to scale (as you have mentioned scalability)
TL;DR I would stick with jwt.verify() if it doesn't cause performance issues with your current load
For regular JWT token created with HS256 Algorithm, jwt.verify() is not a CPU intensive task that runs under <1ms on the modern CPU
For a Redis case we need to take into account two cases
We run a Redis instance on the same machine so we don't have to make a network call and lose time on latency or deal with the risk of the network error. But we anyway introduce a latency because 2 separate processes have to talk to each other but it would be the same <1ms
We have one global Redis server/cluster which stores our JWT tokens and we have to deal with network stuff and increase latency up to 30-50ms and even more
Also when we introduce Redis to our system we create an additional layer of the complexity to our system which has to maintained and etc.
Regardless of the fact that Redis brings an extra level of complexity, it's more Node.js-oriented philosophy to make everything async as much as we can and don't lock the CPU (EventLoop) with heavy tasks.
BUT using the Redis approach, we are kind of losing the advantages of the JWT itself (us userId already encrypted in token), and maybe we need to look at the solution which uses sessions to store userId instead of JWT. In most cases, we need to store JWT somewhere when the token becomes expired and we need to access the refresh token to create a new JWT.
So, I think that the best way would be to stick with jwt.verify() if it doesn't cause performance issues with your current load (like your server is not used at peak level all the time but that's another issue and topic to discuss)
P. S. You can use Node APIs like process.hrtime() to simply measure performance of your running code

Can I access twitter auth data via firebase cloud functions Admin SDK? If so, how?

I'm currently using firebase for the backend of a project I'm working on. In this project, the client authenticates using the firebase-twitter sign in method. For the purpose of security, I'm trying to minimise the amount of communication between the client and backend when it comes to auth data. In jest of this, I'm wondering if there is a way to access the auth data i.e. the user's twitter key/secret (as well as things like the user's twitter handle) from the server-side after the user authenticates ? I figured there might be a way as the authentication happens through twitter + firebase, but I'm struggling to find the exact solution I need in the documentation (been stuck on this for a week now) so was hoping someone else already knows if this is possible and how :) cheers
Maybe not the best way, but you can try: on client side use RealTime database and add a new entry every time the user log in. They call this 'realtime triggers'.
You don't mention what front are you using, but on ionic is something like:
firebase.auth().onAuthStateChanged(function(user) {
if (user)
this.db.addLogin(user.uid)
});
On database class function:
addLogin(uid){
let path = "/logins/"
let ref = this.db.list(path)
let body = {uid: uid}
return ref.push(body)
}
On the server side, listen the path using child_added
var ref = db.ref("logins");
ref.on("child_added", function(snapshot, prevChildKey) {
var newPost = snapshot.val();
console.log("Uid: " + newPost.uid);
console.log("Previous Post ID: " + prevChildKey);
});
More information about triggers

How can I authorise an installation of an Electron application?

If you needed to do some kind of an authorization mechanism to an Electron application, what libraries/frameworks would you use for it?
Basic requirements would be that the user enters either a key or some identification information about himself and their right to use the application can be remotely allowed/blocked as necessary.
Kind of like a license key, but a bit more flexible in terms of defining when their right of use ends.
Your question is a little vague (and not really a programming question).
Are you talking about software licensing? I've researched this quite a bit and, while there are a bunch of turnkey solutions, they tend to be relatively expense (monthly subscription fees, etc).
I ended up settling on Easy Digital Downloads and their Software Licensing plugin. The latter enables setting a license expiration date if desired, update alerts and a bunch of other stuff. The tech support is also responsive. It is a WordPress system though – so you would need to set up a 'store' using WordPress.
The API is trivial to interface with through Javascript – to active a license, check license validity, and check for updates.
An open source project I found was Simple Licensing. That is free but is less well documented and there isn't any support.
It depends. I've detailed in this answer how to generate and verify cryptographically signed license keys without a license server. But cryptographic license keys like that are usually perpetual (though can have a fixed expiration inside of the key), and it sounds like you want something a bit more dynamic when it comes to a license's validity, since you mentioned that you want to be able to remotely block a license.
That's where a license server would come in.
At its core, most licensing servers are CRUD apps, meaning they're the typical server allowing you to create, read, update, and delete resources. In this case, that resource would be a license. You would want to create a server endpoint that takes a license key parameter, performs a database lookup for the key, and if the key exists check if the key is expired among other requirements such as its blocked column.
Here's a basic Express app that does that, minus the pg database bits:
const express = require('express')
const app = express()
const { Client } = require('pg')
const db = new Client()
const {
PORT = 8080
} = process
app.get('/validate/:licenseKey', async (req, res) => {
const { licenseKey } = req.params
const { rows } = await db.query('select * from licenses where key = $1::text limit 1', [licenseKey])
const [license] = rows
if (license == null) {
return res.send({ valid: false, code: 'NOT_FOUND' })
}
if (license.blocked) {
return res.send({ valid: false, code: 'BLOCKED' })
}
if (license.expiry < Date.now()) {
return res.send({ valid: false, code: 'EXPIRED' })
}
return res.send({ valid: true, code: 'VALID' })
});
app.listen(PORT, async () => {
await db.connect()
console.log(`Server is running on port ${PORT}`)
})
But in case you aren't particularly keen on writing and maintaining your own in-house licensing system, I’m the founder of a software licensing API called Keygen which can help you get up and running quickly without having to write and host your own license server.
Keygen is a typical HTTP JSON API service (i.e. there’s no software that you need to package with your app). It can be used in any programming language and with frameworks like Electron. As per your main requirement here, it supports remotely suspending (blocking) licenses.
In its simplest form, validating a license key with Keygen is as easy as hitting a single JSON API endpoint (feel free to run this in a terminal):
curl -X POST https://api.keygen.sh/v1/accounts/demo/licenses/actions/validate-key \
-d '{
"meta": {
"key": "C1B6DE-39A6E3-DE1529-8559A0-4AF593-V3"
}
}'
I recently put together an example of adding license key validation, as well as device activation and management, to an Electron app. You can check out that repo on GitHub: https://github.com/keygen-sh/example-electron-license-activation.

Sending data to a independent remote server

I want to send a json object to another server, independent of my website.
The API I am using requires a user (user x in this case) to log into their service to be authorized so user x can manipulate user x's list. However, other users can't write to x's list. So, users need to request an item to be added to x's list, then a server who is logged into x's account can add it to x's list. Refer to the image below.
http://imgur.com/a/wT53t
I am using node/express.js for the servers on the user's side. However, I don't know what I should use for a server who's only job is to receive requests and write to x's list. Can you provide some guidance as to how I can achieve something like this?
Thanks!
There are two options here:
You have to refresh the list in the realtime for connected users.
To achieve this you should use either: WebSockets(e.g. socket.io) or LongPolling.
In second option you dont have to refresh the list in the realtime. You simply use express. Accept data and refresh the list server-side.
Auth with web sockets:
Once understanding the nature of web sockets, you're free to build any logic around them, including authentication/authorization. The great library doing lots of auth things is passport.js.
Very quick and abstract example of server-side:
socket.on('auth', function(data) {
const vendor = data.vendor,
token = data.id
switch(vendor) {
/*
Here you grab through some social API user social id
and save it to database
*/
}
/* set socket as logged in */
socket.logged = true
/* or even save user object */
socket.user = { vendor, token }
})
Next time you need authorized user, you check:
socket.on('mustBeAuthorized', function() {
if(socket.logged || socket.user) {
/* Continue your logic*/
}
})

Resources