OAuth: Logging In with EveryAuth and NodeJS

Lock and Key – Photo by Bohman (Flickr) [CC-BY 2.0]

Connecting to social networks is nearly a must have for every new fangled website in the works. And increasingly, many websites are using OAuth authentication of other social networks to log in to their websites, thereby alleviating users of the need to remember a separate username and password for your website. Using Node, it is surprisingly easy to hookup to your favourite social network with the node module, Everyauth.  So, without further ado, let’s demonstrate how to log into a website using Twitter.

The Aim

Let’s create a basic authentication system that allows:

  • User to log in to the website using a button
  • Display to the user a greeting with their name, like “Hi, KOOStudios!” (That’s my Twitter handle – Follow Me!)
This tutorial requires the following software / node modules. Be sure to download them through the links below or through npm.

1. Setting Up

Let’s do the configuration first. You may generate a project folder using the same structure as a normal NodeJS application. If you don’t  remember how, be sure to check my previous post. Now, we start with our file, main.coffee which will be pretty generic:

# Requires and Variables
exp = require 'express'
app = exp.createServer()

# App Configuration
app.configure () ->
    app.set 'view engine', 'jade'
    app.set 'views', __dirname + '/views'
    app.use exp.static __dirname + '/views'
    app.use exp.bodyParser()
    app.use exp.methodOverride()
    app.use exp.cookieParser()
    app.use exp.session {secret: 'bobsyouruncle'}
    app.use everyauth.middleware()
    app.use app.router

app.listen 1337
console.log 'Server running at http://localhost:1337'

If you followed my previous blog post, most of this is the same. What appears different is that we’ve added four extra lines at the bottom of the configuration. Here’s a little explanation of what they are:

  • Line 12 calls on the cookieParser. When the user logs in, the session information (explained below) will be saved into a cookie, allowing users to move from page to page. The cookieParser method allows us to deal with cookies.
  • Line 13 calls on the session method which allows us to deal with sessions. When a user logs in to the site, a “session” is generated, like a temporary ID card that allows the site to recognise the user when they use it. The secret will be the secret passphrase that will hash it from prying eyes.
  • Line 14 imports the everyauth middleware. We don’t expressly need this in this tutorial but this will lets us use express helpers which are functions which can determine if the user is logged in or let us access the user details.
  • Line 15 is the app.router which tells the application to mount the routes. Normally we use app.get which is sufficient but everyauth uses default routes that can save all the trouble by using this one line.
Note, I recommend writing these lines in this order, not only because it makes more sense but some lines are dependent on lines before it.
 

2. Getting Cozy with the Twitter API

To work with Twitter, you actually need to sign up your application and get a username and password to access Twitter’s interface. These are called the consumer key and consumer secret. You can get these by signing up here. Keep the consumer key and secret handy, you will need them.

After you “create” your application with Twitter, there’s just one tiny little thing we have to do. Because Twitter sends users back to a callback URL, that URL has to be acceptable by Twitter. If you try putting in http://localhost, Twitter will reject it. It’s stingy like that. So we have to make Twitter believe that we have a real URL.

To do this, you can edit the host file. This process will depend on your operating system but the hosts file sets out the domains that are to be preferentially directed to certain locations. In our case, we will be directing something innocent like http://dev.koostudios.com, which is not a real location, to our localhost, 127.0.0.1. So, find your hosts file (try this if you don’t know where it is) and open it up in your favourite editor to add the following line. You may need root access.

127.0.0.1  dev.koostudios.com

Feel free to substitute your own namespace! Save the file and get ready for the awesomesauce.

3. Starting with Everyauth

Whoa! That was a lot of configuration wasn’t it? Let’s get on to the easy bit with the logging in part. First things first, this is the application logic to log into Twitter. Place this in the main.coffee file abovethe app configuration lines.

everyauth = require 'everyauth'
everyauth.twitter
    .consumerKey('')
    .consumerSecret('')
    .findOrCreateUser((session, token, secret, user) ->
        promise = @.Promise().fulfill user
    ).redirectPath '/'

