From 51587aebed41e2b66635c2e1a8b44a4b401231ff Mon Sep 17 00:00:00 2001 From: Michael Purnell Date: Tue, 26 Jun 2018 13:47:35 -0700 Subject: [PATCH 01/24] config file for example purposes --- config.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 config.js diff --git a/config.js b/config.js new file mode 100644 index 0000000..4885165 --- /dev/null +++ b/config.js @@ -0,0 +1,15 @@ +const env = process.env.NODE_ENV || 'development' + +//insert your API Key & Secret for each environment, keep this file local and never push it to repo. +const config = { + development :{ + APIKey : '', + APISecret : '' + }, + production:{ + APIKey : '', + APISecret : '' + } +}; + +module.exports = config[env] From ef38764f09531fa280b934deb7e2f94e1038dfbc Mon Sep 17 00:00:00 2001 From: Michael Purnell Date: Tue, 26 Jun 2018 13:49:29 -0700 Subject: [PATCH 02/24] added package.json --- package.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 0000000..874bf1c --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "zoom-api-jwt", + "version": "1.0.0", + "description": "Zoom API JWT Sample app", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Michael Purnell", + "license": "ISC", + "dependencies": { + "express": "^4.16.3", + "jsonwebtoken": "^8.3.0", + "request": "^2.87.0", + "request-promise": "^4.2.2" + } +} From dd862087fabd6606cbae12339f5a1986c308d386 Mon Sep 17 00:00:00 2001 From: Michael Purnell Date: Tue, 26 Jun 2018 13:51:11 -0700 Subject: [PATCH 03/24] add index.js --- index.js | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 index.js diff --git a/index.js b/index.js new file mode 100644 index 0000000..5c1f32d --- /dev/null +++ b/index.js @@ -0,0 +1,37 @@ +const jwt = require('jsonwebtoken'); +const config = require('./config'); +const rp = require('request-promise'); + +const payload = { + iss: config.APIKey, + exp: ((new Date()).getTime() + 5000) +}; + +//Automatically creates header, and returns JWT +const token = jwt.sign(payload, config.APISecret); + + +var options = { + uri: 'https://api.zoom.us/v2/users', //Zoom API + qs: { + status: 'active' // -> uri + '?status=active' + }, + auth: { + 'bearer': token + }, + headers: { + 'User-Agent': 'Zoom-api-Jwt-Request', + 'content-type': 'application/json' + }, + json: true // Automatically parses the JSON string in the response +}; + +//using request call with promise +rp(options) + .then(function (response) { + console.log('User has', response); + }) + .catch(function (err) { + // API call failed... + console.log('API call failed, reason ', err); + }); \ No newline at end of file From 55c60e37b8590dc25c3471c7c4b4ebdb2408b380 Mon Sep 17 00:00:00 2001 From: Michael Purnell Date: Tue, 10 Jul 2018 10:06:12 -0700 Subject: [PATCH 04/24] index.js file for sample oaith call --- index.js | 90 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/index.js b/index.js index 5c1f32d..b42ae13 100644 --- a/index.js +++ b/index.js @@ -1,37 +1,55 @@ -const jwt = require('jsonwebtoken'); +const express = require('express') +const app = express() const config = require('./config'); -const rp = require('request-promise'); - -const payload = { - iss: config.APIKey, - exp: ((new Date()).getTime() + 5000) -}; - -//Automatically creates header, and returns JWT -const token = jwt.sign(payload, config.APISecret); - - -var options = { - uri: 'https://api.zoom.us/v2/users', //Zoom API - qs: { - status: 'active' // -> uri + '?status=active' - }, - auth: { - 'bearer': token - }, - headers: { - 'User-Agent': 'Zoom-api-Jwt-Request', - 'content-type': 'application/json' - }, - json: true // Automatically parses the JSON string in the response -}; - -//using request call with promise -rp(options) - .then(function (response) { - console.log('User has', response); - }) - .catch(function (err) { - // API call failed... - console.log('API call failed, reason ', err); - }); \ No newline at end of file +const request = require('request'); + +app.get('/', (req, res) => { + + //this will check if the code parameter is in the url, if not the most likely case is that this is the user's inital visit to oauth and we need to redirect them (Step 1) + //if there is a code, it most likely means they were redirected here from zoom oauth screen + if (req.query.code) { + + let url = 'https://zoom.us/oauth/token?grant_type=authorization_code&code=' + req.query.code + '&redirect_uri=' + config.redirectUrl; + + //STEP 3 + //we need to exchange the code for a oauth token + request.post(url, function (error, response, body) { + + //the response should be a JSON payload + body = JSON.parse(body); + + //get refresh token + let refresh_token = body.refresh_token + + if (body.access_token) { + + //STEP 4 + //we can now use the access token to make API calls + request.get('https://api.zoom.us/v2/users/me', function (error, response, body) { + if(error){ + console.log('Error in API ', error) + }else{ + body = JSON.parse(body); + console.log('API call ', body); + //do something with the data + //this is most likely where you want to connect the zoom user to the calendly user, there will be a zoom user id + //add where you'll want to store the access token for future requests + } + }).auth(null, null, true, body.access_token); + + } else { + //handle error, something went wrong + } + + }).auth(config.clientID, config.clientSecret); + + return; + } + + //STEP 2 + //no code provided, so redirect the user to get the code + res.redirect('https://zoom.us/oauth/authorize?response_type=code&client_id=' + config.clientID + '&redirect_uri=' + config.redirectUrl); +}); + +app.listen(3000, () => console.log('Zoom api oauth sample app listening on port 3000!')) + \ No newline at end of file From ad466b38d9ec2b4d5791840bf68bcdb38f482898 Mon Sep 17 00:00:00 2001 From: Michael Purnell Date: Tue, 10 Jul 2018 10:06:28 -0700 Subject: [PATCH 05/24] added config.js file --- config.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/config.js b/config.js index 4885165..cb8352d 100644 --- a/config.js +++ b/config.js @@ -3,12 +3,14 @@ const env = process.env.NODE_ENV || 'development' //insert your API Key & Secret for each environment, keep this file local and never push it to repo. const config = { development :{ - APIKey : '', - APISecret : '' + clientID : '', + clientSecret : '', + redirectUrl : '' }, production:{ - APIKey : '', - APISecret : '' + clientID : '', + clientSecret : '', + redirectUrl: '' } }; From 99cc03675a0c5022d282abd4290f35da982440d5 Mon Sep 17 00:00:00 2001 From: Michael Purnell Date: Tue, 10 Jul 2018 10:09:50 -0700 Subject: [PATCH 06/24] added package.json --- package.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/package.json b/package.json index 874bf1c..15bb630 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,6 @@ "license": "ISC", "dependencies": { "express": "^4.16.3", - "jsonwebtoken": "^8.3.0", - "request": "^2.87.0", - "request-promise": "^4.2.2" + "request": "^2.87.0" } } From e3039b142f226a6af1a1d905f4ae3bcb96fe9c0a Mon Sep 17 00:00:00 2001 From: Michael Purnell Date: Tue, 10 Jul 2018 10:18:42 -0700 Subject: [PATCH 07/24] add readme file --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 66b4806..bd8c299 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ # zoom-jwt +# zoom-oauth-sample-app From c63b62368d4df41d40ac988696faa0b11389f2b8 Mon Sep 17 00:00:00 2001 From: michaelZoomDA <39344486+michaelZoomDA@users.noreply.github.com> Date: Tue, 10 Jul 2018 10:20:05 -0700 Subject: [PATCH 08/24] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index bd8c299..bd38524 100644 --- a/README.md +++ b/README.md @@ -1,2 +1 @@ -# zoom-jwt # zoom-oauth-sample-app From 47bd20a9e26d4800365f6d0c1afcf05dab66436b Mon Sep 17 00:00:00 2001 From: michaelZoomDA <39344486+michaelZoomDA@users.noreply.github.com> Date: Tue, 10 Jul 2018 10:24:21 -0700 Subject: [PATCH 09/24] Update README.md --- README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/README.md b/README.md index bd38524..5b9200a 100644 --- a/README.md +++ b/README.md @@ -1 +1,41 @@ # zoom-oauth-sample-app + +> This is a sample app that uses oauth to call Zoom's API. It uses the request node module to make http calls. + +## Getting Started + +### Install + +Clone the repo using git clone. +` git clone https://github.com/zoom/zoom-oath-sample-app.git` + +> Install the dependent node modules. +``` npm install ``` + +### Quick Start + + + +> In the config.js file, input your clientID, clientSecret, and redirectUrl. +``` + const config = { + development :{ + clientID : '', + clientSecret : '', + redirectUrl : '' + }, + production:{ + clientID : '', + clientSecret : '', + redirectUrl: '' + } +}; +``` +> Set your environment varaibles. +` export NODE_NEV=[environment name] (e.g. export NODE_NEV=production) ` + +> Start the node app. +` node.index.js ` + +### For more Information about Zooms API and JWT +Documentation is available on the [Zoom Oauth docs site](https://marketplace.zoom.us/docs/oauth-with-zoom) From 38cdacd0b742de182674500fd81c190a7b503305 Mon Sep 17 00:00:00 2001 From: michaelZoomDA <39344486+michaelZoomDA@users.noreply.github.com> Date: Tue, 10 Jul 2018 10:55:41 -0700 Subject: [PATCH 10/24] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b9200a..975fab6 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Clone the repo using git clone. -> In the config.js file, input your clientID, clientSecret, and redirectUrl. +> In the config.js file, input your clientID, clientSecret, and redirectUrl. Please note to test locally the redirectUrl can't be localhost, you can use ngrok or a similar service instead. ``` const config = { development :{ @@ -37,5 +37,8 @@ Clone the repo using git clone. > Start the node app. ` node.index.js ` +> Go to localhost:3000 in the browser + + ### For more Information about Zooms API and JWT Documentation is available on the [Zoom Oauth docs site](https://marketplace.zoom.us/docs/oauth-with-zoom) From bc8df82510637eb1b489677944888fc941d43933 Mon Sep 17 00:00:00 2001 From: michaelZoomDA <39344486+michaelZoomDA@users.noreply.github.com> Date: Thu, 29 Nov 2018 10:46:59 -0800 Subject: [PATCH 11/24] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 975fab6..686ce87 100644 --- a/README.md +++ b/README.md @@ -42,3 +42,6 @@ Clone the repo using git clone. ### For more Information about Zooms API and JWT Documentation is available on the [Zoom Oauth docs site](https://marketplace.zoom.us/docs/oauth-with-zoom) + +## Support +For any questions or issues, please visit our new Community Support Forum at https://devforum.zoom.us/ From d44022f6ecc3b524c00eed209034a6ebb56a0d81 Mon Sep 17 00:00:00 2001 From: Shrijana Ghimire Date: Mon, 1 Apr 2019 10:42:19 -0700 Subject: [PATCH 12/24] Changed the development environment to production --- config.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/config.js b/config.js index cb8352d..bb0684b 100644 --- a/config.js +++ b/config.js @@ -1,16 +1,16 @@ -const env = process.env.NODE_ENV || 'development' +const env = process.env.NODE_ENV || 'production' //insert your API Key & Secret for each environment, keep this file local and never push it to repo. const config = { development :{ - clientID : '', - clientSecret : '', - redirectUrl : '' + clientID : 'owl34V64TVrX2gYAKBUvQ', + clientSecret : '4YZ2XLTfQMmt6J1htGB33T5PMEy2XwBT', + redirectUrl : 'https://080b95ee.ngrok.io' }, production:{ - clientID : '', - clientSecret : '', - redirectUrl: '' + clientID : '7W1DsbORUSYvRB1M9C0Q', + clientSecret : 'YkPqAqaVRWZwrPbCgIvUEyZQbe9UO6jp', + redirectUrl: 'https://080b95ee.ngrok.io' } }; From bda39a17f2b178d51dfbb4298ee58739e092f6df Mon Sep 17 00:00:00 2001 From: Shrijana Ghimire Date: Mon, 1 Apr 2019 10:43:11 -0700 Subject: [PATCH 13/24] Display the response in browser --- index.js | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index b42ae13..1c8fda5 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ const express = require('express') const app = express() const config = require('./config'); const request = require('request'); +var resp; app.get('/', (req, res) => { @@ -17,6 +18,18 @@ app.get('/', (req, res) => { //the response should be a JSON payload body = JSON.parse(body); + //html for displaying response in the browser + var title1 ='

