Converted from JWT to OAuth but Can't Disable Old JWT App

We are in the process of migrating our code from JWT to oAuth. We currently have an application that, on the server side, schedules a meeting in the future. When it is time for a user to join the meeting, the user visits our site where, on the web site (in the browser) we use the Zoom Web SDK (currently on version 2.12.0) to ask the server for the credentials in order to connect to Zoom. These credentials are generated on our server and include a “signature” as required by the Zoom Web SDK (see documentation at Meeting SDK - web - client view - Meetings ). Right now this does work, however it is working with JWT and in an odd way.

On the server side, we are using the Classroom Door OAuth (Server-to-Server OAuth) app to create and manage meetings. This works as expected.

Also on the server side, we are generating a signature and providing the browser UI with credentials to connect to Zoom using our SDK App (Meeting SDK).

Here is the code we use to generate the signature on the server side:

  async getSignature(meetingNumber: number, role: MeetingRole) {
    const clientId = env.Zoom.sdkClientId;
    const clientSecret = env.Zoom.sdkClientSecret;

    const iat = Math.round(new Date().getTime() / 1000) - 30;
    const exp = iat + 60 * 60 * 2

    const oHeader = { alg: 'HS256', typ: 'JWT' }

    const oPayload = {
      sdkKey: clientId,
      mn: meetingNumber,
      role: role,
      iat: iat,
      exp: exp,
      appKey: clientId,
      tokenExp: iat + 60 * 60 * 2

    const sHeader = JSON.stringify(oHeader)
    const sPayload = JSON.stringify(oPayload)
    const signature = KJUR.jws.JWS.sign('HS256', sHeader, sPayload, clientSecret);

    console.log("Obtained signature", clientId, clientSecret, signature);

    return signature;

NOTE: Our current code references a new updated Server-to-Server OAuth App (server side) and a new updated Meeting SDK (client side) and the above works fine. However, if I deactivate our old Meeting SDK (which is out of date and uses JWT) or our JWT App, which is NOT referenced anywhere in our code anymore, we get an error when trying to connect: “Signature is invalid”.

My main concern here is that our code is NOT referencing these old JWT based Apps anywhere yet if I deactivate either of them, our zoom sessions will not connect. This is baffling me.

My second concern is the reference to ‘JWT’ above when generating the signature, will this cease to work when JWT support is removed on Sept 8?

I attempted to change the signature generation with the code example at ZoomMtg - Documentation which looks like this for us:

  async getSignature(meetingNumber: number, role: MeetingRole) {
    const clientId = env.Zoom.sdkClientId;
    const clientSecret = env.Zoom.sdkClientSecret;

    let signature = '';
    // Prevent time sync issue between client signature generation and zoom
    const ts = new Date().getTime() - 30000;
    try {
      console.log("Building signature", jsBase64, hmacSHA256, encBase64);
      const msg = jsBase64.encode(clientId + meetingNumber + ts + role);
      const hash = hmacSHA256(msg, clientSecret);
      signature = jsBase64.encodeURI(`${clientId}.${meetingNumber}.${ts}.${role}.${encBase64.stringify(hash)}`);
      console.log("Signature generated", signature);
    } catch (e) {
      console.log('Error getting signature: ', e);
    return signature;

However this new code does NOT work no matter what is enabled in our Zoom apps, it keeps giving us the error “Signature is invalid”.

I have tried following the Zoom documentation but am stuck, the code samples do not work. I know we need to get off the JWT code but nothing I do seems to work.

Any thoughts on why deactivating the old JWT apps is breaking our ability to start a Zoom session?

Here is a screen shot of our apps:

Hi @theclassroomdoor
Thanks for reaching out to us, I am happy to help here.
It looks like you are using the server to server oauth client id and secret to generate the signature.
you should be generating the signature using the client id and secret from your meeting SDK app

Here is a link to our sample app:

If you look into this file, you will see the function to generate Signature and it uses cliend ID and secret from the meeting sdk app

Thanks. I think we got it sorted out. What is confusing is that we are notified that JWT is going away but this code references JWT. It appears the JWT App is going away but we still can use JWT in the signature generation. Because the change could suddenly cause our app to cease functioning in production I was concerned.

I would also mention that we still can not deactivate the old Meeting SDK. We created a new Meeting SDK and switched our code over to that but when we deactivate the old one it breaks the signature. We have left it active for now but at some point this is likely to cause problems.

Hi @theclassroomdoor
Thanks for reaching outback
So the code snippet I shared references the creation of a JWT token using the SDK credentials.
What we are deprecating is the JWT app type that is available in the Marketplace.
Does that clarify the issue a little bit more?

Yea, I finally had figured that out.

Still no idea why I can’t deactivate the no longer used Meeting SDK app. We are not using it anywhere but if I deactivate it the signature starts coming up as invalid. We will leave it alone for now and hope it doesn’t suddenly stop working on us.

Right @theclassroomdoor
please let me know if you need any extra help with this