Zoom Apps Configuration
The app frontend is React + NextJS, and the backend is running Python + Django, with auth purely on our side (no 3rd party). The app is to be embedded in a Zoom desktop.
We are trying the in-client auth feature with the goal to verify & identify the logged in user in Desktop & then issue him Application Auth token pair, so that the user can access Application functionality. Here are the steps:
- Verify in the frontend from the user is authorized or not. If not authorized, call ZoomSdk.authorize
- If authorized, get App Context & send it our backend API
- The backend API decrypts the token (the Zoom app client secret used to decode it also verifies it), identifies the user & issues the application token pair.
- The frontend continues to listen to:
- userContext changes to see if it needs to authorize again
- periodically refresh the application token pair using the refresh token
- The frontend gets the application data using the token pair above
I have 2 questions:
- Is the above flow correct? Specifically - also in this case in the frontend, is ZoomSdk.authorize() or .promptAuthorize() better to call?
- I’m getting an error when decrypting the Zoom App token in the backend. Logic & sample code is below. Need help debugging this.
Error?
def decode_base64url(self, input_str):
# Replace base64url characters with base64 equivalents
input_str = input_str.replace('-', '+').replace('_', '/')
# Pad with '=' to make the length a multiple of 4
padding = len(input_str) % 4
if padding > 0:
input_str += '=' * (4 - padding)
return base64.b64decode(input_str)
def decrypt_zoom_app_context(self, context, secret_key=None):
client_secret = settings.ZOOM_PLUGIN.get('SPEAKER').get('CLIENT_SECRET')
context_bytes = self.decode_base64url(context)
iv_length = context_bytes[0]
iv = context_bytes[1:1 + iv_length]
aad_length = int.from_bytes(context_bytes[1 + iv_length:3 + iv_length], byteorder='little')
aad = context_bytes[3 + iv_length:3 + iv_length + aad_length]
cipher_length = int.from_bytes(context_bytes[3 + iv_length + aad_length:7 + iv_length + aad_length], byteorder='little')
cipher_text = context_bytes[7 + iv_length + aad_length:7 + iv_length + aad_length + cipher_length]
tag = context_bytes[7 + iv_length + aad_length + cipher_length:]
derive = HKDF(
algorithm=hashes.SHA256(),
length=32,
salt=None,
info=b'handshake data',
backend=default_backend()
)
key = derive.derive(client_secret.encode())
# Setup cipher
cipher = Cipher(
algorithms.AES(key),
modes.GCM(iv, tag),
backend=default_backend()
)
decryptor = cipher.decryptor()
decrypted = decryptor.update(cipher_text) + decryptor.finalize()
return json.loads(decrypted.decode('utf-8'))
I’m getting the below error in decryptor.finalize()
decrypted = decryptor.update(cipher_text) + decryptor.finalize()
^^^^^^^^^^^^^^^^^^^^
File "/Users/arvind/venv/lib/python3.11/site-packages/cryptography/hazmat/primitives/ciphers/base.py", line 229, in finalize
data = self._ctx.finalize()
^^^^^^^^^^^^^^^^^^^^
File "/Users/arvind/venv/lib/python3.11/site-packages/cryptography/hazmat/backends/openssl/ciphers.py", line 200, in finalize
raise InvalidTag
cryptography.exceptions.InvalidTag
Troubleshooting Routes
The intermediate debugging values look reasonable - ie iv has length 12, AAD is 0 length, cipher is 216 chars & tag 16 chars. Base64 encoded input was 335 length, with the decoded one 251.
How To Reproduce
Call decrypt_zoom_app_context with this one value I got from zoom -
DGXwvj7p0Xbh7brIgAAA2AAAAEikLl9deBnPNlaABm9UNSyNOQttdQ9Lr9Nw9XDbhX09MtgaO_jAZkObkQDwjb13y-fB75FksOvhWJlKA_jiH5zq18Q4jrNUYigklz_syAKMDTu_k5L1eDRX_iMgjfAiIIh8r9uwzZp_oqIdiqEHYpm-8EF74B88Dnjx-lDmarqvz8dwi5RvajwqdQJVXDRqVNCOGz9JR90r1Fw75I9AKNDCOw7KeLja96ofIlA3f3tEbAU7ozDBQ63uosCaoqoU0lLi8sb8sRxRdQLaKHgZokyLewHLRNBeuEv_oQLQO6Qvtp8659xPo84