Your access token:

' + var title2 ='

Your refresh token:

' + var result1 = title1 + '
' + body.access_token + '
'; + var result2 = title2 + '
' + body.refresh_token + '
'; + + var title ='

User\'s information:

' + //Prettify the JSON format using pre tag and JSON.stringify + + //print access_token in the browser + //res.send(body.access_token); + console.log(body.access_token); //get refresh token let refresh_token = body.refresh_token @@ -30,11 +43,14 @@ app.get('/', (req, res) => { console.log('Error in API ', error) }else{ body = JSON.parse(body); + //display response in console console.log('API call ', body); - //do something with the data - //this is most likely where you want to connect the zoom user to the calendly user, there will be a zoom user id - //add where you'll want to store the access token for future requests + //display response in browser + var result = title + '
'+JSON.stringify(body, null, 2)+ '
' + res.send(result1 + '
' + result2 + '
' + result); + } + }).auth(null, null, true, body.access_token); } else { From 1e10fbb82aa6e2d160cca32e780410135044e603 Mon Sep 17 00:00:00 2001 From: ShrijanaCodes <29689264+ShrijanaCodes@users.noreply.github.com> Date: Mon, 1 Apr 2019 11:46:11 -0700 Subject: [PATCH 14/24] Removed credentials I pushed the credentials of my app by mistake. Removed it now. --- config.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/config.js b/config.js index bb0684b..64f2d3c 100644 --- a/config.js +++ b/config.js @@ -3,14 +3,14 @@ const env = process.env.NODE_ENV || 'production' //insert your API Key & Secret for each environment, keep this file local and never push it to repo. const config = { development :{ - clientID : 'owl34V64TVrX2gYAKBUvQ', - clientSecret : '4YZ2XLTfQMmt6J1htGB33T5PMEy2XwBT', - redirectUrl : 'https://080b95ee.ngrok.io' + clientID : '', + clientSecret : '', + redirectUrl : '' }, production:{ - clientID : '7W1DsbORUSYvRB1M9C0Q', - clientSecret : 'YkPqAqaVRWZwrPbCgIvUEyZQbe9UO6jp', - redirectUrl: 'https://080b95ee.ngrok.io' + clientID : '', + clientSecret : '', + redirectUrl: '' } }; From 2af3078f4e23fa2c563370d62bbedcd603d3db15 Mon Sep 17 00:00:00 2001 From: Michael D Harrington Date: Tue, 11 Jun 2019 14:35:28 -0600 Subject: [PATCH 15/24] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 686ce87..5239869 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,8 @@ Clone the repo using git clone. > Go to localhost:3000 in the browser -### For more Information about Zooms API and JWT -Documentation is available on the [Zoom Oauth docs site](https://marketplace.zoom.us/docs/oauth-with-zoom) +### For more Information about Zooms API and OAuth +Documentation is available on the [Zoom Oauth docs site](https://marketplace.zoom.us/docs/guides/authorization/oauth) ## Support For any questions or issues, please visit our new Community Support Forum at https://devforum.zoom.us/ From 25a4cb73f342958f4403da9bed4f660fccb33fd5 Mon Sep 17 00:00:00 2001 From: "g.turumtaev" Date: Thu, 5 Dec 2019 17:08:34 +0300 Subject: [PATCH 16/24] one little correction --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5239869..592ae21 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ ### Install Clone the repo using git clone. -` git clone https://github.com/zoom/zoom-oath-sample-app.git` +` git clone https://github.com/zoom/zoom-oauth-sample-app.git` > Install the dependent node modules. ``` npm install ``` From ecded0134f5a4e95ea03f5009f3f1a088cd57c4f Mon Sep 17 00:00:00 2001 From: michaeldharrington Date: Tue, 3 Mar 2020 14:32:53 -0700 Subject: [PATCH 17/24] v2 init --- .gitignore | 4 ++ config.js | 17 -------- index.js | 114 ++++++++++++++++++++++++++++++--------------------- package.json | 26 ++++++++---- 4 files changed, 91 insertions(+), 70 deletions(-) create mode 100644 .gitignore delete mode 100644 config.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4f6f8d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules +.env +package-lock.json + diff --git a/config.js b/config.js deleted file mode 100644 index 64f2d3c..0000000 --- a/config.js +++ /dev/null @@ -1,17 +0,0 @@ -const env = process.env.NODE_ENV || 'production' - -//insert your API Key & Secret for each environment, keep this file local and never push it to repo. -const config = { - development :{ - clientID : '', - clientSecret : '', - redirectUrl : '' - }, - production:{ - clientID : '', - clientSecret : '', - redirectUrl: '' - } -}; - -module.exports = config[env] diff --git a/index.js b/index.js index 1c8fda5..5fb452a 100644 --- a/index.js +++ b/index.js @@ -1,71 +1,93 @@ +// Bring in environment secrets through dotenv +require('dotenv/config') + +// Use the request module to make HTTP requests from Node +const request = require('request') + +// Run the express app const express = require('express') const app = express() -const config = require('./config'); -const request = require('request'); -var resp; + app.get('/', (req, res) => { - //this will check if the code parameter is in the url, if not the most likely case is that this is the user's inital visit to oauth and we need to redirect them (Step 1) - //if there is a code, it most likely means they were redirected here from zoom oauth screen + // Step 1: + // Check if the code parameter is in the url + // if an authorization code is available, the user has most likely been redirected from Zoom OAuth + // if not, the user needs to be redirected to Zoom OAuth to authorize + if (req.query.code) { - let url = 'https://zoom.us/oauth/token?grant_type=authorization_code&code=' + req.query.code + '&redirect_uri=' + config.redirectUrl; + // Step 3: + // Request an access token using the auth code + + let url = 'https://zoom.us/oauth/token?grant_type=authorization_code&code=' + req.query.code + '&redirect_uri=' + process.env.redirectURL; - //STEP 3 - //we need to exchange the code for a oauth token - request.post(url, function (error, response, body) { + request.post(url, (error, response, body) => { - //the response should be a JSON payload + // Parse response to JSON body = JSON.parse(body); - //html for displaying response in the browser - var title1 ='

