Requesting Assistance: meetingsdk-web-sample Integration Error (Laravel, "Signature is invalid")

Hi Folks,

I’m writing to request assistance with integrating the Zoom Meeting SDK into a Laravel application running on localhost. I’m using the sample code provided in the meetingsdk-web-sample repository on GitHub:
MeetingSDK

I’ve followed the instructions and updated the clientID and clientSecret credentials within the CDN directory code with those obtained from my Zoom Server-to-Server OAuth App. However, when attempting to join a meeting, I encounter a popup error stating:

Joining Meeting Timeout or Browser restriction

Signature is invalid.

I would greatly appreciate your support in resolving this integration issue. Please let me know if you require any additional information or have any questions.

Thank you for your time and assistance.

Best Regards,

Muhammad Shahid

Hi @shahid.cs96 , is this a legacy meeting SDK app type you are using or unified build flow? Either way, use the application credentials from within that app, not from a separate S2S app. See here for details.

Hi @gianni.zoom I created the App as both General and S2S Oauth but both thrown same error of Signature is inavlid…

@shahid.cs96 , you need to use Unified Build Flow which you can access by clicking “Build App” (not Legacy or Server to Server).

Then click, “Embed” and enable Meeting SDK. From there, use the application credentials to generate your JWT as described in the linked docs from my last response.

1 Like

Alright @gianni.zoom I will follow this approach, and hopefully it will work. Thanks for your support

1 Like

Dear @gianni.zoom

Thank you again for your prompt and helpful support in getting the Zoom Meeting web sample running smoothly. I truly appreciate your assistance.

Looking ahead, I’m aiming to integrate Zoom’s Meeting, Webinar, and Video SDKs into a full application. This will provide a robust and convenient built-in communication mechanism for our users.

I anticipate encountering additional challenges as I delve deeper into the integration process and strive to ensure everything aligns with Zoom’s standards. When these arise, I won’t hesitate to reach out to the fantastic support team, and I’m confident that your expertise will be invaluable.

Thank you once again.

Best regards,

1 Like

Hi @shahid.cs96 , thank you for your kind statement! Our developer advocacy and support teams look forward to you creating on the platform. Just a note, Video SDK is a separate developer account and it not a part of the creation flow you currently see. You would have a different developer email that allows you to build Video SDK.

Here’s some links for more info and help with the process:

1 Like

Hi @gianni.zoom
I’m reaching out regarding the Zoom SDK’s Unified Build Flow. While this approach seems effective for joining meetings, I’m encountering an error when attempting to create new meetings using the same Client ID and Client Secret credentials.

The error message indicates a “400 Bad Request” response with the reason “unsupported grant type.” I’ve attached the relevant code snippet for your reference.

My understanding is that this error arises because the Unified Build Flow application doesn’t support Account IDs, unlike Server-to-Server (S2S) applications. Interestingly, the same code successfully creates meetings with an S2S App, but then throws an “invalid signature” error when joining meetings.

Therefore, I’d like to inquire:

  • Are there guidelines to achieve both meeting creation and joining functionalities with a single application using the Unified Build Flow?
  • Would separate applications be required for these distinct functionalities (one for creation and another for joining)?

Your insights and guidance would be greatly appreciated.

Thank you for your time and assistance.

Code:
public function getToken()
{
// Check if Zoom credentials are configured
$settings = Utility::settings(\Auth::user()->id);
if (
isset($settings[‘zoom_account_id’]) && !empty($settings[‘zoom_account_id’]) &&
isset($settings[‘zoom_client_id’]) && !empty($settings[‘zoom_client_id’]) &&
isset($settings[‘zoom_client_secret’]) && !empty($settings[‘zoom_client_secret’])
) {
// Construct the basic authentication header
$basicAuthHeader = base64_encode($settings[‘zoom_client_id’] . ‘:’ . $settings[‘zoom_client_secret’]);

        // Prepare the request to obtain the access token
        $response = $this->client->request('POST', 'https://zoom.us/oauth/token', [
            'headers' => [
                'Authorization' => 'Basic ' . $basicAuthHeader,
            ],
            'form_params' => [
                'grant_type' => 'account_credentials',
                'account_id' =>  $settings['zoom_account_id']
            ],
        ]);


        // Decode the response and retrieve the access token
        $token = json_decode($response->getBody(), true);

        if (isset($token['access_token'])) {
            return $token['access_token'];
        }
    }

    return false;
}

