Upgrading to OAuth in C++ Windows SDK Application - starting the demo application

Hi
A couple of years ago I wrote a C++ Windows application with JWT style login using the Zoom SDK which has proved very successful and indeed is now crucial to our company. But is has stopped working, I think because of the SDK upgrade requirements. So I am trying to upgrade it to the latest version of the SDK, v 5.11.4.7235, and to use OAuth authorisation.
I worked out how to do it last time by reverse engineering the demo application that comes with the SDK. But this time I cannot even get the demo app to start. It compiles fine, but it asks you to provide an ‘sdk jwt token’ which I thought was the old way of doing things which is about to be made redundant.
So my initial questions are:

Is the demo app an OAuth app at all?
If it isn’t, is there an C++ Windows SDK demo app that uses OAuth available?
If it is, what is a ‘sdk jwt token’ and how does it relate to OAuth?

In parallel I have successfully followed the OAuth documentation and developed fresh C++ code that happily obtains and renews Access Tokens from the Zoom server - all I have to do now is work out how to use the things! I have tried using the lovely new authorisation codes and access tokens as the ‘sdk jwt token’ in the demo app - no luck - the authorisation fails. Similarly I have tried every every code/token I can retrieve from the app market place for my account and application - no luck.

Any help/pointers would be appreciated. If I could get the demo app working, I can bang my head against it until I work out and/or copy what it does.

Thanks

Mike

Okay - so I have now worked out that the example app is a JWT type app, not an OAUTH app.

So now I can go to my freshly created active JWT app, copy the JWT token from there, paste it into the user interface for the demo app and watch it fail in exactly the same way! I will try this a few more times.

Given that we are not supposed to be creating JWT apps, as they are about to be retired, and I have already done the work to get a valid OAuth access token, my questions then become:

1 What do I do with the OAuth access token in a C++ SDK App?
2 is there an example C++ SDK OAuth app we can download and copy?

Thanks

Mike

Hi Mike,

We don’t have a C++ example for the SDK, but you should read about the Server-to-Server OAuth to get an understanding of the architecture. This would require making HTTP calls from your C++ app to authenticate and make requests from the Zoom API. You can do this using any number of http clients or using the standard lib

Hi Shariq

Thanks for the response, although I admit it leaves no less confused.

The application I wrote is a replacement for the standard Zoom windows client that allows our staff to view multiple shared screens simultaneously which is essential to their work. The code makes frequent use of calls such as CreateShareRender to add new users to the client when they join a meeting. I was surprised, therefore, that you suggest I look at the Server to Server architecture. Surely our application is a client rather than another server.

However, I don’t pretend I understand the ways you classify apps now. If I follow the Server to Server architecture, how do I access calls to functions such as CreateShareRende?. Is there HTTP level endpoint that offers such low-level functionality? If there is, can you point me to the spec as I haven’t managed to find it yet.

If the Server to Server route is the correct one to follow, can you also please explain what happens when the access token expires one hour and five minutes into a meeting? Will our app stop working?

Many thanks

Mike

@mikehcam,

You can get started with Windows C++ SDK with the following steps:

  1. The Zoom Meeting SDKs use an SDK Key and Secret to generate an SDK JWT for authorized use of the SDK. To get an SDK Key and Secret, you will need to build an SDK app in Zoom Marketplace. Be sure to save SDK Key and Secret because you need them later on to generate SDK JWT.

Create an SDK app:

  1. If you haven’t already, you will need to download the window SDK from the Marketplace:

Download the window SDK

  1. Launch Visual Studio, and locate the sdk_demo.vcproj file, and open it.

  2. Right-click on the project in the solution panel and changed the Configuration and Platform to Active Release and x64. (or “x86” if you are running the x86 version)

  1. Then, build the SDK. Once the demo application has been built, the first screen will ask you to enter Web Domain , the default domain is https://zoom.us :

image

  1. Then, you will need to authenticate the SDK with an encrypted SDK JSON Web Token (JWT) to start and join a Zoom meeting or webinar. Use the SDK Key and Secret credentials from Step 1 to generate the JWT SDK token , you can find the instruction here :

Generate the SDK JWT

The Header includes the specification of the signing algorithm and the type of token.

Header:

{
  "alg": "HS256",
  "typ": "JWT"
}

The payload of a JWT contains the claims of the token, or the pieces of information being passed about the user and any metadata required.

Payload:

{
  "appKey": SDK_KEY,
  "iat": 1646937553,
  "exp": 1646944753,
  "tokenExp": 1646944753
}

Example SDK JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZGtLZXkiOiJhYmMxMjMiLCJtbiI6IjEyMzQ1Njc4OSIsInJvbGUiOjAsImlhdCI6MTY0NjkzNzU1MywiZXhwIjoxNjQ2OTQ0NzUzLCJhcHBLZXkiOiJhYmMxMjMiLCJ0b2tlbkV4cCI6MTY0Njk0NDc1M30.UcWxbWY-y22wFarBBc9i3lGQuZAsuUpl8GRR8wUah2M

Enter SDK JWT token Window

The window where you will be asked to enter your SDK JWT token looks like this:

image

  1. To join a meeting navigate to the “Only Join” tab and provide the relevant meeting credentials.

Join a meeting

image

Hi

Thanks for that information. I am pleased to report that I have followed the guidance and my custom client can now connect again, and I can login. But the application is not working properly or in the manner it used to. So some more questions if I may.

By far the most important question is whether there is any limit in the Zoom server as to the maximum number of screen shares that can be rendered simultaneously in a custom sdk client. The purpose of my client is to allow our trainers to watch what the trainees are doing on their remote PC’s whilst training software over Zoom. The old version used to be able to render 10 or so remote screen shares simultaneously and it worked really well. But the updated client can only render two at a time.

Some more information. I am testing using four remote Zoom users/sessions on separate PCs all sharing a different local Windows application on their respective machines. Two of the remote shared applications render perfectly in my client but the other two display as black rectangles. I don’t think it’s a problem with the remote Zoom sessions as I can switch between the individual remote shares in the standard Zoom client, and they all display perfectly. Similarly, I don’t think it’s an issue in my client as the remote sessions can all share perfectly within it, but only two at a time. I can control which two work, by the order in which I start the remote sharing. The first pair to start sharing display perfectly, but the second pair appear to the client to be working fine but actually display as black rectangles. I can pick any two from the four, but only two. I don’t think it is a problem with the software as I never get any error messages, the renderers all appear to be created and running ok, any two of the four connections can work (but only in pairs), and it’s the same code that used to be able to render any number of shares. I have tried running the client on two different PC’s and the behaviour was identical on both (two work, two don’t).

So the obvious question, please, is whether you have introduced a limit in your server as to the maximum number of screen/window shares that can be rendered simultaneously in an custom sdk client. If you have, is there any way of raising it for an individual application? A limit of two is a disaster for the application and would be a major problem for us.

And I have three less important questions that your documentation/web site doesn’t currently answer.

To authorize my client, I have to create a JWT token using the SDK key and secret and send it to the server, and all is well. The type of my client is ‘ Meeting SDK’ although this first step requires the use of a JWT Token. Can you please confirm that despite the use of the token, my application is not a ‘JWT App’ that you will stop supporting in June next year, but a Meeting SDK client that will be okay beyond that date.

The sdk authorization I successfully receive lasts for 1 hour. Towards the end of this period I receive an ‘onZoomAuthIdentityExpired’ event. If I respond instantly by generating a new JWT token and requesting authorisation again, the re-authorisation fails. But if I try again a second later it works. Is this just a matter of your server not being ready because my new request is too quick? Is there a better way to do this?

Similarly, I can now use the OAUTH mechanism to login to Zoom. The Zoom access token I receive also lasts one hour. But in this case, my application never receives any corresponding ‘onZoomIdentityExpired’ event, and so I am using a timer to trigger refreshing the access token. This appears to be working fine, but again, is there a better way to do this?

Many thanks

Mike

I have another question which I may as well ask.

I am trying to use the onSharingContentStartRecving event in the ICustomizedShareRenderEvent Class but I never receive these events. I do receive the onSharingSourceUserIDNotification events defined in the same class, but not the onSharingContentStartRecving event.

Does anyone know if onSharingContentStartRecving works in the Windows Meeting SDK?

Right

I think I have got as far as I can with this now and will switch to look for alternative solutions. But in case anyone else has the same issues, I thought I would list my conclusions after weeks of work.

1 The new OAUTH login mechanism is not intended for C++ programmers and is very tricky to get right. The main challenge is generating the JWT token. I managed it using the Microsoft HMACSHA256 class but it is tricky. It’s obviously too hard for whoever at Zoom wrote the original C++ Windows SDK example, and so they haven’t bothered to update it.

2 Once you have all of the required Zoom tokens, the documentation doesn’t bother telling you what you are supposed to do with them in a C++ program. That may be because the C++ Windows SDK doesn’t have any way of using them – who knows without any documentation or feedback from the Zoom team.

3 C++ clients are now limited to rendering no more than two C++ screen shares simultaneously. There did not used to be a limit, but there is now! I have no idea whether this is intended, or another bug. But it is a big blow, and so I hope it was deliberate.

4 The code that is supposed to generate onSharingContentStartRecving events doesn’t work!

5 The code that is supposed to generate onZoomIdentityExpired events doesn’t work!

6 The JWT token-based re-authorisation mechanism is flaky but works if you keep hammering with the same parameters.

7 This Dev Forum is a hopeless mechanism for supporting developers who are trying to use your tools and thereby promote your technology.

Time to start researching MS Teams, I think.

I’m sorry that your experience with Zoom has been less than stellar. I shared your concerns about the SDK with the engineering team and we will work to get some better documentation around the C++ SDK documentation.

Mike,

I don’t have much C++ experience, but I talked to some of the other engineers and this is what I found out. I’ll go by them point by point.

  1. The engineers suggest that you generate the JWT server side and not client side. They removed this from the sample app because they don’t want to encourage people to do this.

  2. Like I said in the previous comment, we need some love on the C++ docs

  3. By default, only one people is allowed to share at a time, and there is a setting to check “Multiple participants can share simultaneously”. The engineers are going to double-check this though.

  4. From the engineers: “Based on the use case he mentioned above, I’m not sure why he decided to use ICustomizedShareRenderEvent rather than the events IMeetingShareCtrlEvent.”

  5. From the engineers: “The callback onZoomIdentitiyExpired works for case when the logged-in users identity is expired, so it works For SSO login. OAuth process gets a ZAK that allows the user to join a meeting with credentials, but that is not logged in so this event is not triggered.”