Your access token:

' - var title2 ='

Your refresh token:

' - var result1 = title1 + '
' + body.access_token + '
'; - var result2 = title2 + '
' + body.refresh_token + '
'; - - var title ='

User\'s information:

' - //Prettify the JSON format using pre tag and JSON.stringify - - //print access_token in the browser - //res.send(body.access_token); - console.log(body.access_token); - - //get refresh token - let refresh_token = body.refresh_token + + // Logs your access and refresh tokens in the browser + console.log(`access_token: ${body.access_token}`); + console.log(`refresh_token: ${body.refresh_token}`); if (body.access_token) { - //STEP 4 - //we can now use the access token to make API calls - request.get('https://api.zoom.us/v2/users/me', function (error, response, body) { - if(error){ - console.log('Error in API ', error) - }else{ + // Step 4: + // We can now use the access token to authenticate API calls + + // Send a request to get your user information using the /me context + // The `/me` context restricts an API call to the user the token belongs to + // This helps make calls to user-specific endpoints instead of storing the userID + + request.get('https://api.zoom.us/v2/users/me', (error, response, body) => { + if (error) { + console.log('API Response Error: ', error) + } else { body = JSON.parse(body); - //display response in console + // Display response in console console.log('API call ', body); - //display response in browser - var result = title + '
'+JSON.stringify(body, null, 2)+ '
' - res.send(result1 + '
' + result2 + '
' + result); - + // Display response in browser + var JSONResponse = '
' + JSON.stringify(body, null, 2) + '
' + res.send(` + +
+
+ User photo +
+ Hello World! +

