zaterdag 6 juni 2015

Node Authentication, migration from mongoose to sequelize

Scotch.io has quite a complete tutorial on how to setup Node authentication with Passport, a great authentication Node.js module. The Scotch.io tutorial uses NOSQL database Mongodb to store user information. Mongodb is a handy database for this tutorial, but many projects already use an SQL database. So I decided to see if I could use the tutorial as a boilerplate for authentication based on user data stored in an SQL database. The original tutorial uses Mongoose, an Object-Releational-Mapping (ORM) middleware to map the javascripted 'User' object to data in NOSQL MongoDB. For SQL, I found an equivalent ORM-middleware called Sequelize. I started very optimistically, thinking I would connect the SQL database in an hour or so, but, in reality, it took me quite some time to do the job. The complete code is available on github at https://github.com/anneb/easy-node-authentication

I first completed the Scotch.io tutorial and checked that it worked. Then I started migration to Sequelize. This required new Node modules to be installed. I happened to choose Postgres as SQL database (Sequelize supports at least Mysql, Postgres, Sqlite, Mariadb and MSsql).



Setup the database connect string (replace dbuser, dbpasswd, dbhost, dbname by appropriate values):

 

Then I had a look at the data model. MongoDB is more or less object based. Data are stored in collections, the NOSQL equivalent of SQL tables. Collections contain documents, the SQL-equivalent of records. All SQL records in a table share the same structure by design. The attributes of objects in the same NOSQL collection may vary from one object to the other. The scotch.io authentication tutorial uses this NOSQL multi-attribute feature to store different user properties for different identity providers. For example, in the case of local identities, we may need such attributes as 'username' and 'password', but for remote identity providers such as Google, we need to store a Google id and a Google OAuth token. To accommodate for the differences between NOSQL and SQL, the datamodel for the Sequelize version of the authentication example had to be modified.



The above Model is instantiated using sequelize.import. (not to be confused with 'require()'):


User.sync() creates table 'users' in the database if it does not yet exist. By default Sequelize silently adds three extra columns to the table: a primary key field id and fields createdAt and updatedAt, refer to the Sequelize documentation for more options.

Another difference between Sequelize and Mongoose is the use of Javascript Promises. Sequelize 2.0+ is Promisified, Mongoose is not (yet). Javascript Promises should make it easier to handle asynchronous events. Javascript Promises are a native feature of many Javascript engines since 2013. However, Microsoft Internet Explorer (IE) included native support for Promises only since version 12 and Promises will never be available in IE on Windows 8.1. For this reason, if you are a Javascript developer for browser based Javascript, you may not yet be fully acquainted with Promises. Sequelize has a separate documentation site, but I found the documentation not to be always very complete. For example, sometimes the documentation describes that a function requires an option object, but forgets to explain the possible options. Functions return Promises, but examples are not provided. It would be great if there were some tutorial on how to use Sequelize. They are probably around, but I found it hard to find. Many of the examples that I did find are for the pre-Promise version, so they don't work for the current version of Sequelize. Please comment a tip if you know of a good Sequelize tutorial or Sequelize example set!

The following example would have helped me a lot:

Mongoose, no Promises


Sequelize, Promisified



The complete code is available on github at https://github.com/anneb/easy-node-authentication