From 7da272f67aebd9681b152066003bd31eb6b6e93d Mon Sep 17 00:00:00 2001 From: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Date: Wed, 7 Sep 2022 14:18:11 -0400 Subject: [PATCH] Prevent saving error responses from Zoom to user credentials (#3743) --- .../zoomvideo/lib/VideoApiAdapter.ts | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/packages/app-store/zoomvideo/lib/VideoApiAdapter.ts b/packages/app-store/zoomvideo/lib/VideoApiAdapter.ts index fe5971cf58..3219b085c3 100644 --- a/packages/app-store/zoomvideo/lib/VideoApiAdapter.ts +++ b/packages/app-store/zoomvideo/lib/VideoApiAdapter.ts @@ -44,6 +44,7 @@ export const zoomMeetingsSchema = z.object({ ), }); +// Successful API response const zoomTokenSchema = z.object({ scope: z.string().regex(new RegExp("meeting:write")), expiry_date: z.number(), @@ -55,12 +56,9 @@ const zoomTokenSchema = z.object({ type ZoomToken = z.infer; +const isTokenValid = (token: ZoomToken) => (token.expires_in || token.expiry_date) < Date.now(); + const zoomAuth = (credential: Credential) => { - const credentialKey = zoomTokenSchema.parse(credential.key); - - const isTokenValid = (token: ZoomToken) => - token && token.token_type && token.access_token && (token.expires_in || token.expiry_date) < Date.now(); - const refreshAccessToken = async (refreshToken: string) => { const { client_id, client_secret } = await getZoomAppKeys(); const authHeader = "Basic " + Buffer.from(client_id + ":" + client_secret).toString("base64"); @@ -77,6 +75,7 @@ const zoomAuth = (credential: Credential) => { }) .then(handleErrorsJson) .then(async (responseBody) => { + if (!responseBody.refresh_token) Promise.reject(new Error("Invalid credentials")); // set expiry date as offset from current time. responseBody.expiry_date = Math.round(Date.now() + responseBody.expires_in * 1000); delete responseBody.expires_in; @@ -89,17 +88,28 @@ const zoomAuth = (credential: Credential) => { key: responseBody, }, }); - credentialKey.expiry_date = responseBody.expiry_date; - credentialKey.access_token = responseBody.access_token; - return credentialKey.access_token; + return responseBody.access_token; }); }; return { - getToken: () => - !isTokenValid(credentialKey) + getToken: async () => { + let credentialKey: ZoomToken | null = null; + try { + credentialKey = zoomTokenSchema.parse(credential.key); + } catch (error) { + // If the parse fails, it means we have an invalid credential saved. We should delete it. + await prisma.credential.delete({ where: { id: credential.id } }); + // We reject the promise, and should handle the error on the UI + return Promise.reject( + "This Zoom credential was malformed so we've removed it from the DB. Please add a new Zoom credential" + ); + } + + return !isTokenValid(credentialKey) ? Promise.resolve(credentialKey.access_token) - : refreshAccessToken(credentialKey.refresh_token), + : refreshAccessToken(credentialKey.refresh_token); + }, }; };