This document specifies a backend project that will be completed using Node.js / Express.
The aim of this project is to assess you as a Node.js backend developer.
- A: User registration
- B: User login, logout, access to protected resources
- C: Persist the user information using MongoDB
- D: Adminstrative functions
- E: Validate user inputs
The user is presented with a web form to register an account.
Note that the assets (register.html, register.js) will be given to you. You do not have to implement them from scratch.
The user will key in his email, username, password and tap the Verify your phone number button. Upon doing this, a dialog (Facebook AccountKit) pops up and the user is required to key in his mobile number.
For development, please key in your personal mobile number.
A verification code from Facebook will be sent to the mobile number via SMS. The user has to key in the verification code and tap on the Continue button.
Upon successful verification, the dialog closes and on the registration form, the number is shown to be verified and the Register button is enabled.
The user will be able to proceed with the registration.
We use Facebook Account Kit to verify a user's mobile number. A user enters his mobile number in the account kit dialog, receives an SMS with a verification code and keys in the verification code.
Facebook verifies that the entered verification code is valid and calls back a function in the user registration page with the response.status and response.code.
A facebook app with account kit has been configured, so you don't have to deal with setting that up.
There should be an API endpoint that takes in the response.code and
- Calls Facebook API to retrieve the phone number. Code given: fbacckit.js
- Checks that the phone number IS NOT an existing phone number belonging to any other user (All users have unique phone number).
- Generate a signed time-limited token (we use JWT) that contains the phone number
- Returns that token to the calling web page so that it can be passed as a hidden field in the form.
The user registration form contains the following input fields
- username
- password
- phone_token (hidden field)
There should be an API endpoint that takes in the above fields and
- Check that the phone_token originates from server (not tampered with) and has not expired.
- Extract the phone from the phone_token
- Check that the username, email, phone are unique
- Generates a unique id. Code given: utils.js
- Salt and hash password. Code given: utils.js
- Stores the user (perhaps in-memory for now, or you can use MongoDB straight away)
- Returns a json response, with a profile and a id_token (again, a JWT) that will be passed in, as a means of authentication, for subsequent requests to protected resources.
The newly created user is represented as follows:
{
"id": "DdfyFgdeRC2BfDLwiHQM5Q",
"created": 1488421913396,
"username": "someone",
"password": "$2a$10$iByQvY.E.ICJNYuqTRSU2.f2QEyVUCcMXJEL7erEoZzAIjYuod3Wu",
"email": "[email protected]",
"e_verified": false,
"phone": "+6591234567",
"role": "parent",
"locked": false
}
The actual JSON returned (hint: use https://jwt.io to examine the id_token)
{
"profile": {
"id": "DdfyFgdeRC2BfDLwiHQM5Q",
"created": 1488421913396,
"username": "someone",
"email": "[email protected]",
"e_verified": false,
"phone": "+6591234567",
"role": "parent"
},
"id_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJTcVM0d2V3YlNOV0xkZzdfc0RwbHJRIiwidXNlcmlkIjoiRGRmeUZnZGVSQzJCZkRMd2lIUU01USIsInJvbGUiOiJwYXJlbnQiLCJzZXJ2aWNlIjoiQVUiLCJpYXQiOjE0ODg0MjE5MTMsImV4cCI6MTQ4OTYzMTUxM30.XGxyojdocjXvfn3TMM6dHOlM3DP4mJx1QE7oWjHIDIY"
}
A user should be able to login given his username and password.
There should be an API endpoint that takes in the username and password. For a valid user, the API will sign the token and return it.
{
"id_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJTcVM0d2V3YlNOV0xkZzdfc0RwbHJRIiwidXNlcmlkIjoiRGRmeUZnZGVSQzJCZkRMd2lIUU01USIsInJvbGUiOiJwYXJlbnQiLCJzZXJ2aWNlIjoiQVUiLCJpYXQiOjE0ODg0MjE5MTMsImV4cCI6MTQ4OTYzMTUxM30.XGxyojdocjXvfn3TMM6dHOlM3DP4mJx1QE7oWjHIDIY"
}
Returns error if no user with such username and password is found.
As a proof-of-concept, implemented a protected API endpoint (me), that returns the user profile when supplied with the id_token in the Authorization header.
Create an endpoint to return a user profile. The id_token is present in the Authorization header. See image for details.
You can use Postman or cURL to test.

Logout a user
Create an endpoint to logout the user. Extract the id_token and check if it is valid. If so, just console.log out the JTI of the token for now.
If you have been using an in-memory store to keep user information, it is time now to persist data in MongoDB storage.
Use mongodb to persist user accounts
Use a local MongoDB instance for development.
We have also created a hosted MongoDB database with MLab. Later on, you can connect using a driver via the standard MongoDB URI
mongodb://<dbuser>:<dbpassword>@ds113630.mlab.com:13630/tentenapp
Ask me for the dbuser and dbpassword.
For proof-of-concept, an adminstrator (who is authenticated) will be able to
- list all users
- retreive a user by id
- update a user
- delete a user
Implement the above API endpoints. Ensure that the adminstrator is authenticated. (As proof-of-concept, can be as checking for Authorisation: ADMIN in the HTTP header)
UI not required.
Currently user inputs when creating user account are not validated. User inputs should be validated.
- username - minimum 5 characters, alphanumeric and underscores only
- password - minimum 6 characters
- email - valid email format
Implement validation
Design sensible APIs with proper namespace, request parameters and responses. Return errors as neccessary.
Structure your code such that it is clean, modular and maintainable. Some examples
- separate routings / services in logical groups
- models kept separately
- database code kept separately
- configuration code kept separately
- Frontend design and style
The Facebook account kit needs the server URLs to be whitelisted. You should use http://localhost:3000 for development.
You can upload your code to Github repo and import it as a project to GoMix (free) to run it. If you do so, let me know the server url so I can add it to the whitelist.
The APIs need to be be accessed from different domains (the web server and API server are different), so you may have to deal with CORS as well.
- Estimate how much time you will take for each part (A to E). Let me know.
- There is no need to do all parts - depends on your speed, availability, appetite.
- Create a git repo and commit your code. Let me have access to the repo. A public repo is fine by me.
- Remember, code organisation is very important.



