Need help with Zoom API from Meeting SDK - Always get "Host requires authentication"

OK, the Zoom documentation is VERY frustrating. It’s often contradictive to itself, and I find myself going down rabbit holes with 20 tabs open and nothing actually working.
I am working on an existing Qt (c++) app, trying to add in the ability for our user to join an existing Zoom meeting. Using Windows Meetig SDK v5.11.4.7235. I want the app to join the meeting, not a Zoom user, which it’s my understanding I can do (join with just a display name).
From what I understand this takes:

  1. Initialize the SDK
  2. Authenticate the SDK via JWT
  3. Initialize meeting service
  4. Join a meeting “without login”

I have succeeded on steps 1-3, but 4 has been excruciating trying to find the correct docs or forum answers.

This is the code I have, based on docs, to join the meeting:

// Join meeting for API user with JoinParam object
ZOOM_SDK_NAMESPACE::JoinParam joinMeetingParam;
// Provide meeting credentials for API user using JoinParam4WithoutLogin
ZOOM_SDK_NAMESPACE::JoinParam4WithoutLogin joinMeetingWithoutLoginParam;

joinMeetingParam.userType = ZOOM_SDK_NAMESPACE::SDK_UT_WITHOUT_LOGIN;

// If there is a ZAK token for this user provide it here, otherwise use JoinParam4NormalUser instead
joinMeetingWithoutLoginParam.userZAK = L"<zak>";
joinMeetingWithoutLoginParam.meetingNumber = 123456;
joinMeetingWithoutLoginParam.psw = L"<psw>";
joinMeetingWithoutLoginParam.userName = L"<MY users name>";

joinMeetingParam.param.withoutloginuserJoin = joinMeetingWithoutLoginParam;

ZOOM_SDK_NAMESPACE::SDKError joinMeetingCallReturnValue(ZOOM_SDK_NAMESPACE::SDKERR_UNKNOWN);
joinMeetingCallReturnValue = meetingService->Join(joinMeetingParam);
if (joinMeetingCallReturnValue == ZOOM_SDK_NAMESPACE::SDKError::SDKERR_SUCCESS)
{
    qDebug() << "Zoom should be in meeting!";
    // Join meeting call succeeded, listen for join meeting result using the onMeetingStatusChanged callback
} else {
    qDebug() << joinMeetingCallReturnValue;
}

Without a ZAK, I just get back joinMeetingCallReturnValue of 3 which is SDKERR_INVALID_PARAMETER

So, the frustrating part. I am trying to get my developer ZAK which accoording to various posts (I could link to the 50 pages of doc and posts I’ve been through that didn’t answer or contradicted others but that would be a mess) I can use to join a meeting without login, and I can obtain using keyword “me” in the api call, or using my dev email.

These are the last 2 requests I attempted.
If I try to get the ZAK directly (which some docs say I can)

QUrl reqUrl("https://api.zoom.us/v2/users/me/zak");

    reqUrl.setPath(reqUrl.path());

    QNetworkRequest req;
    reqUrl.setUrl(QUrl::fromPercentEncoding(reqUrl.toEncoded()));
    req.setUrl(reqUrl);

    QString concatenated = "<clientkey>:<clientsecret>";
    QByteArray header = concatenated.toLocal8Bit().toBase64();
    QString headerData = "Basic "+header;
    req.setRawHeader("Authorization", headerData.toLocal8Bit());

    QNetworkReply* reply = m_nam.get(req);
    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkError(QNetworkReply::NetworkError)));
    if (reply != NULL)
    {
        QNetworkReply::NetworkError error = reply->error();
        if (error != QNetworkReply::NoError)
        {
            qDebug() << "Zoom API GET failed";
        } else {
            qDebug() << "Reply succeeded, attempt being made to GET...");
        }
        //reply->deleteLater();
    }
    else {
        qDebug() << "Zoom API GET failed. No response received.");
    }

Which I’ve also tried with “Bearer: ” instead of the Basic auth above, I always get to my NetworkError slot with “Host requires authentication”

So I figured maybe I can try the OAuth from Client method:

QUrl reqUrl("https://zoom.us/oauth/token?grant_type=client_credentials");

    reqUrl.setPath(reqUrl.path());

    QNetworkRequest req;
    reqUrl.setUrl(QUrl::fromPercentEncoding(reqUrl.toEncoded()));
    req.setUrl(reqUrl);

    QString concatenated = "<clientkey>:<clientsecret>";
    QByteArray header = concatenated.toLocal8Bit().toBase64();
    QString headerData = "Basic "+header;
    req.setRawHeader("Authorization", headerData.toLocal8Bit());
    req.setRawHeader("Content-Type","application/json");

    QNetworkReply* reply = m_nam.post(req,"");
    if (reply != NULL)
    {
        QNetworkReply::NetworkError error = reply->error();
        if (error != QNetworkReply::NoError)
        {
            qDebug() << "Zoom API POST failed";
        }
        //reply->deleteLater();
    }
    else {
        qDebug() <<  "Zoom API POST failed. No response received.");
    }

Then it appears to go through but I back Invalid response, no result object.
I’ve probably tried at least a dozen other variations based on docs/posts and nothing is working to get the ZAK. And what I don’t get is why if I’m using an SDK, which is already authenticated, do I have to even do separate API calls like this? The SDK should have c++ calls/objects to get this information at this stage in the code.

Hi @wes.krasko ,

For your scenario, here’s some tips based on your description above.

If you are trying to join a meeting, try to use JoinParam4NormalUser instead. Windows SDK functions

If you are trying to start a meeting (which is typically what a host does), then you will need a ZAK token of the host.

Now let’s consider if you are trying to start a meeting, you will need a ZAK token. Here’s how we can get a ZAK token. Let me put in the high level steps, we can dive into selected ones based on your response. Lets assume we have a user with an email user@gmail.com

1. Using Zoom API with JWT App Type (Deprecating in Jun 2023)
a. create a JWT App Type on marketplace.zoom.us
b. use the JWT Token from marketplace.zoom.us to make a HTTP GET Call to https://api.zoom.us/v2/users/user@gmail.com/token?type=zak&ttl=7200
Header will need 'authorization': bearer <JWT Token>
This HTTP GET will return a zak token
c. use the zak token in your Windows Meeting SDK app to start meeting as user@gmail.com

2. Using Zoom API with Server to Server OAuth App Type (Replacement for JWT App Type)
a. create a Server to Server OAuth App Type
b. You will need 3 parameters, namely accountId, clientKey and clientsecret from marketplace.zoom.us to make a HTTP POST call.
Prepare the authorization token by doing a base64 encode to <clientkey>:<clientsecret>
c. Make a HTTP POST Call to
https://zoom.us/oauth/token?grant_type=account_credentials&account_id=<accountId>
Header will need 'Authorization': Basic {based64encoded <clientkey>:<clientsecret>}
d. Successful call in step c will return an access token. Use this access token to
make a HTTP GET call to https://api.zoom.us/v2/users/user@gmail.com/token?type=zak&ttl=7200
Header will need 'authorization': bearer <access token>
This will return a zak token
e. use the zak token in your Windows Meeting SDK app to start meeting as user@gmail.com

3. Using Zoom API with PKCE OAuth
a. You will use your existing SDK App on marketplace.zoom.us
b. You will be need 2 parameters, the Client ID and Client Secret. Do not confuse this with SDK Key and SDK Secret.
c. Authenticate user using PKCE flow
d. Successful call in step c will return an access token. Use this access token to
make a HTTP GET call to https://api.zoom.us/v2/users/me/token?type=zak&ttl=7200
Header will need 'authorization': bearer <access token>
This will return a zak token
e. use the zak token in your Windows Meeting SDK app to start meeting as user@gmail.com

I’ll back up a bit. I am trying to join a meeting only, but WITHOUT a user logging in (non-login user), so as the app/devloper.
What we have is an app with a server side controller. When our app gets a message from the controller, it will contain a meeting id, pass, etc to join. We want our app to join that meeting without any user input, meaning they shouldn’t have to login, go to a web page, etc. The app just joins it with a display name which it’s my understanding we can do.
The docs indicate that this requires using the other method of joining a meeting, using the zak, obtained from my devloper account. Then again, many other doc pages and posts contradict that.
In any case, I have tried to join without login using JoinParam4NormalUser and it does not work, I just keep getting back SDKERR_INVALID_PARAMETER when trying to join. I will try again.

This is also where posts/docs just make things more confusing.

  1. Why would you need to create a separate JWT App to use an existing app? I need to apps to authenticate 1?! Also, somewhere in a doc page it said that app type was being dropped/deprecated so why would I use it?

  2. Ok, this might be my only solution but requires a different team, I’ll look into it.

  3. That’s the last thing I was trying to do and as I mentioned above, I get nothing back. No token, empty response.

