API Security

As we are moving our developer platform APIs to v2, we have done a deep analysis of what worked and what needs to be enhanced. Among other things which I will cover in a different post, its apparent that we need to enhance the security framework around our APIs — simply passing a key pair in the headers or as query params are just not good enough. After looking at few options, we have settled in to use JWT (pronounced “jot”). I will provide an intro to JWT in context to Zoom V2 APIs and we will cover OAuth flows in a follow up post. Suffice to say, a lot of people gets these two mixed up — JWT provides a way to communicate claims whereas OAuth is a protocol and framework which might carry a JWT.

Before we deep dive, if you want to get a comprehensive understanding of JWT, refer to IETF spec RFC-7519. JWT is now an IETF standard. Another good source is jwt.io

JSON Web Tokens

The whole premise of JWT centers around something called “claims”. A claim is just a piece of information or statement about a subject. For instance, a claim would be to pass a timestamp so that the session can be expired in certain interval or pass a user name. This claim is encoded as a JSON object, digitally signed and sent between two parties. JWT is very compact (can be sent in as a query parameter or in the HTTP header) and self contained (payload contains all the info).

JWT parts

A JWT consist of 3 parts separated by a dot. The syntax is:

Header.Payload.Signature

Header — The header declares the type of the object and the encoding algorithms that is used. In the following example, the header defines that the encoded json is a JWT and it using HMAC SHA256 algorithm.

{
 “alg”: “HS256”,
 “typ”: “JWT”
 }

This object is then Base64Url encoded that result in an output string similar to “ yJhbGciOiJIUzI1NiIsInR5cCI6I”.

If you wonder what Base 64 encoding is — it converts a binary data into text so that the data is more reliably sent over the network. Base-64 encodes each set of 3 bytes into 4 bytes. The output is approx. 1.3 times bigger than the input and so it takes 1.3x the bandwidth. Why then use Base-64 ? Because the other options (such as Hex) increases the size of the output more than 1.3x and so takes more bandwidth to transfer the data).

Claims (or payload) — The second part of JWT defines the claims. RFC-7519 defines three types of claims — Registered, Public and Private. Instead of repeating the description here, check out the RFC. The claims can contain the user or application meta data which brings a lot of flexibility.

In our v2 APIs, we will be using the two registered claims — exp (expiration time) and iss (issuer).

The exp claim contains the expiration timestamp after which the Zoom platform will decline the API access. The iss claim identifies the issuer. In our case, you will put the API key here so that we can identify your zoom account.

{
 “exp”:1300819380,
 “iss”:”zoom_api_key”
 }

Signature: The last part of the JWT is the signature. The algorithm to compute the signature is:

out = base64UrlEncode(Header) + “.” +base64UrlEncode(Claim)

signature = HMACSHA256(out, zoom API secret)

Note that your application is signing this with your zoom account API secret. While the standard allows one to use a different algorithm, we will support HMAC SHA-256.

Unlike our current V1 APIs, we are not sending your account secret as a query parameter and if an attacker tampers the header or claims, the signature validation will fail in our platform and the request will be rejected.

In summary:

  • Create a header object in JSON and encode it with base64Url
  • Create a claim object in JSON and encode it with base64Url
  • Create the signature (sign it with your account secret)
  • Concatenate the above 3 parts with a dot

The result of the above will be a string like the following (note the two dots):

yJhbGciOiJIUzI1NiIsInR5cCI6I.eyJleHAiOjEzODY4OTkxMzEsImlzcyI6ImppcmE6MTU0ODk1OTUiLCJxc2giOiI4MDYzZmY.uKqU9dTB6gKwG6jQCuXYAiMNdfNRw98Hw_IWuA5MaMo

Transporting JWT

We will support the following two options for passing JWT.

  • Your app can add the token in the URL itself as a query param
https://api.zoom.us/v2/user/create?jwt=xxxx
  • Alternatively, pass it in the HTTP header
Authorization: JWT <jwt>

JWT encode libraries

While you can create these tokens manually in your code, save your time and use the libraries that is commonly available across different languages. Jwt.io has the list of libraries available with the install package names.

As always, feel free to reach us out if you have questions.