OAuth with Zoom

Overview

OAuth 2.0 is the industry-standard authorization protocol that allows applications to obtain requested access to user accounts over the HTTP service with the user’s approval.

At Zoom, we prioritize customer’s data security very seriously. Traditionally, a lot of applications used the old model of client-server authentication using which an end-user (the resource owner) has to provide personal credentials such as username and password to authorize third-party applications to have access to their resources. This comes with a lot of security issues and does not allow the user to easily place constraints and limit the scope of access. OAuth 2.0 provides solutions to these issues and establishes improved standards for privacy.

As a developer leveraging Zoom’s APIs, you can use OAuth to make authorization requests to have access to users’ information related to their Zoom accounts once the users grant you the permission to do so. Your app might need access to various scopes of information and once the user grants authorization to your requests and the authorization is validated by Zoom’s API, an access token gets generated. Your application must then provide Zoom’s API with the access token for authentication. Once the access token is validated, your app receives the requested resources from Zoom’s API.

Get authorization code

Once you have your app credentials, you can use your Client ID to request an authorization code. This is not the final code that will be used to request user data - it will be used in the next step to authenticate a request for the access token.

Authorization endpoint

The authorization endpoint is where the end-user is authenticated and also where the end-user provides your app with the authorization grant to have access to the requested scopes. Your app must direct the end-user to Zoom’s authorize endpoint with client credentials to request an authorization code. When the user authorizes your app with access permissions, Zoom’s API server authenticates the user and directs the user back to your app along with an authorization code.

Make a https GET request call to the Zoom authorization endpoint with your Client ID and Secret to retrieve your authorization code with the following query strings:

response_type=code 
client_id={clientID} // auto-generated when you register your app in the marketplace
redirect_uri={redirect_uri} 

Sample request

POST https://zoom.us/oauth/authorize?response_type=code&client_id={YOUR_CLIENT_ID}&redirect_uri={https://YOUR_REDIRECT_URI}

There are additional parameters that can be passed along with the request. The entire list of Available Parameters is shown below:

Parameter Description Required
response_type This is the authorization type. In this case, it should be set to code. Yes
client_id The identifier issued to the client during the registration process. Yes
redirect_uri Your app’s url to which Zoom redirects the user with the authorization code or an error response code. This must match one of the redirect URIs used during registration. Yes
state An optional string passed with the request to prevent CSRF. The state will be sent back when the redirect occurs to ensure that you initiated the request.
e.g. state=DH73HL9123hfk873g
Optional
scope A URL encoded the string of scopes you’re requesting for your app on behalf of the user. If you do not provide this during the request, we will fallback to the scopes you defined during your application registration.
e.g. scope=user%3Aread+meeting%3Awrite+webinar%3Awrite
Optional

Sample Node Request

const zoomclientid = "enter your client id";
const myappredirect = "https://myapp.io/zoomcallback"; 
const zoomauth = "https://zoom.us/oauth/authorize" + "?response_type=code&client_id=" + zoomclientid + "&redirect_uri=" + myappredirect; 
res.redirect(zoomurl);

If this is the first time that you are requesting authorization from a user, the user will be directed to Zoom’s authorization page. Once the user allows your app to access their account, the user will be redirected to the URI that you have set up as the redirect_uri.

If the user has previously authorized your app with access and if the authorization is still valid, the authorization screen will be immediately bypassed and the user will be redirected to your redirect_uri. Zoom will return a 200 OK response header if your Client ID and redirect URI match with what you have registered when creating the app in our marketplace.
If you get a 400 or a 401 error, check your Client ID and redirect URI again to make sure they match with what has been registered in the Zoom marketplace.

Zoom will trigger a callback to the redirect URIthat you previously registered. The callback will have the authorization code that you have requested in the above step. This code will be attached as a query string in the redirect URI as shown below:
https://myapp.com/oauth/?code=eYanu1uG5TucLenI
This code will be used in the next step to request the access token to allow your app to make requests on behalf of the user. If you sent a state value with the original request, this will also be sent back and can be used to test for CSRF attacks. If the value provided in the state parameter does not match with the response state, the request is immediately denied for security purposes and you will receive a 401 error message.

Request an Access Token

Once you have the authorization code, you can finally make a request for an access token. This is the token that you will use to make subsequent requests on behalf of the authorized user.

Access Token Endpoint

Make a POST request to https://zoom.us/oauth/token endpoint. Include the following query parameters along with your requests:

Parameter Value
grant_type authorization_code
code {your_authorization_code}
redirect_uri {your_redirect_uri}

Additionally, you should include the following in the authorization header:
"Authorization" : "Basic base64(client_id:client_secret)"

