# JWT for Zoom Video SDK The [Zoom Video SDK](/docs/video-sdk/) provides video, audio, screen sharing, chat, and more with an easy to use SDK. In this blog we'll showcase adding video chat to a [Ruby on Rails](https://rubyonrails.org/) web application. ## Prerequisites: - Rails 8.0+ - A Zoom [Video SDK Account](/docs/video-sdk/get-credentials/) You can find the completed project on [GitHub](https://github.com/zoom/videosdk-rubyonrails-quickstart). ## Step 1: Scaffold the application If you already have a [Ruby on Rails](https://rubyonrails.org/) project, you can skip this step. Open a terminal and execute: ```shell rails new videosdk-rails-app --css=tailwind cd videosdk-rails-app ``` After running these commands, you'll have a new Rails project set up with Tailwind CSS for styling. ## Step 2: Configuring the project #### Install the dependencies We will install the JWT gem for token generation and dotenv-rails for environment variable management. Add these to your `Gemfile`: ```ruby # JWT for Zoom Video SDK gem "jwt" # Environment variables gem "dotenv-rails" ``` Then run `bundle install` to install the gems. These gems allow your Rails app to generate JWT tokens (required for Zoom authentication) and securely manage your environment variables. ### Enable shared array buffer support To leverage the full power of the Zoom Video SDK including features like rendering multiple videos, virtual background, & background noise suppression, we need to enable support for Shared Array Buffers (SAB) in the browser. Simply, download this [file](https://github.com/gzuidhof/coi-serviceworker/blob/master/coi-serviceworker.js) and place it in the `public` folder of your project as `public/coi-serviceworker.js`. By adding this file, you enable Shared Array Buffer support in browsers that require a cross-origin isolated context. This is necessary for advanced video features in the Zoom SDK. ### Add environment variables To complete the setup, create a `.env` file in the root of our project and add the Zoom Video SDK Key and Secret to it. You can find your SDK Key and Secret in the [Video SDK Dashboard](https://marketplace.zoom.us), by clicking on the _Develop_ button and selecting _Build Video SDK_. Make sure you're logged in to your Video SDK account. ```bash ZOOM_SDK_KEY="Your Zoom SDK Key" ZOOM_SDK_SECRET="Your Zoom SDK Secret" ``` This file keeps your sensitive credentials out of your codebase. The `dotenv-rails` gem will load these values into your app's environment. You can start the Rails development server with `rails server`. The app will be available at `http://localhost:3000/`. ## Step 3: Set up the controller and routes ### Create the Zoom controller We'll create a controller to handle JWT generation and video session management: ```shell rails generate controller Zoom index generate_jwt video_session ``` This command generates a new controller called `ZoomController` with three actions: `index`, `generate_jwt`, and `video_session`. It also creates the corresponding view files. ### Configure routes Update your `config/routes.rb` file to define the routes for our video conferencing app: ```ruby Rails.application.routes.draw do # Zoom Video SDK routes root "zoom#index" post "zoom/generate_jwt", to: "zoom#generate_jwt" get "zoom/video_session", to: "zoom#video_session" end ``` These routes set the home page to the session form, provide an endpoint for generating JWTs, and a page for joining the video session. ### Implement JWT generation The Zoom Video SDK uses JWTs to authenticate a session. We'll implement the JWT generation in our controller. Update `app/controllers/zoom_controller.rb`: ```ruby class ZoomController < ApplicationController def index end def generate_jwt session_name = params[:session_name] role = params[:role] || 0 # Default to attendee role begin jwt_token = generate_signature(session_name, role.to_i) render json: { jwt: jwt_token, session_name: session_name } rescue => e render json: { error: e.message }, status: :unprocessable_entity end end def video_session @session_name = params[:session_name] @jwt_token = params[:jwt] end private def generate_signature(session_name, role) sdk_key = ENV['ZOOM_SDK_KEY'] sdk_secret = ENV['ZOOM_SDK_SECRET'] if sdk_key.blank? || sdk_secret.blank? raise "Missing ZOOM_SDK_KEY or ZOOM_SDK_SECRET environment variables, please add them in .env file." end iat = (Time.current.to_i) - 30 exp = iat + (60 * 60 * 1) # 1 hour header = { alg: 'HS256', typ: 'JWT' } payload = { app_key: sdk_key, tpc: session_name, role_type: role, version: 1, iat: iat, exp: exp } JWT.encode(payload, sdk_secret, 'HS256', header) end end ``` This controller handles three things: - The `index` action renders the main form. - The `generate_jwt` action receives a session name and role, generates a JWT using your credentials, and returns it as JSON. - The `video_session` action passes the session name and JWT to the view for use in the video call. The `generate_signature` method creates a JWT token using the session name and role. We're using the `jwt` gem to encode the payload with the SDK secret. The token is valid for 1 hour and includes the necessary claims for Zoom Video SDK authentication. ## Step 4: Build the main form We'll create a simple form to collect session information. ![demo form screen](/img/blog/ekaansharora/ror-quickstart/form.png) Update `app/views/zoom/index.html.erb`: ```html

Zoom Video SDK Quickstart

``` This form collects the session name and role from the user. > _**Note**: To make the code blocks easy to read, I've omitted the tailwind styles from the code blocks. You can find them in the GitHub repo._ ```html ``` When the form is submitted, it sends a POST request to your Rails backend to generate a JWT. If successful, it redirects the user to the video session page with the JWT and session name as parameters. ## Step 5: Build the video session component Now for the fun part of building the video call component. We'll create the video session view at `app/views/zoom/video_session.html.erb`: ```html <% content_for :title, "Zoom Video Session" %>

Zoom VideoSDK Quickstart

``` The HTML template provides join/leave buttons, video/audio toggle controls, and a video player container custom element that will hold both the local user's and remote participants' video streams. ```html