Best Practices #
Avoid generating JWTs with unlimited or very long expiry.
Create short-lived JWTs that are valid only for a few minutes using
expclaim in the payload.Add a
nbfclaim for scheduled meetings so that the host cannot create a meeting before meeting start time.Limit one JWT to a single room by setting
roomto the meetingroomNameinstead of "*".Keep your api key safe and secret.
Until now we have been using static tokens for testing. We can use the following code snippets instead to generate JWTs on the go when someone creates a meeting.
Find and replace all instances of cm-consumer-id with your Clan Meeting consumer ID in the code below.
Get your private SSH key file and replace cm-api-key.pem in the code snippets below with the exact file name. Add relative file path if required.
Node.js #
Refer: https://github.com/auth0/node-jsonwebtoken
xxxxxxxxxx11$ npm install jsonwebtoken
xxxxxxxxxx271const jwt = require('jsonwebtoken');2const fs = require('fs');3
4const header = {5 // TODO Edit this6 keyid: "cm-consumer-id",7 algorithm: "RS256"8}9
10const payLoad = {11 // TODO Edit this12 sub: "cm-consumer-id",13 aud: "clanmeeting",14 iss: "production",15 // TODO Edit this16 room: "specify-room-name-here", 17 exp: Math.floor(Date.now() / 1000) + (60 * 15), // token will be valid for 5 minutes only18 nbf: Math.floor(Date.now() / 1000),19 context: {},20}21
22// Synchronous sign23const signature = fs.readFileSync('cm-api-key.pem');24
25const token = jwt.sign(payLoad, signature, header);26
27console.log(token);
PHP #
Refer: https://github.com/firebase/php-jwt
Use composer to manage your dependencies and download PHP-JWT:
xxxxxxxxxx11composer require firebase/php-jwt
Optionally, install the paragonie/sodium_compat package from composer if your php is < 7.2 or does not have libsodium installed:
xxxxxxxxxx11composer require paragonie/sodium_compat
xxxxxxxxxx281use Firebase\JWT\JWT;2
3$now = time();4$expiry_in_seconds = 60 * 15; // token will be valid for the next 15 minutes5
6// TODO Edit this7$header = "cm-consumer-id";8
9$payload = array(10 // TODO Edit this11 "sub"=> "cm-consumer-id",12 "aud"=> "clanmeeting",13 "iss"=> "production",14 // TODO Edit this15 "room"=> "specify-room-name-here", 16 "exp"=> $now + $expiry_in_seconds,17 "nbf"=> $now,18 "context"=> array()19);20
21$private_key_file = url('cm-api-key.pem');22
23$signature = openssl_pkey_get_private(24 file_get_contents($private_key_file)25);26
27$token = JWT::encode($payload, $signature, 'RS256', $header);28echo $token;
Python #
Refer: https://pyjwt.readthedocs.io/en/stable/usage.html#encoding-decoding-tokens-with-rs256-rsa
xxxxxxxxxx11$ pip install pyjwt
xxxxxxxxxx11$ pip install pyjwt[crypto]
xxxxxxxxxx211import jwt2import datetime3
4header = {"kid": "cm-consumer-id"}5
6now = datetime.datetime.utcnow()7payload = {8 "sub": "cm-consumer-id",9 "aud": "clanmeeting",10 "iss": "production",11 "room": "specify-room-name-here",12 "exp": now + datetime.timedelta(seconds=900), # e.g. User should login within the next 15 minutes.13 "nbf": now,14 "context": {}15}16
17with open('cm-api-key.pem','r') as file:18 signature = file.read()19 20token = jwt.encode(payload, signature, algorithm="RS256", headers=header)21print(token)
Ruby #
Refer: https://github.com/jwt/ruby-jwt
Rubygems:
xxxxxxxxxx11gem install jwt
Bundler:
Add the following to your Gemfile
xxxxxxxxxx11gem 'jwt'
And run bundle install
xxxxxxxxxx131require 'jwt'2require 'openssl'3
4# Please see above examples for payload5payload = { foo: 'bar' }6
7private_key_file = 'cm-api-key.pem';8signature = OpenSSL::PKey::RSA.new(File.read 'private_key_file')9
10# TODO edit kid11token = JWT.encode payload, signature, 'RS256', header_fields= { kid: 'cm-consumer-id' }12
13puts token
Java #
https://github.com/auth0/java-jwt
OR
Others #
RS256 algorithm should be supported by the library used to generate JWT.