Sample Node Request
router.get('/zoomcallback', function(req, res) {

    const zoomtokenep = "https://zoom.us/oauth/token";
    const myappredirect = "https://myapp.io/zoomcallback";

    if (req.query.code) {
        var auth = "Basic " + new Buffer(zoomclientid + ':' +
            zoomclientsec).toString('base64');
        var url = zoomtokenep + '?grant_type=authorization_code&code=' +
            req.query.code + '&redirect_uri=' + myappredirect;
        request.post({
            url: url,
            headers: {
                "Authorization": auth
            }
        }, function(error, response, body) {
            if (error) {
                console.log("Error when getting Zoom token = " + error);
                return;
            }
            body = JSON.parse(body);
            if (body.access_token) {
                accessToken = body.access_token;
                refreshToken = body.refresh_token;
                // Process and securely store these tokens
            } else {
                console.log("FATAL - could not get zoom token");
            }
            return;
        });

    } else {
        console.log("Missing code from Zoom");
    }
});

Evaluate the access token response

If the request is successful, a JSON response will be returned. This JSON object will have all the information you need to complete requests and to request additional tokens once the initial access token expires.
The following response parameters will be returned:

Parameter Description
access_token The token you will use to make requests on behalf of the user.
token_type The type of token that will be sent to make requests.
refresh_token Used when requesting a new access token once the previous one has expired.
expires_in Time in seconds until the access token expires. Once expired you will use the refresh token to request a new access token.
scope A space-delimited string of available scopes associated with your app for the access token.
Example Response Schema
{
  "access_token": "5kwaMOrdEFWx1jYVK8qg80cImPYBA83Zff",
  "token_type": "bearer",
  "refresh_token": "Ggf2816C5ANa6XVplzO8vwE6IRIXtjvE",
  "expires_in": 3599,
  "scope": "meeting:write user:read recording:write webinar:write"
}

Refresh Access Token

The original access token expires in 60 minutes. If you call a Zoom API with an expired access token, you will receive an invalid 400 or 401 error. If you need to make additional API calls after the initial access token expires, you will need to refresh your access token. You can do this by setting the value of grant_type to refresh_token and using the refresh_token parameter with the refresh_token string instead of code.

Sample cURL Request for Refresh Token
curl -X POST -H "Content-Type:application/x-www-form-urlencoded" \
--user client_id:client_secret  \
--data 'grant_type=refresh_token&refresh_token={refresh_token}' \
https://zoom.us/oauth/token
Refresh Token Response Example
{
  "access_token": "eyJhbGciOiJIUzUxMiJ9",
  "token_type": "bearer",
  "refresh_token": "eyJhbGciOiJIUzUxMiJ9",
  "expires_in": 3599,
  "scope": "imchat:write"
}
Refresh Tokens

Refresh Tokens have a lifespan of 15 years. When you refresh an access token, you will also get a new refresh token that you need to use in your next refresh. Store the new refresh token safely for the next time when you try to refresh the tokens.

Example Node Refresh Token Request
function refresh_token(refreshToken, freshToken, zoomclientid, zoomclientsec, myappredirect) {

    const zoomtokenep = "https://zoom.us/oauth/token";

    var auth = "Basic " + new Buffer(zoomclientid + ':' +
        zoomclientsec).toString('base64');
    var url = zoomtokenep + '?grant_type=refresh_token&refresh_token='+ refreshToken + 
    '&redirect_uri=' + myappredirect;
    request.post({
        url: url,
        headers: {
            "Authorization": auth
        }
    }, function(error, response, body) {
        if (error) {
            console.log("Error when getting Zoom token = " + error);
            return;
        }
        body = JSON.parse(body);
        if (body.access_token) {
            console.log("Got new access and refresh tokens");
            accessToken = body.access_token;
            refreshToken = body.refresh_token;
            // Process and securely store these tokens
        } else {
            console.log("FATAL - could not refresh access token");
        }
        return;
    });
}

Revoke Access Token

In some scenarios where the user wishes to revoke your app’s access or when you need to revoke the access yourself, you will have to revoke the access tokens.
To do so, make a POST request to Zoom revoke endpoint as shown below:
POST https://zoom.us/oauth/revoke
The POST request must include the following parameters:

Header: Content-Type':'application/x-www-form-urlencoded’
Body: token=<TOKEN>

Provide your current access token that is valid and not expired. Provide your Client ID in the user field and the Client Secret in the pass field as the password as shown in the example below:

Example Node Revoke Access Token
var request = require('request');

var headers = {
    'Content-Type': 'application/x-www-form-urlencoded'
};

var dataString = 'token=04WRoU4vb9cK1l8Ne8okytrJSvsZx0J8';

var options = {
    url: 'https://zoom.us/oauth/revoke',
    method: 'POST',
    headers: headers,
    body: dataString,
    auth: {
        'user': 'Odet7ldYQjyagzLKzNomA',
        'pass': 'UeE0e7LZopJRFityw1h3b7dJFz29IeY7'
    }
};

function callback(error, response, body) {
    if (!error && response.statusCode == 200) {
        console.log(body);
    }
}

request(options, callback);

You have now successfully learned how to authenticate your app with Zoom on behalf of your user! On the next page, you can see a walkthrough guide of the same.