Zoom API JWT authentication with C#

April 18, 2020

This is a quick guide on using the Zoom API JWT authentication with C#. I found Zoom’s docs to be quite lacking, and had to experiment with this a bit to get it to work.

When to use JWT

Zoom has two methods of authenticating: OAuth and JWT - JSON Web Token. They recommend using JWT for server-server API calls. So if you want the user to perform an operation on his own account from his own client, you should use user operations with OAuth. If, on the other hand, you want your server to open a Zoom meeting and wait for users to enter, and record the meeting on the server, there is no “Zoom client” involved in these operations, therefore you should use JWT authentication.

What is JWT

According to jwt.io:

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

What does that actually mean in practice?

  1. You as a client will use your API key and secret, and other parameters like the expiration time of the token, to generate a signed (hashed) token which you’ll send to the server (this is more secure than just sending the API key and secret directly to API endpoints). This step is performed on the client, using one of the JWT client libraries.
  2. The server will use your API secret to decode your JWT and respond with another token, which can be used to perform API calls, until it expires. It’s recommended to give a short expiration time span, like 30 seconds or so.
  3. You call the API endpoint you need with the token you received.

Generating a JWT in C

First you’ll need to make a Zoom JWT app and get your API key and secret.

We’ll use Microsoft’s System.IdentityModel.Tokens.Jwt nuget package to generate the JWT. Open Nuget Package Manager, and add System.IdentityModel.Tokens.Jwt by Microsoft.

Now add this piece of code to create your JWT token:

var tokenHandler = new System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler();
var now = DateTime.UtcNow;
var apiSecret = "<your API secret here>";
byte[] symmetricKey = Encoding.ASCII.GetBytes(apiSecret);

var tokenDescriptor = new SecurityTokenDescriptor
    Issuer = "<your API key here>",
    Expires = now.AddSeconds(30),
    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(symmetricKey), SecurityAlgorithms.HmacSha256),
var token = tokenHandler.CreateToken(tokenDescriptor);

var tokenString = tokenHandler.WriteToken(token);

Important things to note here:

  • The symmetricKey is what’s used to sign the JWT. This should be ASCII encoded, or else Zoom will reject it (this seems to be undocumented)
  • The Issuer field is your Zoom API key.
  • The Expires field can be set to any future date, but is recommended to be short-lived.
  • Only the SecurityAlgorithms.HmacSha256 hashing algorithm is supported by Zoom.

Now you have your JWT in tokenString.

Debugging the token

To ensure that you have the correct token, you can use the JWT debugger Paste your JWT, and enter your secret in the secret field. You should see the headers including the HS256 algorithm and the JWT token type:

  "alg": "HS256",
  "typ": "JWT"

And the payload including the exp expiry time in unix milliseconds, and iss (issuer) with your API key:

  "nbf": 1587197901,
  "exp": 1587197931,
  "iat": 1587197901,
  "iss": "<your API key here>"


Calling the API

Now that you have the token from the server, you can use it to make API calls. Just concatenate the token to the Bearer prefix and put it in the authorization HTTP header (I’m using RestShart here):

var client = new RestClient("https://api.zoom.us/v2/users?status=active&page_size=30&page_number=1");
var request = new RestRequest(Method.GET);
request.AddHeader("content-type", "application/json");
request.AddHeader("authorization", String.Format("Bearer {0}", tokenString));

IRestResponse response = client.Execute(request);

And you should get all the account’s users. Enjoy :)

Written by@Jonathan Perry
Fullstack dev - I like making products fast