OAuth2 From Scratch
Tags: oauth, oauth2, pkce, react
Published: 2020-02-11 08:08:52

---
title: OAuth2 From Scratch
published: true
description: Learn how to set up an OAuth 2 workflow from scratch.
tags: oauth, oauth2, pkce, react
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/epawo771jxfwoblsxb5n.jpeg
---

You see it everywhere: "login with < Google|Twitter|GitHub|Facebook|etc >". Personally I like it, A LOT. It's fast, easy, and saves me time. Who needs more passwords to remember? Heck, I used it to login to write this post. 

Now it's time to find out how it works. Come with me, as we journey into the magical world of OAuth 2...

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/k9gr1ax1xfjxkdgag8rj.jpeg)

### TLDR
OAuth 2 is easy to implement. There are just 2 steps: request a code and use that code to get a token. That's it.  If you prefer reading this post in another language, [I translated it to typescript](https://github.com/coleHafner/oauth-test/tree/parcel).

### Set up the client
I chose Google, but, since OAuth is a standard, it should be fairly similar for any provider. Here's how to set up an OAuth client with Google:

1. Create a new project [on Google dashboard](https://console.developers.google.com/apis/dashboard)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/b79epetfel0uraq0jxky.png)
1. Enable APIs for that project. You can enable ANY service Google has: Drive, Gmail, Sheets, Docs, Voice-to-text, etc. The basic one you'll need is the Google People API, which provides information about user profiles
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/sp16px5qcn65t0v98vxv.png)
1. Create an OAuth client. This will be the client id/secret you need for requesting the oAuth token. First click 'Create Credentials' and then OAuth Client ID. It will prompt you to create a consent screen. Follow the prompts and then fill out the form like this. Make sure to set up the authorized domains and redirect domains. I'm using `https://localhost`, but you can use whatever you like, as long as it's HTTPS. It's easy to run HTTPS locally with [this node package](https://www.npmjs.com/package/https-localhost).
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/az99q6agr6nflmgaqgs9.png)
1. Copy the client id and secret for later use. 

### Get a Token
Now here's the fun part. It takes just 2 steps to get an OAuth token from Google:

#### Request an authorization code

The code is not THE token, it's called the authorization code and it's used to get the token later.

"That's dumb. Why not just send the token?" Good question. It used to be that way. It is called the [Implicit Grant Type](https://oauth.net/2/grant-types/implicit/). It's a *bad idea* and generally not recommended any more (in some cases outright banned). 

We'll be using the [Authorization Code Grant Type](https://oauth.net/2/grant-types/authorization-code/). It takes one more step, but is more secure.


```javascript
// GET request with the following params
{
   code_challenge_method: 'S256',
   scope: 'email profile', // tells google what info you want
   access_type: 'offline',
   response_type: 'code',
   client_id: clientId, // clientID from step 1
   redirect_uri: redirectUri, // page that handles token request
   code_challenge: challengeToken, // hashed/encoded PKCE challenge
   state: stateString, // random guid that will be passed back to you
}


// example
<a href="https://accounts.google.com/o/oauth2/v2/auth?code_challenge_method=S256&scope=email%20profile&access_type=offline&response_type=code&client_id=<client id>&redirect_uri=https://localhost/auth&code_challenge=o259Sjip6Cevgfe8RUw59jVO5z1mSzji_OuzIZFDTug&state=434595.10145617445">
   Login with Google
</a>
```

The aforementioned `code_challenge` parameter is from a method called [PKCE](https://oauth.net/2/pkce/). It stands for Proof Key for Code Exchange and is a security method to help make OAuth more secure. At its core, it's an hashed string that you send to the provider so it can verify your identity in the second step by sending the original string from which it was hashed. There's a real helpful [node package](https://www.npmjs.com/package/pkce-challenge) that helps you generate PKCE challenges. 

#### Request the OAuth Token
If all goes right on the first request, the provider will ask the user to login, generate the authorization code, and redirect to the uri specified in the `redirect_uri` param. It will include 2 important URL params: `code` and `state`. 

Code is the authorization code needed to request the OAuth token.

State is the initial `state` param you sent in the last step. It's a simple mechanism to ensure the client can verify the identity of the server. If the state doesn't match, or isn't included, you can know not to trust that request. 

```javascript

// POST request with the following params
{
   code: authCode, // authorization code from the provider
   client_id: clientId, // id of the OAuth client
   client_secret: clientSecret, // secret of the OAuth client
   redirect_uri: redirectUri, // same from last request ¯\_(ツ)_/¯
   grant_type: 'authorization_code',
   code_verifier: codeVerifier, // raw PKCE token
}

// returns the following payload
{ 
   access_token: <access token>, // this can be used to query APIs
   refresh_token: <refresh token>, // can be used to get a new token
   expires_in: <expiration in seconds>, // usually set to an hour
   id_token: <id of the user>, // haven't really found a use for this
}
```

#### Use the Token!
You can then use the token to get data from Google on behalf of the user.

```javascript
axios.get(
  'https://www.googleapis.com/oauth2/v2/userinfo',
  {
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': `Bearer ${token}`
    }
  }
)
```

Google has a cool [OAuth playground](https://developers.google.com/oauthplayground) where you can try out all kinds of APIs. 

That's it! You're done! 

### Resources 
Here's a link to some of the resources I used to learn about this:

PKCE explanation: https://oauth.net/2/pkce/

PKCE node package: https://www.npmjs.com/package/pkce-challenge

Google OAuth Playground: https://developers.google.com/oauthplayground 

OAuth2 Overview: https://aaronparecki.com/oauth-2-simplified/#web-server-apps

Google OAuth Walkthrough: https://developers.google.com/identity/protocols/OAuth2InstalledApp#obtainingaccesstokens

Sample GitHub repo: https://github.com/coleHafner/oauth-test/tree/parcel