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
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.
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.
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
.
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!
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.