Done! That’s it! This is the backend of the logging in process. We tell our application to include the package everyauth and use the twitter method (Lines 1 and 2). Then, we give it our consumer key and secret (Lines 3 and 4) and the real magic happens in the findOrCreateUser method. This allows you to log in to Twitter when the browser is turned to /auth/twitter and be returned straight back to the root location. Plus logging out is as easy as hitting up /logout. All Automagically!

What isn’t much explained is Line 6. OAuth requires you to send back information from your end of who is actually logging in. However, because NodeJS is asynchronous, that is, it keeps on going and does not wait for lines to stop, it is a tad too fast and sends out a promise that we will give it user information instead. The findOrCreateUser function must return a fulfilled promise so I’ve just sent the user information straight back in Line 6. Please note, normally we would have a few lines before fulfilling the promise to find the user on our database first (as we see later).

4. Fun with Front-End

Now that you have the entire login mechanism on the back-end, it is time to deal with the front-end. As mentioned previously, you only need a link to /auth/twitter to start the login process and a link to /logout to log out. So let us set up the link for logging in and logging out by determining whether we’ve logged in. Heck, let’s even add a greeting to say hi when they’ve logged in. Here is the routing done on main.coffee.

app.get '/', (res, req) ->
    if (req.session.auth)
        user = req.session.auth.twitter.screen_name

res.render('index', {
    layout: false
    locals: {user: user}
}

Notice that I am still rendering ‘index’ if I am logged in or not. The only difference is that the user variable will be set to their twitter screen name if they are logged in or will be undefined if they are logged out. We can use this information now to build index.jade.

!!! 5
html
    body
        - if (typeOf(user) != 'undefined')
            span= "Hi, " + user + " "
            a(href="/logout") = "Logout"
        - else
            a(href= "/auth/twitter")= "Login"

And that’s done! We’re using the neat JavaScript feature in index.jade to figure out whether user is defined or not and displaying a greeting with a logout button or a login button depending on the answer. Cool, huh?

5. Running

If you are using the awesome coffee –watch command, your amazing coffee files will have been compiled. However, if you are not, run the following in your project folder:

coffee --compile main.coffee

Now, you can run your little monster! Simply type:

node main.js

Remember the compiled version of the file is the one you need to run! And if you get your own lovely message of ‘Server running at http://localhost:1337′, you know you’ve got yourself a winner. Just hit up your browser and take a look at the magic!

Conclusion

Dealing with OAuth in NodeJS is dead simple. In fact, I think it is laughably simple. EveryAuth deals with everything and deals with everything automagically for you. You simply have to give it your API details and it logs the user in, saves their information in a cookie and lets you have default login and logout paths. The great thing about EveryAuth is that the process is pretty much the same for all the other APIs that it supports, so don’t stop with Twitter but keep going… Google, Facebook, LinkedIn… it all awaits!

This entry was posted in Tutorial. Bookmark the permalink.
  • Sigurd

    Thanks again for a simple and interesting introduction! The only change I had to do to make it work was adding “user” in req.session.auth.twitter.screen_name so it is req.session.auth.twitter.user.screen_nameBut that was really a minor change :) Thank you!

  • Santiago Gaviria

    Thanks

  • Fred

    You can use coffeescript if you want, but please, just post the resulting javascript.
    Coffescript is NOT a language, it’s just a helper and must stay personnal I think.
    Your final code is Javascript, and this is Javascript you should post.
    Just an opinion.

    • brian

      I disagree, if you write in Coffeescript you should post that. Nobody wants to read generated Javascript, it’s not the same way we’d write it. Calling it a ‘helper’ is a poor way to define it. Coffeescript and other preprocessors can be considered languages.

  • http://twitter.com/TaowH Tw Huang

    Thanks for your tutorial. But there’re two issue I identifed:
    1. I have to put ‘everyauth = require ‘everyauth” on top of main.coffee;
    2. The indention for ‘res.render(‘index’, {
    layout: false
    locals: {user: user}
    }’ seems be wrong.

    Moreover, I still need help to get it work on my side. I already got ‘Server running at http://localhost:1337‘, but when i assess the link ‘http://localhost:1337′, I got the following error message:
    TypeError: Cannot read property ‘auth’ of undefined
    Could you help me to fix this please?

  • sharonjl

    For the love of god, please stop using coffescript.