Skip to content

Commit bece9ee

Browse files
authored
VC/Zoom: Drop support for JWT authentication (#224)
1 parent 6734a2f commit bece9ee

File tree

4 files changed

+30
-53
lines changed

4 files changed

+30
-53
lines changed

vc_zoom/README.md

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
- Adapt to Indico 3.3 changes
1717
- Support Python 3.12
18+
- Drop support for discontinued JWT authentication
1819

1920
### 3.2.5
2021

@@ -151,12 +152,6 @@ The scopes to select when creating the app are:
151152
- `webinar:write:admin` (optional, only needed when using webinars)
152153

153154

154-
### Zoom API key/secret (JWT, deprecated)
155-
156-
Zoom deprecated JWTs in June 2023, existing ones still work but no new ones can be created.
157-
As soon as Zoom fully dropped them, JWT support will also be removed from this plugin.
158-
159-
160155
## Intellectual Property
161156

162157
Developed by Giovanni Mariano @ **ENEA Frascati**, based on the Vidyo Plugin by the Indico Team at **CERN**. Further

vc_zoom/indico_vc_zoom/api/client.py

Lines changed: 28 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import time
99

10-
import jwt
1110
import requests
1211
from pytz import utc
1312
from requests import Session
@@ -172,20 +171,16 @@ class ZoomClient:
172171
'webinar': WebinarComponent
173172
}
174173

