Hey @ojus.zoom, I wouldn’t call sending requests to the rest api without an sdk custom, just regular usage of a web api.
Anyway here are results that can be duplicated when the recording is public or private. I have redacted all sensitive information.
Setting the access token in the url query
First is setting the access token query parameter, this is usually done with a webhook that includes a download token. But a download token is not available outside the context of the webhook so here it is being substituted by the user’s access token obtained from their refresh token.
curl -v "https://api.zoom.us/recording/download/recording/download/<< download id>>?access_token=<< access token obtained from refresh token>>"
* Trying 52.202.62.237...
* TCP_NODELAY set
* Connected to api.zoom.us (52.202.62.237) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: OU=Domain Control Validated; CN=*.zoom.us
* start date: Mar 25 19:38:42 2019 GMT
* expire date: Mar 25 19:38:42 2021 GMT
* subjectAltName: host "api.zoom.us" matched cert's "*.zoom.us"
* issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2
* SSL certificate verify ok.
> GET /recording/download/<< download id>>?access_token=<< access token obtained from refresh token>> HTTP/1.1
> Host: api.zoom.us
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Date: Thu, 16 May 2019 20:27:34 GMT
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Server: ZOOM
< x-zm-trackingid: WEB_39d8a5536bcac863bc669f7ae0edbe9c
< Set-Cookie: _zm_mtk_guid=<<cookie stuff>>; Domain=.zoom.us; Expires=Tue, 03-Jun-2087 23:41:41 GMT; Path=/; Secure
<
* Connection #0 to host api.zoom.us left intact
{"status":false,"errorCode":401,"errorMessage":"java.lang.IllegalArgumentException: Scope cannot be null","result":null}%
What’s funky is we have all the correct scopes being set, and the access token is being validated because I messed up and forgot a letter in the access token which resulted in a different error stating that it was an invalid access token.
Setting the Authorization Header
Next is setting the Authorization
header, which is how the rest of the zoom api performs, this results in a different error seen here.
curl -v -H "Authorization: Bearer <<access token obtained from client refresh token>>" "https://api.zoom.us/recording/download/<<download id>>"
* Trying 52.202.62.238...
* TCP_NODELAY set
* Connected to api.zoom.us (52.202.62.238) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: OU=Domain Control Validated; CN=*.zoom.us
* start date: Mar 25 19:38:42 2019 GMT
* expire date: Mar 25 19:38:42 2021 GMT
* subjectAltName: host "api.zoom.us" matched cert's "*.zoom.us"
* issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2
* SSL certificate verify ok.
> GET /recording/download/<<download id>> HTTP/1.1
> Host: api.zoom.us
> User-Agent: curl/7.54.0
> Accept: */*
> Authorization: Bearer <<access token obtained from client refresh token>>
>
< HTTP/1.1 401 Unauthorized
< Date: Thu, 16 May 2019 20:31:17 GMT
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Server: ZOOM
< x-zm-trackingid: WEB_bfeee8f55376baf1272152960b86a627
< Set-Cookie: _zm_mtk_guid=<<cookie stuff>>; Domain=.zoom.us; Expires=Tue, 03-Jun-2087 23:45:24 GMT; Path=/; Secure
<
* Connection #0 to host api.zoom.us left intact
{"status":false,"errorCode":401,"errorMessage":"java.lang.IllegalArgumentException: urn:zoom:connect:clientid:<<my client id>> not support","result":null}%
What’s crazy here is it even returned my client id.
Success
Here is a correct one for a public recording, this is nothing special as I have no auth provided.
curl -v "https://api.zoom.us/recording/download/<<download id>>"
* Trying 52.202.62.238...
* TCP_NODELAY set
* Connected to api.zoom.us (52.202.62.238) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: OU=Domain Control Validated; CN=*.zoom.us
* start date: Mar 25 19:38:42 2019 GMT
* expire date: Mar 25 19:38:42 2021 GMT
* subjectAltName: host "api.zoom.us" matched cert's "*.zoom.us"
* issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2
* SSL certificate verify ok.
> GET /recording/download/<<download id>> HTTP/1.1
> Host: api.zoom.us
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Thu, 16 May 2019 20:23:18 GMT
< Content-Type: txt;charset=UTF-8
< Content-Length: 495
< Connection: keep-alive
< Server: ZOOM
< x-zm-trackingid: WEB_0c253a7085e655c599d8bbfdcfc85bc6
< Set-Cookie: _zm_mtk_guid=<<more cookie stuff>>; Domain=.zoom.us; Expires=Tue, 03-Jun-2087 23:37:24 GMT; Path=/; Secure
< X-Robots-Tag: noindex, nofollow
< X-Content-Type-Options: nosniff
< Set-Cookie: cred=<<cookie stuff>>; Path=/; Secure; HttpOnly
< Set-Cookie: _zm_page_auth=<<hide this>>; Domain=.zoom.us; Path=/; Secure; HttpOnly
< p3p: CP="NOI ADM DEV PSAi COM NAV OUR OTR STP IND DEM"
< Set-Cookie: _zm_ssid=<<more cookie stuff>>; Domain=.zoom.us; Path=/; Secure; HttpOnly
< Content-Disposition: attachment;filename=GMT20190513-223817_-No-title-.transcript.vtt
< Strict-Transport-Security: max-age=31536000
< X-XSS-Protection: 1; mode=block
<
WEBVTT
<< web vtt file stuff>>
* Connection #0 to host api.zoom.us left intact
So far the only time I can download a private recording on behalf of a user is when the webhook provides a download token, and a public one can only be downloaded by that token or without authentication.