Setting up Server-to-Server (S2S) OAuth to test Zoom APIs via Postman
For those who have been integrating and developing on Zoom Developer Platform, this shouldn’t not be new to you. But, for those who are reading this for the FIRST time, Zoom has a developer platform which allows you to build innovative integrations that deliver value for your customers with easy-to-implement solutions from Zoom.
With an open and secure platform, developers are able to leverage on APIs, SDK and many more to build apps for both public and private use, custom integration and new functionalities that enriches the Zoom experiences for end users.
Enough with the introduction and going straight into the main objective of this article.
Setting the context
At the most basic level, Zoom offers APIs as the primary entry point for developers to access the collection of resources from Zoom. As any new developers starting off with a new platform, the first step is to establish the access of APIs to understand the different services made available from the platform.
Similar to many platform providers, Zoom APIs are based on REST architecture and can be accessed via HTTPS at specified URLs. The access of APIs needs to be authenticated and Zoom supports JSON Web Tokens (JWT) and OAuth 2.0 for authentication.
With the recent announcement, JWT app type will be deprecated in June 2023 (You can read the announcement and FAQ here) and this will impact the following scenarios:
- Open API requests made with JWT authentication method
- Meeting Web SDK apps that have not migrated to SDK + OAuth app type
- Internal Server-to-server App build with JWT authentication
I can already think of the benefits using OAuth moving forward and you can read this link for your interests.
Moving away from JWT to OAuth 2.0 in Postman
I am sure that Postman is not foreign to you but it is an API platform for developers to design, build, test and iterate their APIs.
Like many other developers who have tested/developed on Zoom Developer Platform, Postman is a common tool to test Zoom APIs quickly. For those who are interested to test, you can download the API collections, which use the OpenAPI specification, and import into your workspaces. You can get started via this link.
With the change from JWT to OAuth, there are several steps you will need to perform before invoking your first API call using the new authentication method.
Create a Server-to-Server OAuth app
I will based on the assumption that the permissions for Server-to-Server OAuth has been enabled at the role level. You can follow the steps here to enable for your developers.
First, sign in to Zoom App Marketplace with your account credentials, hover to “Develop” dropdown list and click “Build App”.
Choose the Server-to-Server OAuth app type and click “Create”. Enter a name for your app and then click “Create”.
Once created, you will see the new created App type with the following sections.
App Credentials
It contains your App credentials — Account ID, Client ID and Client secret that are required to generate an access token to access Zoom APIs.
Information
You are required to add information about your app based on the following stated fields. As stated in the documentation, Name and Email address are required for activation.
Feature
If you need to use Zoom Webhooks for this app, please enable Event Subscriptions. I will not elaborate on this part as I won’t be touching on Webhooks for this exercise. You can refer to this link for more details.
Scopes
This is an important step as you will need to define the API endpoints or methods that this app is allowed to use to access specific resources.
The key difference between JWT and Server-to-Server OAuth is the ability to define the scope or simply — restricting the types of operations and data the app can access.
For the purpose of this exercise, let’s add 1 scope (User) for the app and click “Done”.
You are able to see the added scope(s) and you can provide a description for how the app uses the scope. For best practices, you should always add a description so that your team members will understand the scope purpose in relationship to your app/integration.
Once all the necessary details are provided and defined, you should see the following message when you reach “Activation”.
Click on “Activate your app” to activate and you should be able to start generate an access token.
If you did not provide the Name and Email address details under Information, you will not be able to activate the app and see the following error messages.
Setting Authorization method at Postman Collection
We switch gears now over to Postman. To save some time on explanation, I have downloaded the Zoom Meeting API collection and imported into my Postman app as shown below.
Click on Zoom Meeting API and the workspace will open up the collection details. You should see the “Authorization” tab, expand the “Type” dropdown list and select “OAuth 2.0”.
You should see the following view after selecting “OAuth 2.0”.
Configure New Token
Scroll down to “Configure New Token” section, under the “Configuration Options” tab and provide the following information.
- Token Name — Provide a name for the token. I have used the following name Access Token_{{$isoTimestamp}} where I’m using the global dynamic variable from Postman to add a suffix to the access token name when generated. This allows me to know the timestamp of the generated token.
- Grant Type — Select Client Credentials. Client Credentials is used in server-to-server authentication.
- Access Token URL — Provide the following URL https://zoom.us/oauth/token?grant_type=account_credentials&account_id={accountId} where accountId is the Account ID under the app created earlier.
- Client ID — Provide the Client ID under the app created earlier.
- Client Secret — Provide the Client Secret under the app created earlier.
- Scope — You can skip scope as you have already defined the scope under the app that it can access. Even if you add the required scope(s), Zoom does not append or overwrite the scope(s) that has been configured in the app.
- Client Authentication — Select “Send as Basic Auth header” where it will generate a Base64-encoded credentials with the Client ID and Client Secret.
Once completed, click “Get New Access Token” and you see the following dialog on the access token generation success.
Once the dialog closes, it will open up the “Manage Access Token” dialog and show you all the token(s) available in the collection. You should be able to see the details of the newly generated token.
The access token will have the following details:
- Access Token — the generated token which I have masked it.
- Token Type — Bearer
- Expire in — 3599. The value is in long and it has a time-to-live (TTL) value of 1 hour.
- Scope — It will state all the scope(s) which you have selected in the app settings earlier.
Click on “Use Token” and it will set this access token in the Current Token section as shown below.
The Header Prefix will be set as “Bearer” as this will be added to the Authorization Header before the access token when you are invoking an API.
Always click “Save” or Ctrl + S or Cmd + S whenever you make changes to the Collection. If not, the new changes will not be set in place when you are calling the APIs.
Testing Postman
Now, we are ready to test with a simple API call — List User API based on the scope which we have earlier defined.
Under the collection, you can open List User API from Zoom Meeting API > users > List user.
There are a few things you should check before invoking this API.
- Authorization — Click on the Authorization tab and the Type should be selected as “Inherit auth from parent”.
- Headers — Click on the Headers tab. If you observe that there is an indication for hidden headers, click to display the hidden headers. You should see the value for Authorization and it should be “Bearer <<access token>>”.
Once the above points have been validated, you can proceed to invoke the API (Please ensure that the parameters are correct). The response should be a status code 200 and the response body as shown below:
For the sake of testing, I am going to invoke another API which is not covered under the scope of the access token. I will test List Roles API which the required scope is role:read:admin. As expected, it returned a status code 400 with the error code 4700: “Invalid access token, does not contain scopes: [role:write:admin, role:read:admin].”
So this concludes how you can now configure S2S OAuth for Zoom Meetings APIs Collection in Postman.
Actually…
There is another approach that was shared by my colleague, Chun Siong on using Pre-request Script at the Collection level. The script will always be executed before every request in the collection.
Create an environment variable in Postman Collection
We first need to create an environment variable named my_access_token under the “Variable” tab.
The purpose of this variable is the ability to store the value of the generated access token from the pre-request script which we will elaborate later.
Create the Pre-request Script in Postman Collection
Next, click on the “Pre-request Script” tab and paste the following script.
Essentially, the code block above is the steps to request for an access token if you are calling manually. You will need to provide the following parameters as shown in the code block:
- Account ID in the URL string
- Base64-encoded string of your Client ID and Client Secret separated with colon (
:
). You can use any online base64 encoder to encode.
The successful response will be in the following format:
{“Access_token“: String,“Token_type”: “bearer”,“Expire_in”: long,“scope” : [String]}
We can then set the value of the access token from the response to the variable my_access_token.
Below is a screenshot of the pre-request script for this collection in my Postman app.
Set Authorization Method
Now, return to the “Authorization” tab and select “Bearer Token” for the Type. Under Token, you can reference the variable my_access_token using the following syntax double curly braces around the name {{my_access_token}}.
As mentioned previously, always click “Save” or Ctrl + S or Cmd + S whenever you make changes to the Collection. If not, the new changes will not be set in place when you are calling the APIs.
Comparing the approaches
You are all set to perform the same test as above. There are some differences between the two approaches.
Authorization value in the Headers
With the first method, you should see the access token value in the value. For the second method, you only see the variable reference instead.
Number of Tokens
With the first approach, you will always use the same token until it expires. Once expired, you can return to the collection level, configure a new token and set the new token. With the access token management, you can easily removed expired or all tokens from Postman.
With the second approach, it will result in many access token generated — Whenever you are making a request, the pre-request script will execute before every request in this collection. Hence, every single request will result in 1 access token generated. To show this behavior, I made 2 requests using List Users API and opened the postman console.
Essentially, this shows that the pre-request script has been executed twice before calling the API when I made the requests.
Conclusion
Well, this exercise has been fun knowing that there are many ways to get the same outcome depending on your preferences.
Now back to regular work and more cat photos.