Hi Shariq
Thanks for the response. I apologise if I sounded frustrated in my previous post but I admit I am.
Let me start by explaining what version 1 of this app did.

  1. The trainer started the app – it connected to your server.
  2. The trainer entered the joining details for a meeting, which was actually one of our training courses, and the app joined the meeting as a participant.
  3. The app then displayed a grid of cells, with each trainee on the course being allotted one cell in the grid.
  4. As each trainee joined the course/meeting, they shared their copy of the software application we are training them on.
  5. The app detected each new trainee’s share and displayed it in the trainee’s cell in the grid. It did this by calling the CreateShareRender method in your ICustomizedUIMgr class, to create a separate renderer for each trainee/participant.
    That’s it essentially. There were a few more bells and whistles but they were icing on the cake.
    The application allowed the trainer to watch over what the trainee’s were doing and to help them individually as they progressed through the course. Because your architecture allows multiple participants to share simultaneously, version 1 could show the screens of 10 or 12 trainees simultaneously and it worked really well! We sang your praises loud and clear.
    Now let me tell you what my current application does.
  6. The trainer starts the app – it successfully connects to your server and authorises (most of the time).
  7. The trainer enters the joining details for a meeting and the app joins the meeting as a participant.
  8. The app then displayed a grid of cells, with each trainee on the course being allotted one cell in the grid.
  9. As each trainee joined the course/meeting, they share their copy of the software application we are training them on.
  10. The app detects the first two trainee’s new shares and displays them using share renderers created using the CreateShareRender method as before.
  11. As the third, fourth etc trainees join the course, it starts to share these two renderers amongst all the trainees by switching them using the SetUserID and Resize methods in your ICustomizedShareRender class.
    If I follow the model I used for V1 and create a separate Zoom share renderer for each participant, only the first two I create work. The third, fourth, fifth etc renderers I create just display a solid black rectangle rather than the user’s screen. Which two renderers work depends on the order the trainees join and share. Which is why I think the limit on the number that work is in your server, not my code.
    The switching I am currently using to share the renderers amongst the trainees causes a lot of flicker on the screen which may mean it’s just too distracting for the trainers. We are currently evaluating this.
    I hope that explanation will allow you to understand my responses to your responses.
  12. The engineers suggest that you generate the JWT server side and not client side. They removed this from the sample app because they don’t want to encourage people to do this.
    What server side? The app is a C++ Windows Client. There is no server side. If you can propose a better architecture, then I would be interested. But I have not found the necessary methods in any of the alternative SDKs.
  13. Like I said in the previous comment, we need some love on the C++ docs
    Yep – but thanks for acknowledging that.
  14. By default, only one people is allowed to share at a time, and there is a setting to check “Multiple participants can share simultaneously”. The engineers are going to double-check this though.
    I am not asking how many people can share at once. Lots can and that’s great. I am asking how many custom share renderers I can create simultaneously. It used to be lots (> 12 at least) – now it appears to be 2.
  15. From the engineers: “Based on the use case he mentioned above, I’m not sure why he decided to use ICustomizedShareRenderEvent rather than the events IMeetingShareCtrlEvent.”
    I use the ICustomizedShareRenderEvent’s to detect when a new participant starts or stops sharing. But when I am switching a renderer to a different participant (using SetUserID()), I would like to hide the renderer until the new content has come online. Because it looks very clunky if the trainer has to watch the renderer stop showing one trainee’s share, then go black, then start showing another trainee’s share. The ICustomizedShareRenderEvent onSharingContentStartRecving event would appear to be the ideal event to allow me to do this, But I am not sure of that because it doesn’t work. Of course I would rather not switch in this way at all – I would much rather just have 10 or 12 renderers all working at once which I used to be able to do.
  16. From the engineers: “The callback onZoomIdentitiyExpired works for case when the logged-in users identity is expired, so it works For SSO login. OAuth process gets a ZAK that allows the user to join a meeting with credentials, but that is not logged in so this event is not triggered.”
    Fair enough – makes sense. One of the subtleties you might like to mention in the documentation.
    At the moment I am struggling to try to control the custom renderer’s you use to display the shares. I would love to know how to capture a bitmap from one of them. And I would like to know how to hide them. I have worked out that you create child windows to host the renderers, and I am gradually working out how to control and access them through blind trial and error. This is not a productive way forward and hence my frustration.
    Thanks in advance for any help you can give!
    Mike

Just noticed two mistakes in my response,
The numbering has all merged together: paras 1 to 5 are correct, paras 6 to 10 should be numbered 1 to 5 again to allow comparison with the first five, and paras 11 to 15 should be 1 to 5 again to allow comparison with your previous response to me.
And my response in para 15 should read “I use the IMeetingShareCtrlEvent’s to detect when a new participant starts or stops sharing.”

I’ve been there myself. Things have changed and an upgrade that you thought was going to be fairly easy turns into a bigger headache than you originally thought. I’ll go to the engineers and see if I can get some more clarification on what you said about the custom share renderers. There might be some undocumented side effect going on.

As point 12 goes, we want you to generate the the JWT token on a separate server and then pass it over to the client. This would mean making an HTTP call to – let’s say a Python server that will generate the JWT token – and then using the returned value in the C++ client.

Hi Shariq
Any response from the engineers yet?
The main open question is whether there really is a limit on the number of custom share renderers that a Windows C++ client can have open simultaneously, and if there is a limit, is there any mechanism to increase the number?
If there is no way to increase it, then I would appreciate knowing if there is anyway of capturing the content of one of the renderers in a bitmap (other than capturing it directly from the screen) as that would make sharing the renderers between users much smoother.
Thanks
Mike

Mike,

Folks have been wrapped up with putting the finishing touches on Zoomtopia. Now that is done, I’ll re-engage the devs and see what they say. Thanks for your patience.

Hi Shariq
I’m still hoping your technical folks might deign to comment.
Ta
MIke

Guess its time to give up!
Very disappointing attitude from the technical folks. It should not take them 4 months to answer a very straight forward question.
Certainly puts us back in our place!

Hi! thanks for that information!

1 Like