Best Practices
Avoid generating JWTs with unlimited or very long expiry.
Create short-lived JWTs that are valid only for a few minutes using
exp
claim in the payload.Add a
nbf
claim for scheduled meetings so that the host cannot create a meeting before meeting start time.Limit one JWT to a single room by setting
room
to the meetingroomName
instead of "*".Keep your api key safe and secret.
Use the following code snippets to generate JWTs. Find and replace all instances of cm-consumer-id
with your Clan Meeting consumer ID. Copy the cm-api-key.pem
file shared with you and add relative file path if required.
Node.js
Refer: https://github.com/auth0/node-jsonwebtoken
xxxxxxxxxx
11$ npm install jsonwebtoken
x
1const jwt = require('jsonwebtoken');
2const fs = require('fs');
3
4const header = {
5 // TODO Edit this
6 keyid: "cm-consumer-id",
7 algorithm: "RS256"
8}
9
10const payLoad = {
11 // TODO Edit this
12 sub: "cm-consumer-id",
13 aud: "clanmeeting",
14 iss: "production",
15 // TODO Edit this
16 room: "specify-room-name-here",
17 exp: Math.floor(Date.now() / 1000) + (60 * 15), // token will be valid for 5 minutes only
18 nbf: Math.floor(Date.now() / 1000),
19 context: {},
20}
21
22// Synchronous sign
23const 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:
xxxxxxxxxx
11composer 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:
xxxxxxxxxx
11composer require paragonie/sodium_compat
x
1use Firebase\JWT\JWT;
2
3$now = time();
4$expiry_in_seconds = 60 * 15; // token will be valid for the next 15 minutes
5
6// TODO Edit this
7$header = "cm-consumer-id";
8
9$payload = array(
10 // TODO Edit this
11 "sub"=> "cm-consumer-id",
12 "aud"=> "clanmeeting",
13 "iss"=> "production",
14 // TODO Edit this
15 "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
xxxxxxxxxx
11$ pip install pyjwt
xxxxxxxxxx
11$ pip install pyjwt[crypto]
x
1import jwt
2import datetime
3
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:
xxxxxxxxxx
11gem install jwt
Bundler:
Add the following to your Gemfile
xxxxxxxxxx
11gem 'jwt'
And run bundle install
x
1require 'jwt'
2require 'openssl'
3
4# Please see above examples for payload
5payload = { foo: 'bar' }
6
7private_key_file = 'cm-api-key.pem';
8signature = OpenSSL::PKey::RSA.new(File.read 'private_key_file')
9
10# TODO edit kid
11token = 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.