Billy Fung

My First Node App

Github OAuth2

Billy Fung / 2016-02-10


As a technical exercise I learned Node.js last week, and it was a pretty interesting exercise. One of the main differences compared to other frameworks is that Node.js is a Javascript server that you build, with all the different modules located within your server. So instead of having to load different libraries into your OS, you have a folder of node_modules where all the dependencies will be located for the Node app.

The GitHub repo for my app can be found . The app is very basic, but goes through the basic tools of building a Node.js app, along with GitHub OAuth2 authentication for a login.

Overview

Set up a basic login page homepage with GitHub authentication via passport- github, no database integration, just GitHub authentication, and display the information from GitHub profile.

Detailed Introduction

If you’ve been wanting to try out Node.js for awhile, but haven’t found a concise enough tutorial to walk you through a simple Node.js application, here’s another one you can try. The tutorial will hopefully walk you through setting up a Node.js app where users can sign up or log in through GitHub.

Setup for OS X

Go to https://nodejs.org/en/ and use the package installer, it makes everything much simplier compared to older options of having to download binary and unpack. The package installer also installs npm for you, which is the n ode p ackage m anager.

If you run into errors, the best bet would be to search on Google for the error and see what options people have available to solve. For now this tutorial will only be for OS X.

To check that everything is working correctly so far, try running the commands:

    node -v
    npm -v

and make sure that the numbers correspond to the version that you downloaded. Node is still relatively new, so releases are quick and abundant and new versions come out like hot cakes.

Once node and npm have been installed correctly (yes, this is probably one of the harder parts), you can write your first Node.js code.

Hello World

Using your editor of choice, create a file called helloworld.js in your directory and put the follow code into it:

    console.log("Hello World");

Save the file and run it with Node.js using:


    node helloworld.js
    

Then you should see Hello World printed in your terminal, and that’s the basic Hello World for Node.js

Web Application

Now that the setup stuff is out of the way, it’s time for the action you’ve been looking for. The real reason you’re looking to use Node.js is so you can have Javascript executed within a web server. In Node.js, the application you want to build is actually the same as the server you build, so with this in mind the next step is to choose a framework that helps you with creating a server for a web application.

Express

One of the common choices for a Node.js web application framework is Express. express-generator is a tool that creates a web application skeleton for you, meaning all the requires files and folders for a web application is created. Install the tool with:


    npm install express-generator -g
    

The -g installs the package on the local npm installation directory for system-wide usage.

To create an Express project run:


    express
    

And now the project folder will be populated with a bunch of new files that will build the Express web app. The package.json file contains the list of project dependancies, which tells npm which packages to install for the project. So run the command:


    npm install
    

This will read the JSON file and let npm know to install all those packages into the node_modules folder, with the version specified. This is useful when you want to try a different node project on your computer, but the module versions are all different.

The packages that should be in the dependencies are:

If all is going according to plan, you should have a barebones web app ready to be used, test it out by running:


    npm start
    

The Node.js web server is located at http://localhost:3000.

express viewexpress

Understanding Express

So now you should have the web app skeleton set up for Node.js, so the next step is to use the framework to make the web application. Currently the view that is rendered at http://localhost:3000 consists of the Node.js server from app.js and 3 files in the project folder: routes/index.js, views/index.jade, and views/layout.jade. It is here that Node.js with Express differs a bit from tradiational MVC framework. Routes in Express are similar to controllers, but not really because routes also have a bit of the model in them.

Another important part of Express is middleware, depending on what framework you’re used to already, it might look a bit familiar. If not, middleware is essentially a means to manipulate request and response objects. This is a very powerful tool, and used very often.

Express app.js

Looking into the app.js file, you can see that there is code already generated in there that tells Express where to look for routing files. For example, the app.set declaration tells the Express app where to look for views, and which engine to render the views with. In order to have the server point to the correct views, the routing for the application must also be set, this is done by:


    app.use('/', routes);
    app.use('/users', users);
    

/routes/index.js

Looking at the /routes/index.js file, you can see that inside is some Javascript that sets up a variable with Express functionality, and then assigning router = Express.router() method. What does that Express router do? It is always good to check out documentation when you’re working through understanding the functionality of the framework.

So for the purposes of this framework, the router method creates an object that can be used for HTTP methods (get, put, post…). So the router variable is then used to GET / and pass the title, and render the response which is in index.jade. A valid substitution would be to use app.get('/', routes), for the purposes when you know that it will be a GET. The app.use command is more general and will allow all HTTP verbs through.

/views/index.jade

After Express routes the GET request, the response is rendered based on what is in index.jade. Looking into the file, you can see that the page layout is set up in there, with the stylesheet being chosen. So it is within here that you can use a different UI framework, like Bootstrap or Semantic UI.

Changing the front end

Now you know most of the basic information of what files do what within Express, and the general workflow, the next step is to design the front end. You could also do the backend first as well, no strict rules to follow here.

Using Semantic UI

layout.jade

To use Semantic UI, you have to specify the stylesheet source within layout.jade. Since this isn’t going to be a very complex app, it is reasonable to use the online source. Go into layout.jade and put:


    link(rel='stylesheet', href='//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/semantic.min.css')
    script(src="//ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js")
    script(src="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/semantic.min.js")
    

This will now allow you to use Semantic UI within your index.jade. So far there really hasn’t been much said about the file template language, but it’s clearly a bit different from normal HTML.

Jade is a templating engine that relies heavily on whitespace for writing HTML, so instead of <head> you can write head and it will be converted accordingly. Tags are automatically closed for you, and in general everything looks a bit cleaner. The documentation is a good place to learn most of the features of Jade.

index.jade

Now that the layout is set up, you can use Semantic UI within index.jade to define the contents of the block. To create simple page following the login page example make your file look like:


    extends layout
    
    block content
      .ui.middle.aligned.center.aligned.grid
        .column
            h2.ui.teal.header
                .content Log-in to your account
            form.ui.large.form(method='POST')
                .ui.stacked.segment
                    .field
                        .ui.left.input
                            input(type="text", name="email", placeholder="E-mail address")
                    .field
                        .ui.left.input
                            input(type="password",  name="password", placeholder="Password")
                    .ui.fluid.large.teal.submit.button Login  
                .ui.error.message
            .ui.message New to us? 
                a(href='#') Sign up 
    

Now when you run npm start and view http://localhost:3000 you should see some resemblance of a login page. It is noteworthy that the form has method='POST' in order to send the data to the Node.js server.

without css image

Not quite there yet, some CSS touchups is needed to finalize the look. The layout.jade file has a reference to /stylesheets/style.css so it is inside there that changes to CSS can be applied. Add this code into the file to clean up the look:


    body {
          background-color: #DADADA;
        }
    body > .grid {
          height: 100%;
        }
    .image {
          margin-top: -100px;
        }
    .column {
          max-width: 450px;
        }
    

In order to set restrictions on the text entered into the email and password boxes, you will need to set up a function to check. There you have it, a simple login page done. The next step will be to make the sign in page do something. To do this, you can write a javascript function, and place the file main.js within /public/javascripts:


    $(document)
        .ready(function() {
          $('.ui.form')
            .form({
              fields: {
                email: {
                  identifier  : 'email',
                  rules: [
                    {
                      type   : 'empty',
                      prompt : 'Please enter your e-mail'
                    },
                    {
                      type   : 'email',
                      prompt : 'Please enter a valid e-mail'
                    }
                  ]
                },
                password: {
                  identifier  : 'password',
                  rules: [
                    {
                      type   : 'empty',
                      prompt : 'Please enter your password'
                    },
                    {
                      type   : 'length[6]',
                      prompt : 'Your password must be at least 6 characters'
                    }
                  ]
                }
              }
            })
          ;
        })
      ;
    

Don’t forget to reference the script within layout.jade otherwise it won’t be used for the login page.


    script(src='/javascripts/main.js')
    

GitHub authentication

Now that the login page is all set up, the next step is to add the GitHub authentication to the application. The go-to authentication middleware for Node.js is Passport, which has a npm package called passport-github that uses the OAuth 2.0 API for GitHub authentication. To use the package for your Node.js application run:


    npm install --save passport-github passport express-session 
    

express-session helps to protect the app from cookie exploits, and it also stores the session data on the server by saving the session ID.

Now with that installed, to make sure of the strategy, the application must be configured properly for it. The general outline of how the Passport authentication will work is that the developer will generate keys that will allow access to specific parts of user information for login. The authentication request is passed from the GitHub API to Passport for authentication using the strategy. In order to obtain the keys, you will need to create a GitHub developer application and get the CLIENT_ID and CLIENT_SECRET.

github dev settings

When a user wants to use GitHub to authenticate, they will be asked to authorize the application, and then once that is done, they will be redirected back to the web app. The information from authentication is then stored within the session, which will ensure that the req info will be redirected to the pages accordingly.

The workflow will be to have the user login with GitHub, authorize the application, and then display the information showing that the user data has been obtained.

Passport configuration

app.js

After installing the two packages, you will need to add them into the module dependencies, along with express-session to manage the session:


    var session = require('express-session')
    var passport = require('passport')
    var GitHubStrategy = require('passport-github').Strategy;
    

The GitHub authentication strategy is then used along with the application client ID and secret in the Node.js app. Configure the strategy after the Express app is initialized:


    passport.use(new GitHubStrategy({
        clientID: GITHUB_CLIENT_ID,
        clientSecret: GITHUB_CLIENT_SECRET,
        callbackURL: "/auth/github/callback"
      },
      function(accessToken, refreshToken, profile, cb) {
          return cb(null, user);
      }
    ));
    