${body.first_name} ${body.last_name}

+

${body.role_name}, ${body.company}

+
+
+
+

JSON Response:

+ + API Reference + + ${JSONResponse} +
+
+ `); } - }).auth(null, null, true, body.access_token); - + } else { - //handle error, something went wrong + // Handle errors, something's gone wrong! } - }).auth(config.clientID, config.clientSecret); + }).auth(process.env.clientID, process.env.clientSecret); return; + } - //STEP 2 - //no code provided, so redirect the user to get the code - res.redirect('https://zoom.us/oauth/authorize?response_type=code&client_id=' + config.clientID + '&redirect_uri=' + config.redirectUrl); -}); + // Step 2: + // If no authorization code is available, redirect to Zoom OAuth to authorize + res.redirect('https://zoom.us/oauth/authorize?response_type=code&client_id=' + process.env.clientID + '&redirect_uri=' + process.env.redirectURL) +}) -app.listen(3000, () => console.log('Zoom api oauth sample app listening on port 3000!')) - \ No newline at end of file +app.listen(4000, () => console.log(`Zoom Hello World app listening at PORT: 4000`)) \ No newline at end of file diff --git a/package.json b/package.json index 15bb630..0d833fc 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,27 @@ { - "name": "zoom-api-jwt", + "name": "zoom-oauth-hello-world", "version": "1.0.0", - "description": "Zoom API JWT Sample app", + "description": "Hello World app using an OAuth Marketplace App client ID and Secret to create an OAuth token, used to call the Zoom API.", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "start": "nodemon index.js" }, - "author": "Michael Purnell", + "keywords": [ + "Zoom", + "Zoom App Marketplace", + "OAuth", + "Hello", + "World" + ], + "author": "Michael Harrington", "license": "ISC", "dependencies": { - "express": "^4.16.3", - "request": "^2.87.0" + "dotenv": "^8.2.0", + "express": "^4.17.1", + "request": "^2.88.0" + }, + "devDependencies": { + "nodemon": "^2.0.2" } -} +} \ No newline at end of file From 085dd8c2ab3d0cea2dfbd3fe88bbf433addd45e9 Mon Sep 17 00:00:00 2001 From: michaeldharrington Date: Tue, 3 Mar 2020 14:51:02 -0700 Subject: [PATCH 18/24] update readme --- README.md | 147 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 115 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 592ae21..8a97a66 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,130 @@ -# zoom-oauth-sample-app +# Zoom OAuth Hello World -> This is a sample app that uses oauth to call Zoom's API. It uses the request node module to make http calls. +This is a Hello World app using an OAuth Marketplace App client ID and Secret to create an OAuth token, used to call the Zoom API. -## Getting Started +Follow allong with relevant Zoom OAuth documentation as we set this up: -### Install +1. [OAuth with Zoom](https://marketplace.zoom.us/docs/guides/authorization/oauth/oauth-with-zoom) +2. [Create an OAuth App](https://marketplace.zoom.us/docs/guides/getting-started/app-types/create-oauth-app) -Clone the repo using git clone. -` git clone https://github.com/zoom/zoom-oauth-sample-app.git` +## Setup app locally -> Install the dependent node modules. -``` npm install ``` +Clone and install the app and it's dependencies. We'll be using [Express](https://www.npmjs.com/package/express) for a basic Node.js server, [dotenv](https://www.npmjs.com/package/dotenv) for our credentials, [requests](https://www.npmjs.com/package/requests) to make HTTP requests and [nodemon](https://www.npmjs.com/package/nodemon) for easier development refreshing. -### Quick Start +```bash +git clone https://github.com/zoom/zoom-oauth-sample-app.git +``` +```bash +cd zoom-oauth-sample-app && npm install +``` +Run server: -> In the config.js file, input your clientID, clientSecret, and redirectUrl. Please note to test locally the redirectUrl can't be localhost, you can use ngrok or a similar service instead. -``` - const config = { - development :{ - clientID : '', - clientSecret : '', - redirectUrl : '' - }, - production:{ - clientID : '', - clientSecret : '', - redirectUrl: '' - } -}; +```bash +npm run start ``` -> Set your environment varaibles. -` export NODE_NEV=[environment name] (e.g. export NODE_NEV=production) ` -> Start the node app. -` node.index.js ` +### Setup dotenv +Create a `.env` file in which to store your PORT, access credentials, and Redirect URL. + +```bash +touch .env +``` + +Copy the following into this file, which we'll add your own values to: + +``` +clientID= +clientSecret= +redirectURL= +``` + +> Remember: Never share or store your client credentials publicly. Your `.env` is included in the `.gitignore` file to ensure these files won't be included in a git workflow. + +## Install [ngrok](https://ngrok.com/) + +During the OAuth flow, Zoom will need to know where to redirect a user after they have successfully authenticated and installed the app on their account. + +For this we'll use [ngrok](https://ngrok.com/download), which creates a public link to a localhost development server. + +Download and install ngrok, then follow the steps to connect your account. + +Run ngrok on the same localhost port (4000): + +```bash +~/./ngrok http 4000 +``` + +This will generate a forwarding link. Copy this and add it into your `.env` file as the `redirectURL`. Keep ngrok running! If the linkage disconnects, we'll need to readd a new redirectURL. + +Example: + +``` +redirectURL=https://12345678.ngrok.io +``` + + +## Create an OAuth App on the Zoom App Marketplace + +Sign in to the Zoom App Marketplace and [Create an OAuth App](https://marketplace.zoom.us/develop/create?source=devdocs). + +Creating this app will generate your OAuth Client ID and Secret needed to install on your account and get an access token. + +Copy these credentials and add them to your `.env` file. + +Example: + +``` +clientID=1234567890 +clientSecret=13245678901234567890 +redirectURL=https://12345678.ngrok.io +``` + +### Add your Redirect URL from ngrok to your app + +Copy and paste your ngrok link into the Redirect URL for OAuth field, then click Continue. + +### Fill out app information. + +To install the app, we'll need to add some quick info on the app. Add in the following: + +1. *Short Description* +2. *Long Description* +3. *Developer Name* +4. *Developer Contact* + + +> We won't need to add any Features to our app, but if we wanted to enable [Event Subscriptions](https://marketplace.zoom.us/docs/guides/tools-resources/webhooks#event-subscriptions) through Zoom Webhooks, we'd do it here. + +### Add Scopes + +OAuth is used to guarantee that an app only has access to the data you authorize. If an app does not have the required scope, it cannot call the API on your behalf. + +To request data,we'll need to add a Scope to our app. The only data we need is for a user's profile information. Click **+ Add Scopes** and add *"View your user information"* (`user:read`). Click **Done** and continue on to the Installation page. + +## Install app + +With our app running on `localhost:4000`, a live redirectURL from ngrok, and proper scopes requested we can now install the app on our account. + +Click **Install** or copy the Installation URL into a browser. + +Zoom will now ask you to authorize the app on your account. Note that the app is requesting only the scope we've added. + +> If you're not the admin on your Zoom account, the admin might require you to ask them for pre-approval to install this app. Submit a request to get this pre-approved by your account admin. + +Authorizing the app will send you to the Redirect URL of your app, linked to our app running on localhost:4000. + +Your express server will log your access_token, refresh_token and the API call response to get your user information. + +In your browser, you'll see your Zoom profile data, with a JSON object showing the response. This API request was made using an `access_token` specific to this app and scopes. + +## Next steps -> Go to localhost:3000 in the browser +Follow our documentation on OAuth with Zoom for more information on building a user-level app on the Zoom App Marketplace. +Code happy! -### For more Information about Zooms API and OAuth -Documentation is available on the [Zoom Oauth docs site](https://marketplace.zoom.us/docs/guides/authorization/oauth) +## Support +For any questions or support using this sample app, visit our Developer Forum at https://devforum.zoom.us -## Support -For any questions or issues, please visit our new Community Support Forum at https://devforum.zoom.us/ From b81f5e9b994ecd5b98e3136e19bebec9995cc934 Mon Sep 17 00:00:00 2001 From: Tommy Gaessler Date: Thu, 3 Jun 2021 13:37:03 -0600 Subject: [PATCH 19/24] updated support text --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8a97a66..15a6a07 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,6 @@ Follow our documentation on OAuth with Zoom for more information on building a u Code happy! -## Support -For any questions or support using this sample app, visit our Developer Forum at https://devforum.zoom.us +## Need help? +If you're looking for help, try [Developer Support](https://devsupport.zoom.us) or our [Developer Forum](https://devforum.zoom.us). Priority support is also available with [Premier Developer Support](https://zoom.us/docs/en-us/developer-support-plans.html) plans. From 5d6696dae9f330ce305345bc9d583edee2cd2a74 Mon Sep 17 00:00:00 2001 From: Kassian Wren Date: Fri, 4 Jun 2021 10:49:00 -0500 Subject: [PATCH 20/24] License and CoC fix --- CONTRIBUTING.md | 133 ++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE.md | 1 + README.md | 2 + 3 files changed, 136 insertions(+) create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..36fca7a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,133 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[INSERT CONTACT METHOD]. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available +at [https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..821ed35 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1 @@ +Use of this sample app is subject to our [Terms of Use](https://zoom.us/docs/en-us/zoom_api_license_and_tou.html) \ No newline at end of file diff --git a/README.md b/README.md index 15a6a07..00a5747 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Zoom OAuth Hello World +Use of this sample app is subject to our [Terms of Use](https://zoom.us/docs/en-us/zoom_api_license_and_tou.html) + This is a Hello World app using an OAuth Marketplace App client ID and Secret to create an OAuth token, used to call the Zoom API. Follow allong with relevant Zoom OAuth documentation as we set this up: From 19a38f130f537b3ea0f34c28e12aa24efd9e4f66 Mon Sep 17 00:00:00 2001 From: Ojus M Save Date: Fri, 4 Mar 2022 14:16:21 -0800 Subject: [PATCH 21/24] V1 initial commit Initial commit --- .DS_Store | Bin 0 -> 6148 bytes index.js | 27 ++++++++++----------------- package.json | 4 ++-- 3 files changed, 12 insertions(+), 19 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..6feef0890fed7dec6fe938c06880a4ffad5ca34d GIT binary patch literal 6148 zcmeHK%Sr=55UgGUCK@oF^teYa3ZA{Jc_0B3!RT4@5K&`RkbuX%_%VKsAL9pT^~?~= zB)JBZZs@L=*{W1t40Ojk@Q3`?YOhIgc`DaNcA)spv!w~H6_F~k$&J@XIA%3a^xDch6z zyOpnKhH5m!3SQEWcok~d!YP{QEPux2Gh(o7W(t@BrofsM;GV5k-u7tG6fgx$ftdpO zeMsqwS-`@h`*bk4BLK0)VP|aXPoi?tfLXx8Bd^fJQ;D7`;fNug&ha$lWdRG1o(>6z z4+)heoKVD7=lrQlhh!ctngXW4yaF4(Thsl&wfg)&PqLmVU<&*z1*FvMHS2t&u(vKe wobI(L{g$q#d4 { - // Step 1: - // Check if the code parameter is in the url - // if an authorization code is available, the user has most likely been redirected from Zoom OAuth - // if not, the user needs to be redirected to Zoom OAuth to authorize - - if (req.query.code) { - - // Step 3: + // Step 1: // Request an access token using the auth code - let url = 'https://zoom.us/oauth/token?grant_type=authorization_code&code=' + req.query.code + '&redirect_uri=' + process.env.redirectURL; + let url = 'https://zoom.us/oauth/token?grant_type=account_credentials&account_id=' + process.env.account_id; request.post(url, (error, response, body) => { // Parse response to JSON body = JSON.parse(body); - // Logs your access and refresh tokens in the browser + // Logs your access tokens in the browser console.log(`access_token: ${body.access_token}`); - console.log(`refresh_token: ${body.refresh_token}`); - + if (body.access_token) { // Step 4: @@ -41,7 +33,8 @@ app.get('/', (req, res) => { // The `/me` context restricts an API call to the user the token belongs to // This helps make calls to user-specific endpoints instead of storing the userID - request.get('https://api.zoom.us/v2/users/me', (error, response, body) => { + request.get('https://api.zoom.us/v2/users/' + process.env.user_id, (error, response, body) => { + console.log(`User Id is ${process.env.user_id}`) if (error) { console.log('API Response Error: ', error) } else { @@ -82,12 +75,12 @@ app.get('/', (req, res) => { }).auth(process.env.clientID, process.env.clientSecret); return; - - } + + }) // Step 2: // If no authorization code is available, redirect to Zoom OAuth to authorize - res.redirect('https://zoom.us/oauth/authorize?response_type=code&client_id=' + process.env.clientID + '&redirect_uri=' + process.env.redirectURL) -}) + // res.redirect('https://zoom.us/oauth/authorize?response_type=code&client_id=' + process.env.clientID + '&redirect_uri=' + process.env.redirectURL) +//}) app.listen(4000, () => console.log(`Zoom Hello World app listening at PORT: 4000`)) \ No newline at end of file diff --git a/package.json b/package.json index 0d833fc..7107d7a 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,6 @@ "request": "^2.88.0" }, "devDependencies": { - "nodemon": "^2.0.2" + "nodemon": "^2.0.15" } -} \ No newline at end of file +} From e5cde543e6c24c2259df1d1d3c3423fb02abc6cf Mon Sep 17 00:00:00 2001 From: Ojus M Save Date: Fri, 4 Mar 2022 14:18:22 -0800 Subject: [PATCH 22/24] Revert "V1 initial commit" This reverts commit 19a38f130f537b3ea0f34c28e12aa24efd9e4f66. --- .DS_Store | Bin 6148 -> 0 bytes index.js | 27 +++++++++++++++++---------- package.json | 4 ++-- 3 files changed, 19 insertions(+), 12 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 6feef0890fed7dec6fe938c06880a4ffad5ca34d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%Sr=55UgGUCK@oF^teYa3ZA{Jc_0B3!RT4@5K&`RkbuX%_%VKsAL9pT^~?~= zB)JBZZs@L=*{W1t40Ojk@Q3`?YOhIgc`DaNcA)spv!w~H6_F~k$&J@XIA%3a^xDch6z zyOpnKhH5m!3SQEWcok~d!YP{QEPux2Gh(o7W(t@BrofsM;GV5k-u7tG6fgx$ftdpO zeMsqwS-`@h`*bk4BLK0)VP|aXPoi?tfLXx8Bd^fJQ;D7`;fNug&ha$lWdRG1o(>6z z4+)heoKVD7=lrQlhh!ctngXW4yaF4(Thsl&wfg)&PqLmVU<&*z1*FvMHS2t&u(vKe wobI(L{g$q#d4 { - // Step 1: + // Step 1: + // Check if the code parameter is in the url + // if an authorization code is available, the user has most likely been redirected from Zoom OAuth + // if not, the user needs to be redirected to Zoom OAuth to authorize + + if (req.query.code) { + + // Step 3: // Request an access token using the auth code - let url = 'https://zoom.us/oauth/token?grant_type=account_credentials&account_id=' + process.env.account_id; + let url = 'https://zoom.us/oauth/token?grant_type=authorization_code&code=' + req.query.code + '&redirect_uri=' + process.env.redirectURL; request.post(url, (error, response, body) => { // Parse response to JSON body = JSON.parse(body); - // Logs your access tokens in the browser + // Logs your access and refresh tokens in the browser console.log(`access_token: ${body.access_token}`); - + console.log(`refresh_token: ${body.refresh_token}`); + if (body.access_token) { // Step 4: @@ -33,8 +41,7 @@ app.get('/', (req, res) => { // The `/me` context restricts an API call to the user the token belongs to // This helps make calls to user-specific endpoints instead of storing the userID - request.get('https://api.zoom.us/v2/users/' + process.env.user_id, (error, response, body) => { - console.log(`User Id is ${process.env.user_id}`) + request.get('https://api.zoom.us/v2/users/me', (error, response, body) => { if (error) { console.log('API Response Error: ', error) } else { @@ -75,12 +82,12 @@ app.get('/', (req, res) => { }).auth(process.env.clientID, process.env.clientSecret); return; - - }) + + } // Step 2: // If no authorization code is available, redirect to Zoom OAuth to authorize - // res.redirect('https://zoom.us/oauth/authorize?response_type=code&client_id=' + process.env.clientID + '&redirect_uri=' + process.env.redirectURL) -//}) + res.redirect('https://zoom.us/oauth/authorize?response_type=code&client_id=' + process.env.clientID + '&redirect_uri=' + process.env.redirectURL) +}) app.listen(4000, () => console.log(`Zoom Hello World app listening at PORT: 4000`)) \ No newline at end of file diff --git a/package.json b/package.json index 7107d7a..0d833fc 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,6 @@ "request": "^2.88.0" }, "devDependencies": { - "nodemon": "^2.0.15" + "nodemon": "^2.0.2" } -} +} \ No newline at end of file From b7c7633011a15cb44109cdf7b99e755dd7d1f569 Mon Sep 17 00:00:00 2001 From: ffedoroff Date: Wed, 13 Apr 2022 17:43:29 +0600 Subject: [PATCH 23/24] fix typo in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 00a5747..a3e4ea1 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Use of this sample app is subject to our [Terms of Use](https://zoom.us/docs/en- This is a Hello World app using an OAuth Marketplace App client ID and Secret to create an OAuth token, used to call the Zoom API. -Follow allong with relevant Zoom OAuth documentation as we set this up: +Follow along with relevant Zoom OAuth documentation as we set this up: 1. [OAuth with Zoom](https://marketplace.zoom.us/docs/guides/authorization/oauth/oauth-with-zoom) 2. [Create an OAuth App](https://marketplace.zoom.us/docs/guides/getting-started/app-types/create-oauth-app) From dc1ae8e4d2cb7d377bc23074354063fa09a5694b Mon Sep 17 00:00:00 2001 From: ffedoroff Date: Wed, 13 Apr 2022 17:52:09 +0600 Subject: [PATCH 24/24] fix another typo in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a3e4ea1..2ad7a7f 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Run ngrok on the same localhost port (4000): ~/./ngrok http 4000 ``` -This will generate a forwarding link. Copy this and add it into your `.env` file as the `redirectURL`. Keep ngrok running! If the linkage disconnects, we'll need to readd a new redirectURL. +This will generate a forwarding link. Copy this and add it into your `.env` file as the `redirectURL`. Keep ngrok running! If the linkage disconnects, we'll need to read a new redirectURL. Example: