Skip to main content

Building a simple Web App with OAuth 2.0

Hi all! In this blog I'll give you all a brief introduction to OAuth 2 and how to build a simple web app which utilizes OAuth 2 as the authorization mechanism. If you have not used OAuth 2 earlier, don't panic, I'll make the things simple as possible. So let's get started

What is OAuth 2 ? In simple terms OAuth 2 is an authorization framework that grants users limited access to information in one site from another site, by means of a token.This is a secure way to expose information to third party services without exposing users credentials.The original OAuth 2 specification is a bit complex and can be confusing if you are reading for the first time, however the basic concepts behind OAuth 2 are very simple and easy to understand.  Many popular companies like Google, Amazon, LinkedIn, Facebook, Instagram, NetFlix and PayPal now use OAuth 2 to allow users access account information using third party services. Today we will look into how we can build a simple web app that authorize users using Google OAuth 2 and will use the Google API to upload files to the user's drive.

Before starting to build our app lets understand how OAuth 2 works. The initial step of OAuth 2 is to authorize the user. There are 4 different mechanisms/grant types that OAuth 2 uses to authorize users:

  • Authorization Code Grant - The front end application issues a code after the user logs in. The authorizing server uses this code and the client password to issue and access token which can be used by the client app to access user information. 
  • Client Credential Grant - An access token is issued from the server authenticating only the client without authenticating the user. 
  • Implicit Grant - Access token is issued as soon as the user logs in
  • Password Grant - Access token is issued when the user logs in along with all the login information such as username, password, client id and client secret. Easier to implement but may have other issues.
Depending on our scenario we should use one of the above grant types which best suite our application. In the application that we are going to build we will use authorization code grant.

Below diagram shows the main flow of events between the client app and the authorizing google servers when using authorization code grant.



As seen in the above diagram we need to follow basically four steps when accessing Google API using OAuth 2. 

1. Get OAuth 2 credentials from Google API Console.
 Navigate to Google API Console. You will be redirected to the dashboard page of Google API Console as follows. 


Next select Credentials → Create Credentials → OAuth Client ID. You will get a page as follows



Select Web application (since we are going to make a web application), and give a name to your application. Then enter redirect URI , in our case it is http://localhost:3000/dashboard page . Then hit create button. You will get the client ID and the client secret which will be known by both the our application and the google servers. These OAuth credentials are stored in the keys.js file of our application.

// OAuth credentials obtained from Google API Consoleconst KEYS = {
    'googleOauth': {
        'clientID': "948103666603-qj71gukhm51805vof2861q3huuu1uetg.apps.googleusercontent.com",        'clientSecret': "M61wWOyIJvJzq-3LRjQt277b",        'callback': '/auth/google/redirect'    },    "session_key": "secret123"}

module.exports = KEYS

2. Get access token from Google Authorization Server
In order access data using Google API we need to get an access token first which grants us access to the API. As our server side programming language we use node js along with passport js to implement google authorization with OAuth 2. Passport JS is a flexible middle ware for node js that can used with any express based web application.

const passport = require('passport')
const GoogleStrategy = require('passport-google-oauth20')
const KEYS = require('./keys')


// set cookie base on this userpassport.serializeUser((user, done) => {

    let sessionUser = {
        _id: user.googleID,        accessToken: user.accesstoken,        name: user.name,        pic_url: user.pic_url,        email: user.email    }

    done(null, sessionUser)
})

// get cookie & get relevent session datapassport.deserializeUser((sessionUser, done) => {

    done(null, sessionUser) // now can access request.user})


passport.use(
    // google login    new GoogleStrategy(
        // google keys        {
            clientID: KEYS.googleOauth.clientID,            clientSecret: KEYS.googleOauth.clientSecret,            callbackURL: KEYS.googleOauth.callback,            passReqToCallback: true
        }, (request, accessToken, refreshToken, profile, done) => {

            //save data along with the access token in the session            user = {
                "accesstoken": accessToken,                'googleID': profile.id,                'name': profile.displayName,                'pic_url': profile._json.picture,                'email': profile._json.email            }

            done(null, user)
        }
    )
)

3. Send access token with API call
In order to access the access the google drive's API to upload a file, we need to pass the access token that we obtained along with the API request as follows.

router.post('/upload', function (req, res) {

    // not auth    if (!req.user) res.redirect('/auth/login/google')
    else {
        // auth user
        // configuring google drive with access token        const oauth2Client = new google.auth.OAuth2()
        oauth2Client.setCredentials({
            'access_token': req.user.accessToken
        });
        const drive = google.drive({
            version: 'v3',            auth: oauth2Client
        });
        //move file to google drive
        let { name: filename, mimetype, data } = req.files.file_upload
        // sending API request to upload a file         const driveResponse = drive.files.create({
            requestBody: {
                name: filename,                mimeType: mimetype
            },            media: {
                mimeType: mimetype,                body: Buffer.from(data).toString()
            }
        });
        driveResponse.then(data => {

            if (data.status == 200) res.redirect('/dashboard?file=upload') // success            else res.redirect('/dashboard?file=notupload') // unsuccess
        }).catch(err => { throw new Error(err) })
    }
})


4. Refresh access token if necessary
Access tokens are not permanently valid , instead they have limited lifetimes. However if we need to access the Google API beyond the lifetime of an access token we can get a refresh token which allows us to obtain more access tokens.

The UI of the app is implemented using simple html and materialize css, hence you'll find this easy to implement. Below are 2 screen shots of the UI.


You can download the full project from github

I hope this blog was helpful for you in learning basic concepts of OAuth 2.

Comments

Popular posts from this blog

How to get started with MongoDB

In my last post I gave you all a brief introduction about NoSQL databases and its uses. As I mentioned in my last post , in this blogpost I'll give you all an overview of MongoDB and how to get started using MongoDB. Basically MongoDB is a document-oriented, NoSQL database and it can be rated as the most popular and widely used NoSQL database. MongoDB is free and open source , therefore anyone can simply download it from their site and start using it in their applications. It stores data as JSON(JavaScript Object Notation) like documents with schemas. In fact, data is actually stored in MongoDB as BSON objects. BSON is very much similar to JSON except that it is the binary representation of JSON. Unlike JSON, BSON is optimized for performance and navigational abilities. Typically data will be stored in the format shown on the following picture.  Key features that had contributed to the huge popularity of MongoDB are as follows: Support Ad hoc queries together JavaScript ...

A comparison between Node and Express

If you are programmer who have worked a long time with JavaScript you might know that , earlier JavaScript was just a scripting language used in the client side. However now the story is different. With many libraries like Node js and Express js being added to the JavaScript family JavaScript have evolved beyond, just being a scripting language in the client side. With these new libraries being added, now it is possible to build entire sites on JavaScript, extending it from front to back-end seamlessly. So what is Node and Express? Let's  clear this out step by step! What is Node js? Node js is an open source JavaScript runtime environment that executes JavaScript code server side. Node enables developers to use JavaScript for server side scripting. Node uses an event driven, non-blocking I/O model that makes it light weight and efficient. Because of this model Node js is particularly useful in web application that have many input/output operations and for real time web appli...

Difference between callback functions and promises in javascript

If you have ever worked with JavaScript you might have the experience that it is a quite confusing language to understand at first. This is because  in JavaScript there are many ways to do the same thing, and also unlike most other programming languages, if you do a small mistake in JavaScript instead of giving any errors, the program would behave in a totally different way than what you expect. Therefore, without understanding the basic concepts of JavaScript, it's quite difficult to work with it. In this post I'll be explaining about callback functions and promises, what they are used for and the difference between the two methods. Actually callback functions and promises are 2 different ways of doing the same thing. By default JavaScript is an asynchronous programming language. Which means that JavaScript does not execute instructions line after the other as in many programming languages. Whenever JavaScript come across an operation that takes relatively a long time, typic...