Skip to content

Commit

Permalink
Merge pull request #475 from jrchamp/fix/oauth-scope-check
Browse files Browse the repository at this point in the history
oauth: Check required scopes; use POST data
  • Loading branch information
jrchamp authored Apr 29, 2023
2 parents b2515d2 + 5df19e4 commit 72b0425
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 25 deletions.
19 changes: 8 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ To connect to the Zoom APIs, this plugin requires an account-level app to be
created.

### Server-to-Server OAuth
To [create an account-level Server-to-Server OAuth app](https://marketplace.zoom.us/docs/guides/build/server-to-server-oauth-app), the `Server-to-server OAuth app`
permission is required.
To [create an account-level Server-to-Server OAuth app](https://developers.zoom.us/docs/internal-apps/create/), the `Server-to-server OAuth app`
permission is required. You should create a separate Server-to-Server OAuth app for each Moodle install.

The Server-to-Server OAuth app will generate a client ID, client secret and account ID.

Expand All @@ -23,7 +23,7 @@ At a minimum, the following scopes are required by this plugin:
- meeting:write:admin (Create/Update meetings)
- user:read:admin (Read user details)

Additional scopes are required for certain functionality:
Optional functionality can be enabled by granting additional scopes:

- Reports for meetings / webinars
- dashboard_meetings:read:admin (Business accounts and higher)
Expand All @@ -43,13 +43,12 @@ Additional scopes are required for certain functionality:
JWT will be deprecated in June 2023. To create an account-level JWT app the 'JWT' permission is
required.

See https://marketplace.zoom.us/docs/guides/build/jwt-app. You will need to
create a JWT app and that will generate the API key and secret.
You will need to [create a JWT app](https://developers.zoom.us/docs/platform/build/jwt-app/) and that will generate the API key and secret.

## Installation

1. Install plugin to mod/zoom. More details at https://docs.moodle.org/en/Installing_plugins#Installing_a_plugin
2. Once you install the plugin you need to set the following settings to enable the plugin:
1. [Install plugin](https://docs.moodle.org/en/Installing_plugins#Installing_a_plugin) to the /mod/zoom folder in Moodle.
2. After installing the plugin, the following settings need to be configured to use the plugin:

- Zoom account ID (mod_zoom | accountid)
- Zoom client ID (mod_zoom | clientid)
Expand All @@ -60,13 +59,11 @@ JWT will be deprecated in June 2023. For a JWT app, you need to set the followin
- Zoom API key (mod_zoom | apikey)
- Zoom API secret (mod_zoom | apisecret)

Please note that the API key and secret is not the same as the LTI key/secret.
Please note that the API key and secret are not the same as the LTI key/secret.

If you get "Access token is expired" errors, make sure the date/time on your
server is properly synchronized with the time servers.

- Zoom home page URL (mod_zoom | zoomurl), Link to your organization's custom Zoom landing page.

## Changelog

v4.10.0
Expand Down Expand Up @@ -113,7 +110,7 @@ v4.8.0

- Feature: Support Server-to-Server OAuth app #387 (thanks @haietza, @mhughes2k)
- New settings `zoom/accountid`, `zoom/clientid`, `zoom/clientsecret`
- Reminder: You must [switch from JWT to Server-to-Server OAuth by June 2023](https://marketplace.zoom.us/docs/guides/build/jwt-app/jwt-faq/).
- Reminder: You must [switch from JWT to Server-to-Server OAuth by June 2023](https://developers.zoom.us/docs/internal-apps/jwt-faq/).
- Regression: Locked settings were not being applied #407 (thanks @krab-stik)
- Introduced in v4.7.0 while adding support for automatic recording.

Expand Down
48 changes: 34 additions & 14 deletions classes/webservice.php
Original file line number Diff line number Diff line change
Expand Up @@ -1043,38 +1043,58 @@ protected function get_access_token() {
private function oauth($cache) {
$curl = $this->get_curl_object();
$curl->setHeader('Authorization: Basic ' . base64_encode($this->clientid . ':' . $this->clientsecret));
$curl->setHeader('Content-Type: application/json');
$curl->setHeader('Accept: application/json');

// Force HTTP/1.1 to avoid HTTP/2 "stream not closed" issue.
$curl->setopt([
'CURLOPT_HTTP_VERSION' => CURL_HTTP_VERSION_1_1,
]);

$timecalled = time();
$response = $this->make_curl_call($curl, 'post',
'https://zoom.us/oauth/token?grant_type=account_credentials&account_id=' . $this->accountid, []);
$data = [
'grant_type' => 'account_credentials',
'account_id' => $this->accountid,
];
$response = $this->make_curl_call($curl, 'post', 'https://zoom.us/oauth/token', $data);

if ($curl->get_errno()) {
throw new moodle_exception('errorwebservice', 'mod_zoom', '', $curl->error);
}

$response = json_decode($response);
if (isset($response->access_token)) {
$token = $response->access_token;
$cache->set('accesstoken', $token);

if (isset($response->expires_in)) {
$expires = $response->expires_in + $timecalled;
} else {
$expires = 3599 + $timecalled;
}
if (empty($response->access_token)) {
throw new moodle_exception('errorwebservice', 'mod_zoom', '', get_string('zoomerr_no_access_token', 'mod_zoom'));
}

$requiredscopes = [
'meeting:read:admin',
'meeting:write:admin',
'user:read:admin',
];
$scopes = explode(' ', $response->scope);
$missingscopes = array_diff($requiredscopes, $scopes);

if (!empty($missingscopes)) {
$missingscopes = implode(', ', $missingscopes);
throw new moodle_exception('errorwebservice', 'mod_zoom', '', get_string('zoomerr_scopes', 'mod_zoom', $missingscopes));
}

$cache->set('expires', $expires);
$token = $response->access_token;

return $token;
if (isset($response->expires_in)) {
$expires = $response->expires_in + $timecalled;
} else {
throw new moodle_exception('errorwebservice', 'mod_zoom', '', get_string('zoomerr_no_access_token', 'zoom'));
$expires = 3599 + $timecalled;
}

$cache->set_many([
'accesstoken' => $token,
'expires' => $expires,
'scopes' => $scopes,
]);

return $token;
}

/**
Expand Down
1 change: 1 addition & 0 deletions lang/en/zoom.php
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@
$string['zoomerr_meetingnotfound'] = 'This meeting cannot be found on Zoom. You can <a href="{$a->recreate}">recreate it here</a> or <a href="{$a->delete}">delete it completely</a>.';
$string['zoomerr_meetingnotfound_info'] = 'This meeting cannot be found on Zoom. Please contact the meeting host if you have questions.';
$string['zoomerr_no_access_token'] = 'No access token returned';
$string['zoomerr_scopes'] = 'The Zoom OAuth configuration is missing these required scopes: {$a}';
$string['zoomerr_usernotfound'] = 'Unable to find your account on Zoom. If you are using Zoom for the first time, you must activate your Zoom account by logging into <a href="{$a}" target="_blank">{$a}</a>. Once you\'ve activated your Zoom account, reload this page and continue setting up your meeting. Else make sure your email on Zoom matches your email on this system.';
$string['zoomerr_alternativehostusernotfound'] = 'User {$a} was not found on Zoom.';
$string['zoomerr_viewrecordings_off'] = 'View Recordings is switched off, task cannot run';
Expand Down

0 comments on commit 72b0425

Please sign in to comment.