Hi @gianni.zoom
I’m looking for your response on this thread please.

I was facing all sorts of problems, so I had posted a question. After trying a lots of things, I was able to make Web SDK and Server to Server App combination work.

I had posted my question here

It explains the problems.

And here:

The second link might help you.

I will try to post Laravel part of it here as well.

1 Like

Using Server to Server App Credentials here:

use App\Http\Controllers\Controller;
use GuzzleHttp\Client as GHttp;
use GuzzleHttp\Psr7\Request as GRequest;

// access token
$url = env('ZOOM_API_URL');
        $basic_auth = new GHttp(['base_uri' => $url]);
        $account_id = env('ZOOM_ACCOUNT_ID');
        $client_id = env('ZOOM_CLIENT_ID');
        $client_secret = env('ZOOM_CLIENT_SECRET');

        $credentials = base64_encode($client_id . ':' . $client_secret);

        $meeting_id = ''; 
        $access_token = ''; 
        $zak_token = ''; 
        $user_id = ''; // add your user id

 $response = $basic_auth->post(
            'oauth/token',
            [
                'headers' =>
                [
                    'Content-Type' => 'application/x-www-form-urlencoded',
                    'Authorization' => 'Basic ' . $credentials,

                ],
                'form_params' => [
                    "grant_type" => "account_credentials",
                    "account_id" => $account_id
                ]
            ]
        )->getBody()->getContents();

        $json_response = json_decode($response);
        $access_token = $json_response->access_token;
       //get zak token, if needed

        $zak_url = $url . 'v2/users/' . $user_id . '/token/?type=zak';
        $headers =  ['headers' =>, 
        [
            'Authorization' => 'Bearer ' . $access_token

        ]];
        $request = new GRequest('GET', $zak_url);

        $response = $basic_auth->send($request, $headers)->getBody()->getContents();

        $json_response = json_decode($response);
        $zak_token = $json_response->token;

create meeting

$response = $basic_auth->post(
            '/v2/users/' . $user_id . '/meetings',
            [
                'headers' =>
                [
                    'Content-Type' => 'application/json',
                    'Authorization' => 'Bearer  ' . $access_token,

                ],
                'json' => [
                    'topic' => 'My Topic',
                    'type' => 1,
                    'agenda' => '',
                    'settings' => [
                        'waiting_room' => false,
                        'host_video' => true,
                        'participant_video' => true,
                        'join_before_host' => true,
                        'mute_upon_entry' => true,
                        'approval_type' => 0,
                        'auto_recording' => 'cloud'
                    ]
                ]
            ]
        )->getBody()->getContents();

        $meeting_json_response = json_decode($response);

// get user details if needed
$user_details = $basic_auth->get(
            'v2/users/' . $user_id,
            [
                'headers' =>
                [
                    'Content-Type' => 'application/x-www-form-urlencoded',
                    'Authorization' => 'Bearer ' . $access_token,

                ]
            ]
        )->getBody()->getContents();


        dd($user_details);
1 Like

Hi @longoff
Thanks for your detail response.
Though our use cases look same for Zoom integration and your code looks fine to create the meeting via S2S app, but how do you manage to join the meeting, perhaps using normal app separately from S2S.
Please also advice how to assign multiple users in meeting

Yes. I am using a Web SDK on the frontend and second app credentials (Not server to Server App) to join, create signatures etc. Please check the links that I have posted above. Second link might help you. It has all the detailed discussion of what I tried, and how it finally seems to have worked.

I tested with more than one host users now.

Only thing is, the normal App remains in draft mode and I do not want to publish it. It is for our internal use.

2 Likes

Hi @longoff , thank you for sharing the links to the other threads! This is the guidance we recommend.

1 Like