← Home

You (Probably) Don't Need That Auth Library

Published • Last Updated • 3 minutes

If you have ever visited r/nextjs, you have probably seen a post with someone complaining about an auth library. "NextAuth.js has bad or incomplete documentation", "Clerk (or Auth0) is too expensive", etc. One question I have not seen is, "Do I even need these libraries?" or better yet, "Why do I need these libraries?".

I asked myself the same question a while back when first looking into setting up single sign-on via Facebook Login and Google Login in a PHP application1. What I learned surprised me.

The Surprise

When I looked into how existing libraries worked, I found that it boiled down to only two URLs. Two!

But wait, you might be wondering, "Is he crazy? How could it be so easy if there are libraries like NextAuth.js and services like Auth0?"

The Problem

Before we can answer this, let's look at this table of auth providers:

Provider OAuth Protocol Version Documentation
Apple 2.0 developer.apple.com
Discord 2.0 discord.com/developers
Facebook 2.0 developers.facebook.com
GitHub 2.0 docs.github.com
Google 2.0 developers.google.com
Instagram 2.0 developers.facebook.com
LinkedIn 2.0 learn.microsoft.com
Microsoft 2.0 learn.microsoft.com
PayPal 2.0 developer.paypal.com
Spotify 2.0 developer.spotify.com
Twitch 2.0 dev.twitch.tv

What do they have in common? They all share the same OAuth Protocol Version, which is the easier version to work with. But, as you can imagine, that wasn't always the case.

Let's take a look at these auth providers:

Provider OAuth Protocol Version
Bitbucket 1.0a, 2.0
Dropbox 1.0, 2.0
Etsy 1.0
Evernote 1.0a
Flickr 1.0a
Goodreads 1.0
Netflix 1.0a
Okta 1.0a, 2.0
OpenTable 1.0a
Trello 1.0
Tumblr 1.0a
Twitter 1.0a, 2.0
WordPress.com 1.0

See the difference? While some of them support 2.0, others have yet to make it past 1.0 or even 1.0a. And, for the sake of my mental well-being, I will not go into the difference between 1.0 and 2.0. Let's say that if you are considering writing your own logic, 2.0 is the only way to go.

The Solution

Now, let's take a look at those URLs.

/auth

This is the URL used to redirect you to the provider's authentication confirm page.

const client_id = 'xxxxx';

const redirect_uri = 'http://localhost:8080/oauth/google/callback';

const redirectUrl =
  `https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=${redirect_uri}&client_id=${client_id}` +
  `&access_type=offline&response_type=code&prompt=consent&scope=https://www.googleapis.com/auth/userinfo.email`;

/token with code

Once you confirm, the page will redirect you back to your app with a code parameter in the URL's hash. You then use this code to fetch the tokens you will use to make further requests. Note that this token is single-use and only valid for about 30 seconds.

const code = 'xxxxx';

const client_id = 'xxxxx';
const client_secret = 'xxxxx';

const redirect_uri = 'http://localhost:8080/oauth/google/callback';

const response = await fetch('https://oauth2.googleapis.com/token', {
  method: 'POST',
  body: JSON.stringify({
    code,
    client_id,
    client_secret,
    redirect_uri,
    grant_type: 'authorization_code'
  })
});

An example response from this request:

{
  ...
  "access_token": "xxxxx",
  "expires_in": 0,
  "refresh_token": "xxxxx"
  ...
}

/token with refresh_token

And finally, when the access token you got from the request above expires, you can use the refresh token to get another one.

const access_token = 'xxxxx';

const response = await fetch('https://oauth2.googleapis.com/token', {
  method: 'POST',
  body: JSON.stringify({
    refresh_token,
    client_id,
    client_secret,
    grant_type: 'refresh_token'
  })
});

An example response from this request:

{
  ...
  "access_token": "xxxxx",
  "expires_in": 0,
  "refresh_token": "xxxxx"
  ...
}

That's it!

And because I got sick and tired of digging for those URLs, I made a package for myself and others to use https://github.com/neogeek/create-app-oauth-providers.

But you don't have to use this package! In fact, I recommend you use it as a reference, as there is barely anything to it.

Footnotes

  1. https://github.com/neogeek-deprecated/Overseer-Framework/blob/master/oauth2.php