You will notice here that the callbackURL is set to an address, one that you will need to account for when setting the routes for the application. The GitHub strategy will access the API, along with the user profile, the information is contained within a user object. The middleware function is used to verify the credentials, and then pass the information within req.user after authentication.

Next will be the session and user management code, used to maintain the login session and provide the ability to store user records. Generally when authenticating you will want to store the user to a database, and then Passport will deserialize the user from the session. For demonstration purposes, this Node.js will not use a database and just display the user information.

Session management is done with:


    app.use(session({secret:'tswift', resave: true, saveUninitialized: true}))
    
    app.use(passport.initialize());
    app.use(passport.session());
    
    passport.serializeUser(function(user, done) {
      done(null, user);
    });
    
    passport.deserializeUser(function(id, done) {
        done(null, user.id);
    });
    

It is important to note that the way the session is managed in this application is without storing it, so the information goes straight from the authentication token to being displayed on the page, which is definitely not what you want for an actual app. This is only to demonstrate how the GitHub authentication works with Node.js.

After this is all done, the last steps will be to organize the routes for authentication, so that after login the profile information will be displayed.

Middleware for authentication

The authenticate() function is used authenticate the request, and then redirect it to the proper page.

Routing in app.js


    app.get('/auth/github', passport.authenticate('github'));
    app.get('/auth/github/callback', 
      passport.authenticate('github', { failureRedirect: '/' }), 
      function(req, res) {
      //res.render('users', {user:req.user});
      res.redirect('/users');
    });
    

With all the middleware set up for authentication, the routing is fairly straightforward. The /auth/github route is used to begin the authentication, and the /auth/github/callback is the route that handles the callback from the GitHub strategy. It is important to remember that the callback URL is specified within the GitHub developer settings for the application, as well as within the Passport strategy setup.

On a successful callback, the route handler will redirect to /users where the information for the GitHub profile can be displayed. A useful thing to do is to test that the session is authenticated, by writing a testAuthentication function, and passing it into the route handler. It’s also good to have a logout feature, so the session isn’t hanging around.


    app.get('/users', ensureAuthenticated, users)
    
    app.get('/logout', function(req, res){
      req.logout();
      res.redirect('/');
    })
    
    function ensureAuthenticated(req,res,next){
      if(req.isAuthenticated())
        return next();
      res.redirect('/');
    }
    

With the routing all set in place, the last thing to do is to make the frontend pages are display the information.

GitHub Login information

/routes/index.jade

With all the /auth/github routing set up, you will need to create a button for GitHub login in. You can put the code under the submit button, which isn’t set to do anything.


    a(href='/auth/github').ui.fluid.large.blue.button
                        i.github.icon
                        | Sign in with GitHub
    

/routes/users.js

Within this file, the router middleware will be used to render the user profile page.


    router.get('/users', function(req, res, next) {
      res.render('users', { title: "Profile Page", user: req.user });
    });
    

/views/users.jade

And lastly here is where the profile information from GitHub will be displayed. The information is passed through req.user in JSON format with the name user so it is straightforward to take the information out.


    extends layout
    
    block content
        .ui.middle.aligned.center.aligned.grid
            .column
                h1.ui.teal.header Profile Information
                .form.ui.large
                    .ui.stacked.segment
                        .field
                          label Username
                            .ui.right.input.fluid
                                input(type="text", name="username", value='#{user.username}')
                        .field
                            label Name
                            .ui.right.input.fluid
                                input(type="text", name="name", value='#{user.displayName}')
                        .field
                            label URL
                            .ui.right.input.fluid
                                input(type="text", name="name", value='#{user.profileUrl}')
                        .field
                            label Email
                            .ui.right.input.fluid
                                input(type="text", name="name", value='#{user._json.email}')
                        .field
                            label Number of Public Repos
                            .ui.right.input.fluid
                                input(type="text", name="name", value='#{user._json.public_repos}')
                        a(href='/logout').ui.fluid.large.red.button Logout 
    

And with that you should be all done your Node.js application, with GitHub authentication!

profile page

Deploying to Heroku

Now with the app complete, deployment to Heroku is quick and easy. Follow the instructions at Heroku. The easiest way to to have your project saved onto GitHub first, and then use the GitHub Command Line Interface.


    heroku login
    heroku create
    

For Heroku deployment, you will need to update the callback URL and homepage URL specified within GitHub developer settings. The Heroku url is obtained after running heroku create.

To set the environmental variables within Heroku, use:


    heroku config:set CLIENT_ID='your_client_id_here' CLIENT_SECRET='your_client_secret_here'
    

Then lastly, to deploy the code and view the app:


    git push heroku master
    git open
    

If you run into errors, check the logs using: heroku logs --tail

After all this is done, your app should be deployed properly! It should look something like this example

What next?

Now that you have the basics of Node.js and authentication down, you can build your application further by having database integration, so you can save user login information and create accounts for the app. Depending on your application purposes, PostgreSQL is a good start. You can check out this tutorial for some further examples.