OAuth Simplified
Tags: oauth, node, javascript, authentication
Published: 2018-12-10 12:01:03

---
title: OAuth Simplified
published: true
description: OAuth like a BOSS
tags: oauth, node, javascript, authentication
---

We often need to implement some sort of login functionality in our web apps, or authorize our app to access the user's data programmatically.

Historically this was done by using the user's password directly for authorization. Unfortunately this leads to alot of problems, so a delegated authorization framework was invented, called OAuth.

Two versions of OAuth are available: OAuth 1.0a and OAuth 2.0, the latter being the most widely used today. Both OAuth 1.0a and the so called _server side flow (Authorization Code Grant)_ of OAuth 2.0 require a server app, and involve multiple steps to improve security.

This makes these two types of authorization flows a bit more complicated to implement, so naturally, we look for third-party modules ready to drop in and get going.

# Login

A few years ago I was using Passport to implement login functionality using OAuth in my NodeJS app. The problem was, however, that Passport was never built around the idea of having multiple login providers in a single app. While totally possible it required separate module for every provider, developed by a different person.

On top of that Passport makes one additional request after the OAuth flow to get a more detailed profile of the user. Unfortunately that's not part of the specification, and over time it become an obstacle, because I always needed something slightly different.

I ended up with fair amount of glue code in my app, just for a handful of login providers. And to make matters worse - now I had to write tests for it.

So I asked myself:

> Is it possible to create something _dramatically_ simpler?

You see, it doesn't matter if something already exists:

> You can innovate **always**!

You can always take already existing solution and create a better one, a simpler one, unique in its own way.

Meet **[Grant]**!

# Goals

Grant was built around very narrow and extreme use case:

> Support for **unlimited** number of OAuth providers, without the need of **any** glue code.

As we all know good configuration data structure is the backbone of every great app. At its core Grant is exactly that:

> A simple, yet powerful configuration data structure.

Having all aspects of the module defined as JSON, opens up the doors for all kinds of interesting use cases:

- static configuration per environment
- nested [static] sub configurations per provider
- [dynamic] configuration per authorization attempt

In fact, the configuration is not even required, it can be passed dynamically via GET or POST request:

> Making [Grant] a completely transparent **[OAuth proxy][oauth-proxy]**.

Meaning that you can deploy it somewhere on your stack and access it from **any** other server and programming language.

# How

First we need to register an OAuth app for every provider that we want to login with. For example, we have to register OAuth 2.0 client app for [Google], and OAuth 1.0a client app for [Twitter]. The redirect URL of our OAuth apps should **always** end with `/connect/[provider]/callback`:

```
http://localhost:3000/connect/google/callback
http://localhost:3000/connect/twitter/callback
```

Then we need a configuration file where we can put our OAuth app credentials along with a few other options:

```json
{
  "defaults": {"origin": "http://localhost:3000", "callback": "/hello", "state": true},
  "google": {"key": "...", "secret": "...", "scope": ["openid"], "nonce": true},
  "twitter": {"key": "...", "secret": "..."}
}
```

Lastly, our server may look like this:

```js
var express = require('express')
var session = require('express-session')
var grant = require('grant-express')

express()
  .use(session({secret: 'dev.to'}))
  .use(grant(require('./config.json')))
  .use('/hello', (req, res) => res.end(JSON.stringify(req.query, null, 2)))
  .listen(3000)
```

This will allow us to login with Google and Twitter by navigating to the following URLs in our browser:

```
http://localhost:3000/connect/google
http://localhost:3000/connect/twitter
```

# Conclusion

> OAuth has never been easier!

And to prove that [Grant] comes with support for **180+** login providers, but any other provider conforming to the OAuth spec should work out of the box.

Grant was also developed along with an [example app][app] showcasing the design goals behind it, and its real potential. As you can imagine this app consists of almost no code on the server, and only a JSON configuration.

Lastly, the [official documentation][docs] of the module is a great source of information where I try to cover diverse set of features and use cases.

Happy Coding!


  [grant]: https://github.com/simov/grant
  [app]: https://grant.outofindex.com

  [docs]: https://github.com/simov/grant#table-of-contents
  [static]: https://github.com/simov/grant#connect-static-overrides
  [dynamic]: https://github.com/simov/grant#dynamic-http
  [oauth-proxy]: https://github.com/simov/grant#dynamic-oauth-proxy

  [google]: https://console.developers.google.com
  [twitter]: https://developer.twitter.com/en/apps