175-
def __init__(self, api_key, api_secret, account_id, client_id, client_secret, timeout=15):
174+
def __init__(self, account_id, client_id, client_secret, timeout=15):
176175
"""Create a new Zoom client.
177176
178-
:param api_key: the Zoom JWT API key
179-
:param api_secret: the Zoom JWT API Secret
180177
:param account_id: the Zoom Server OAuth Account ID
181178
:param client_id: the Zoom Server OAuth Client ID
182179
:param client_secret: the Zoom Server OAuth Client Secret
183180
:param timeout: the time out to use for API requests
184181
"""
185182
# Setup the config details
186183
config = {
187-
'api_key': api_key,
188-
'api_secret': api_secret,
189184
'account_id': account_id,
190185
'client_id': client_id,
191186
'client_secret': client_secret,
@@ -217,8 +212,6 @@ class ZoomIndicoClient:
217212
def __init__(self):
218213
from indico_vc_zoom.plugin import ZoomPlugin
219214
self.client = ZoomClient(
220-
ZoomPlugin.settings.get('api_key'),
221-
ZoomPlugin.settings.get('api_secret'),
222215
ZoomPlugin.settings.get('account_id'),
223216
ZoomPlugin.settings.get('client_id'),
224217
ZoomPlugin.settings.get('client_secret'),
@@ -262,36 +255,31 @@ def get_zoom_token(config, *, force=False):
262255
client_id = config['client_id']
263256
client_secret = config['client_secret']
264257

265-
if account_id and client_id and client_secret:
266-
ZoomPlugin.logger.debug(f'Using Server-to-Server-OAuth ({force=})')
267-
hash_key = '-'.join((account_id, client_id, client_secret))
268-
cache_key = f'token-{crc32(hash_key)}'
269-
if not force and (token_data := token_cache.get(cache_key)):
270-
expires_in = int(token_data['expires_at'] - time.time())
271-
ZoomPlugin.logger.debug('Using token from cache (%s, %ds remaining)', cache_key, expires_in)
272-
return token_data['access_token'], token_data['expires_at']
273-
try:
274-
resp = requests.post(
275-
'https://zoom.us/oauth/token',
276-
params={'grant_type': 'account_credentials', 'account_id': account_id},
277-
auth=(client_id, client_secret)
278-
)
279-
resp.raise_for_status()
280-
except HTTPError as exc:
281-
ZoomPlugin.logger.error('Could not get zoom token: %s', exc.response.text if exc.response else exc)
282-
raise Exception('Could not get zoom token; please contact an admin if this problem persists.')
283-
token_data = resp.json()
284-
assert 'access_token' in token_data
285-
ZoomPlugin.logger.debug('Got new token from Zoom (expires_in=%s, scope=%s)', token_data['expires_in'],
286-
token_data['scope'])
287-
expires_at = int(time.time() + token_data['expires_in'])
288-
token_data.setdefault('expires_at', expires_at) # zoom doesn't include this. wtf.
289-
token_cache.set(cache_key, token_data, token_data['expires_in'])
290-
return token_data['access_token'], token_data['expires_at']
291-
elif config['api_key'] and config['api_secret']:
292-
ZoomPlugin.logger.warning('Using JWT (deprecated)')
293-
header = {'alg': 'HS256', 'typ': 'JWT'}
294-
payload = {'iss': config['api_key'], 'exp': int(time.time() + 3600)}
295-
return jwt.encode(payload, config['api_secret'], algorithm='HS256', headers=header), None
296-
else:
258+
if not (account_id and client_id and client_secret):
297259
raise Exception('Zoom authentication not configured')
260+
261+
ZoomPlugin.logger.debug(f'Using Server-to-Server-OAuth ({force=})')
262+
hash_key = '-'.join((account_id, client_id, client_secret))
263+
cache_key = f'token-{crc32(hash_key)}'
264+
if not force and (token_data := token_cache.get(cache_key)):
265+
expires_in = int(token_data['expires_at'] - time.time())
266+
ZoomPlugin.logger.debug('Using token from cache (%s, %ds remaining)', cache_key, expires_in)
267+
return token_data['access_token'], token_data['expires_at']
268+
try:
269+
resp = requests.post(
270+
'https://zoom.us/oauth/token',
271+
params={'grant_type': 'account_credentials', 'account_id': account_id},
272+
auth=(client_id, client_secret)
273+
)
274+
resp.raise_for_status()
275+
except HTTPError as exc:
276+
ZoomPlugin.logger.error('Could not get zoom token: %s', exc.response.text if exc.response else exc)
277+
raise Exception('Could not get zoom token; please contact an admin if this problem persists.')
278+
token_data = resp.json()
279+
assert 'access_token' in token_data
280+
ZoomPlugin.logger.debug('Got new token from Zoom (expires_in=%s, scope=%s)', token_data['expires_in'],
281+
token_data['scope'])
282+
expires_at = int(time.time() + token_data['expires_in'])
283+
token_data.setdefault('expires_at', expires_at) # zoom doesn't include this. wtf.
284+
token_cache.set(cache_key, token_data, token_data['expires_in'])
285+
return token_data['access_token'], token_data['expires_at']

vc_zoom/indico_vc_zoom/plugin.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@
4242

4343
class PluginSettingsForm(VCPluginSettingsFormBase):
4444
_fieldsets = [
45-
(_('API Credentials (Server-to-Server OAuth)'), ['account_id', 'client_id', 'client_secret', 'webhook_token']),
46-
(_('API Credentials (Legacy JWT, deprecated)'), ['api_key', 'api_secret']),
45+
(_('API Credentials'), ['account_id', 'client_id', 'client_secret', 'webhook_token']),
4746
(_('Zoom Account'), ['user_lookup_mode', 'email_domains', 'authenticators', 'enterprise_domain',
4847
'allow_webinars', 'phone_link']),
4948
(_('Room Settings'), ['mute_audio', 'mute_host_video', 'mute_participant_video', 'join_before_host',
@@ -52,8 +51,6 @@ class PluginSettingsForm(VCPluginSettingsFormBase):
5251
(_('Access'), ['managers', 'acl'])
5352
]
5453

55-
api_key = StringField(_('API Key'), [])
56-
api_secret = IndicoPasswordField(_('API Secret'), [], toggle=True)
5754
account_id = StringField(_('Account ID'), [])
5855
client_id = StringField(_('Client ID'), [])
5956
client_secret = IndicoPasswordField(_('Client Secret'), [], toggle=True)
@@ -137,8 +134,6 @@ class ZoomPlugin(VCPluginMixin, IndicoPlugin):
137134
vc_room_attach_form = VCRoomAttachForm
138135
friendly_name = 'Zoom'
139136
default_settings = VCPluginMixin.default_settings | {
140-
'api_key': '',
141-
'api_secret': '',
142137
'account_id': '',
143138
'client_id': '',
144139
'client_secret': '',

vc_zoom/setup.cfg

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ include_package_data = true
2424
python_requires = >=3.9.0, <3.13
2525
install_requires =
2626
indico>=3.3.dev0
27-
PyJWT>=2.0.0,<3
2827

2928
[options.entry_points]
3029
indico.plugins =

0 commit comments

Comments
 (0)