[Web SDK] Random "Joining meeting timeout. Signature is invalid" error

We are trying to integrate Zoom into our application using Web SDK and only one issue has not resolved yet. We faced with “Joining meeting timeout. Signature is invalid” randomly on both of our environments (development and staging). After clicking several times on “retry” button user is able to join to the meeting successfully. It occurs for every meeting for any user. We were able to find several opened issues in your devforum but they were not very helpful (Clock sync was suggested as a solution. But clock is synchronized in our environments for sure because we had sync clock issue with other integration). Could you help as to figure out what is the reason of this randomly occurred error? We are using ruby language to generate signature using the code snippet provided in your documentation and JWT zoom application for integration

Thank you.

Joining meeting timeout. Signature is invalid

Which version?
We are using CDN solution. The version is 1.7.9.

To Reproduce(If applicable)
Steps to reproduce the behavior:

  1. Initiate joining to the meeting using JS (ZoomMtg.join method)
  2. User sees an error message ‘Joining meeting timeout. Signature is invalid’
  3. Click retry several times
  4. User is successfully joined to the meeting.

Laptop (please complete the following information):

  • Does not matter. It is reproducible in different devices and different OS

Additional context
Tried to use other possible variations of signature generation. Tried to use UTC timezone explicitly. Both of this actions did not resolve the problem.

Hey @onboardu,

Can you please share your Web SDK signature that is throwing this error so I can debug it?


Hi Tommy,

Here is invalid signature received after first attempt to join the meeting (after two retries I was able to join the meeting using another signature): QmRyeDVqRF9Sc2FnYjkwMkU3STE1QS44NTgyMzI3MjgzMy4xNTk1NjM2Mzk0MDAwLjEuMkhZU2NsRDV0aG5BYWowM3hpUGljc0RiVDZOd1lLZjJhSDVicy1yM1VVOD0=

Hey @onboardu,

Are you still having issues then?


Hi @tommy ,

Yes we are. Every time when we try to join to the meeting, we have to make 3 or more retries until successful join.

Hi @onboardu and @tommy,

I actually noticed that the sample Ruby code nearly always generates this error for me. I adapted the following code from another forum post a while back (can’t find the link right now), and it’s been working consistently:

require "base64"

module SignatureRoles
  HOST = 1

def generate_signature(meeting_id:)
  # Prevent time sync issue between client signature generation and Zoom
  timestamp = (Time.now.to_f * 1000).round(0) - 30000

  role = <logic for host or participant> ? SignatureRoles::HOST : SignatureRoles::PARTICIPANT
  key = Rails.application.config.zoom.api_key
  secret = Rails.application.config.zoom.api_secret

  message = Base64.strict_encode64([key, meeting_id, timestamp, role].join)
  hash = Base64.strict_encode64(OpenSSL::HMAC.digest("SHA256", secret, message))

  Base64.strict_encode64([key, meeting_id, timestamp, role, hash].join("."))

Hope this helps!

Hey @onboardu,

Just FYI, you are passing role 1 into the Web SDK signature which means you are trying to start the meeting. If you are trying to join the meeting, try passing in role 0 and let me know if that fixes the issue.


Hey @abiyani,

Thanks for sharing this. We will reanalyze the Ruby sample code. :slight_smile:


@abiyani Thanks so much! It works!

1 Like

Happy to hear that is working! :slight_smile:


The problem is that ruby doesn’t use the same aphabet:


the gsub is performed on the final tempStr instead of the hash only

Here is the modified version that works:

time = (Time.now.to_i * 1000 - 30000).to_s
data = Base64.urlsafe_encode64(options[:api_key] + options[:meeting_number] + time + options[:role].to_s)
hash = Base64.urlsafe_encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), options[:api_secret], data))
tempStr = options[:api_key] + '.' + options[:meeting_number] + '.' + time + '.' + options[:role].to_s + '.' + hash
replacedTmpStr = tempStr.gsub('-', '+').gsub('_', '/')
return Base64.urlsafe_encode64(replacedTmpStr).gsub(/#{Regexp.escape('=')}+$/, '')
1 Like

Hey @cnadeau,

Thanks for posting this and contributing to the Zoom Developer Community! :slight_smile: