API Authentication Frameworks

August 18, 2017

As we move our APIs to version 2 and launch an app marketplace, we looked at some robust options for authentication and authorization. Our current model of account based API authentication using an API key pair (API key and API secret that gets generated and assigned for every Zoom account) has some inherent issues. Let's take a deeper look at our current model and what we are moving towards.

Authentication using API keys

This is one of the simple forms of authenticating the APIs. The platform generates an API key pair for your account and you will have few options to pass it - pass it as a query parameter in the URL or pass the key in a HTTP Authorization header or pass it in the body or use a custom header. The standard recommends using a Authorization header which is a preferred approach.

Since launching our platform, we have chosen to use the query parameter for passing the kay pair for simplicity.  When we did some testing back then with the APIs of popular platforms, we found that about 40% of them using the query string, about 45% using the Authorization header and the rest of them using a custom header.

While the API key pair approach works well for internal enterprise apps, it has downsides when used by developers to write apps that can be distributed/used across all customers in the platform. Anyone who wants to use your app needs to get their API key pair and then configure that in your app. It also gives full account level (write and read) access to anyone who gets hold of them and can create a vulnerability. Also keep in mind there is a chance that the API key pair will be logged in http servers and/or intermediaries that the request is passing through that might be undesirable by security teams.

That brings us to the second approach.

Json Web Tokens (JWT)

JWT (pronounced “jot”) is an IETF standard.  JWT is not a replacement to exposing API key pair but a companion that alleviates many of the pain points that we discussed here.  The length (in bytes) of the token depends on how much data is stored in the token and not defined in spec. A JWT consist of 3 parts separated by a dot.

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 isit 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. The claims can contain the user or application meta-data which brings a lot of flexibility.

Signature: The last part of the JWT is the signature. The signature is computed by encoding the header and claim and inserting a dot in between [base64UrlEncode(Header) + “.” +base64UrlEncode(Claim)].

To summarize

  • Create a header object in JSON and encode it with base64
  • Create a claim object in JSON and encode it with base64
  • 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

Zoom JWT Token Format

Our V2 API framework will use JWT.   You can get a JWT token either on your developer account (note: do not use the jwt from the developer account in your production code - each jwt has an expiry time that needs to set by the app for security reasons and our jwt in the playground expires in about 10 mins) or compute the token in your application as follows:

Header

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

Claims

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. If this token expires, your application needs to regenerate the JWT (just update the timestamp and generate a new token) and send it over again in your next API call. We recommend that your web app has the logic to set the token to expire every 30 days and then regenerate it.

The iss claim identifies the issuer. You need to put the API key here so that we can identify your zoom account.

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

Signature

The logic 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 us to use a different algorithm, we will support HMAC SHA-256. Our backend authenticator on the platform will validate your zoom account and signature. If they are valid, it will allow the access to the REST endpoints. We will be expanding the claims in the near feature to include more granular scopes.

Finally, JWT should be specified in the HTTP Authorization header.

Authorization: Bearer <jwt token>

Since JWT is just a token and not a protocol, there are no built-in options to refresh the token other than updating the token in an API request.

oAuth 2.0

oAuth  provides a framework for third party apps to access end user data on a platform.  When end users or admin uses a third party app that needs access to the account or user data, the app initiates the oAuth handshake with the platform. As part of the handshake, the user will be shown an authorization alert that explains what the app is trying to access and whether the user or the account owner is willing to authorize that access.  When the user gives the authorization, the platform will pass an access token to the app that should be used for subsequent API calls. The standard does not specify the format of the token and so its implementation dependent.  The access token is passed in the Authorization header. We can use JWT as an access token with oAuth to combine the power of both.  We have recently added oAuth service to our platform (not released yet) and we will cover that in detail in our next blog soon.

Thiya Ramalingam
Thiya heads the platforms, integrations, product partnerships and private cloud engineering @ Zoom