Mind of Lloyd

Mind of Lloyd

Zoom OAuth with a NuxtJS App, Part 2

Zoom OAuth with a NuxtJS App, Part 2

All About ServerMiddleware

Subscribe to my newsletter and never miss my upcoming articles

Listen to this article

No reason for a long intro paragraph. Here is the first part for Zoom OAuth with NuxtJS, if you haven't seen it yet. Let's get to work!

Preliminaries:

  • For some strange reason, fetch is not automatically available in our serverMiddleware (don't ask, I dunno). Hence, we'll need to import the node-fetch library into our project like so: const fetch = require('node-fetch').

First Steps:

  • Let's rewrite the skeleton of the serverMiddleware we made in the previous article to include an arrow function, just for code readability.
const fetch = require('node-fetch')

const handler = async (req, res) => {
//
}

export default handler

The Work Begins: Our serverMiddleware will help us get the Access Token which will be used to get user data.

  • In an async function, I prefer to use try...catch blocks because they make error and response handling easier and cleaner. So let's create one inside our handler.
const handler = async (req,res) => {
    try {
        //
    }
    catch(e){
        console.log(e)
    }
}
  • To get the access token, we'll need to make a POST request to Zoom with these three parameters: grant_type, code, and redirect_uri.
    • The value for grant_type, according to the docs, is 'authorization_code'.
    • For code, we'll need to catch the value for the code param that we got from the client-side.
    • The value for redirect_uri is the same base URL that we have in our .env file.
  • To get code, we'll use the URL interface that is also made available in Node. The URL interface has a property called searchParams that has all query params in an object, and we can use the get method to retrieve its value. To make use of the URL interface, we'll need to make an absolute URL, since the URL we get from the client is only partial.
    • Afterwards, we can create the URL to which we'll be making a POST request.
try {
    const url = new URL(req.url, `https://${req.headers.host}`)

    const zoomUrl = new URL('https://zoom.us/oauth/token')
    zoomUrl.searchParams.set('grant_type', 'authorization_code')
    zoomUrl.searchParams.set('code', url.searchParams.get('code'))
    zoomUrl.searchParams.set('redirect_uri', process.env.NUXT_ENV_BASE_URL)
}

The Work Continues: Zoom has a strange demand that we use a special code in our header to make our POST request. This code is special because, in pseudocode, it would look something like this: base64(CLIENT_ID:CLIENT_SECRET).

  • We turn that into real code by using Node's Buffer class. This class helps in the handling of binary data. We'll create a new buffer with the concatenated string using our Zoom client ID and client secret, and then we'll convert that into base64.
const data = process.env.NUXT_ENV_ZOOM_CLIENT_ID + ':' + process.env.NUXT_ENV_ZOOM_CLIENT_SECRET
const newData = Buffer.from(data, 'utf8')
const b64string = newData.toString('base64')
  • Now we can finally make our POST request. I like to define my options object first for fetch. If we await our JSON response, we should get back an object with our access token.
const options = {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + b64string
    }
}
const response = await fetch(zoomUrl, options)
const json = await response.json()

The Work Ends:

  • Sometimes, for a variety of reasons, the access token is not generated, hence we'll need to move forward only if there is an access token. To get our user, we'll make another fetch, but using the GET method this time.
    • Just like with most other token-based auth, we'll use our access token as a bearer token in the header.
  • When that is done, we will await the User object, and send the data back to the client.
    if (json.access_token){
      const preUser = await fetch('https://api.zoom.us/v2/users', {
          method: 'GET',
          headers: {
              'Authorization': 'Bearer ' + json.access_token
          }
      })
      const user = await preUser.json()
      res.setHeader('Content-Type', 'application/json')
      res.end(JSON.stringify(user))
    }
    else {
      throw new Error('Something went wrong!')
    }
    
  • In our last article, the method that we used to fetch user data was getZoomUser. In the last line of that method, just log user to the console, open your browser and you'll see what you get.
    • You will see an object with properties that look unrelated at first glance. Open the object and you will see the user that you got permission from to use their data (it'll most likely be your account).

Conclusion:

  • In just about every frontend framework that you use, persisting the data you get from the API is hard work. In a future article, we'll discuss state management and persisting state with cookies.
 
Share this