And her is how I’m trying to join the other way you mentioned, based on docs. This as I mentioned gives back SDKERR_INVALID_PARAMETER (3 in my debug output) no matter what I do. This is a meeting I created with just myself in it from another computer, then copied the invite info. I tried both the pwd in the url and the “Pass code”, both same result.

// Join meeting for end user with JoinParam object
            ZOOM_SDK_NAMESPACE::JoinParam joinMeetingParam;
            // Provide meeting credentials for end user using JoinParam4NormalUser
            ZOOM_SDK_NAMESPACE::JoinParam4NormalUser joinMeetingForNormalUserLoginParam;

            joinMeetingParam.userType = ZOOM_SDK_NAMESPACE::SDK_UT_NORMALUSER;

            joinMeetingForNormalUserLoginParam.meetingNumber = 75010625938;
            joinMeetingForNormalUserLoginParam.psw = L"rqrcn5"; //Or, pwd=DTfNt_c93uV6H6iB6_a9hWwPk-GyLG.1 ?
            joinMeetingForNormalUserLoginParam.userName = L"Test User";

            joinMeetingParam.param.normaluserJoin = joinMeetingForNormalUserLoginParam;

            ZOOM_SDK_NAMESPACE::SDKError joinMeetingCallReturnValue(ZOOM_SDK_NAMESPACE::SDKERR_UNKNOWN);
            joinMeetingCallReturnValue = meetingService->Join(joinMeetingParam);
            if (joinMeetingCallReturnValue == ZOOM_SDK_NAMESPACE::SDKError::SDKERR_SUCCESS)
            {
                qDebug() << "We joined a meeting!";
                // Join meeting call succeeded, listen for join meeting result using the onMeetingStatusChanged callback
            } else {
                qDebug() << "WTF";
                qDebug() << joinMeetingCallReturnValue;
            }

Could you share with me which part of the docs might be confusing? I’ll take the feedback and work to improve it.

Thank you for the further elaboration, I understand your scenario better now

If you are trying to join a meeting, you do not need a ZAK token.
If you are trying to start a meeting, then you will need a ZAK token.

For the JWT token generation, I wanted to be as exhaustive as possible, hence I’ve shared all 3 possible methods of using JWT App, Server to Server OAuth App, and PKCE OAuth.

Nonetheless, if you are just joining a meeting, you do not need a ZAK token.

To join a meeting there are 3 parameters which are needed. I’ve checked our sample c++ code, and it seems your original code was using the correct param (JoinParam4WithoutLogin). Let’s compare notes, while my code snippet might not be exactly the same as yours, it should be largely similar.

  1. Meeting Number
  2. Password (not passcode)
  3. User Name
ZOOM_SDK_NAMESPACE::tagJoinParam joinParam;
	joinParam.userType = ZOOM_SDK_NAMESPACE::SDK_UT_WITHOUT_LOGIN;
       //need to initialize withoutloginParam
	ZOOM_SDK_NAMESPACE::JoinParam4WithoutLogin& withoutloginParam = joinParam.param.withoutloginuserJoin;
      
        //set the 3 parameters
	withoutloginParam.meetingNumber = 98942132113;
	withoutloginParam.userName = L"chunsiong";
	withoutloginParam.psw = L"W294M053nNTdUa3VfS3pW22Z2Zno2dzs9";

//set the success message, and attempt to join meeting, and compare success message
	ZOOM_SDK_NAMESPACE::SDKError err = ZOOM_SDK_NAMESPACE::SDKERR_SUCCESS;
	err = m_withoutLoginJoinMeetingWorkFlow.JoinMeeting(joinParam); //this is helper class which calls meetingService->Join
	if (ZOOM_SDK_NAMESPACE::SDKERR_SUCCESS == err)
	{
		m_bInMeeting = true;
	}

a brief question: does the distinction for ZAK token also apply to meetings with the option

Clipboard01

Jürgen

I’m so excited it works! Thank you!! I don’t know why, I compared your code with my last attempts to use SDK_UT_WITHOUT_LOGIN and it’s the same (at least when I commented out the line to add the ZAK) and it never worked until now, but I’ll take it!
There were so many spots in the docs it’s hard to list, but it was mostly contradictions, 2 different pages of SDK saying to do the same thing 2 different ways. If I had to generalize, it seems the iOS and Android are more complete or up to date and maybe the issue is with the desktop docs not being updated. I found a lot of what I couldn’t figure out by translating non-Windows docs rather than using Windows docs directly.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.