From 8090820480821ad03144e2e625abbc36a310c922 Mon Sep 17 00:00:00 2001 From: Giorgos Avgeris Date: Thu, 21 May 2020 14:16:56 +0300 Subject: [PATCH] Initial commit --- .gitignore | 2 ++ README.md | 44 +++++++++++++++++++++++++ lib/index.js | 5 +++ lib/profile.js | 29 +++++++++++++++++ lib/strategy.js | 81 +++++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 45 ++++++++++++++++++++++++++ package.json | 30 ++++++++++++++++++ 7 files changed, 236 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 lib/index.js create mode 100644 lib/profile.js create mode 100644 lib/strategy.js create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fd4f2b0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..437a450 --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +A simple [Passport](http://passportjs.org/) strategy for Zoom OAuth2. + +## Install + +npm install @giorgosavgeris/passport-zoom-oauth2 + +## Usage + +### Register the strategy + +```javascript +var ZoomStrategy = require('@giorgosavgeris/passport-zoom-oauth2').Strategy; + +passport.use(new ZoomStrategy({ + clientID: ZOOM_CLIENT_ID, + clientSecret: ZOOM_CLIENT_SECRET, + callbackURL: 'https://www.example.net/oauth/zoom/callback' + }, + function(accessToken, refreshToken, profile, done) { + User.findOrCreate(..., function (err, user) { + done(err, user); + }); + } +)); +``` + +### Authenticate requests + +```javascript +app.get('/auth/zoom', passport.authenticate('zoom', { state: 'pass_state_here' })); + +app.get( + '/auth/zoom/callback', + passport.authenticate('zoom', { failureRedirect: '/login' }), + function(req, res) { + // Successful authentication + res.redirect('/'); + } +); +``` + +## License + +This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info. diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..3377107 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,5 @@ +var Strategy = require('./strategy'); + +exports = module.exports = Strategy; + +exports.Strategy = Strategy; diff --git a/lib/profile.js b/lib/profile.js new file mode 100644 index 0000000..b3e11c8 --- /dev/null +++ b/lib/profile.js @@ -0,0 +1,29 @@ +/** + * Parse profile. + * + * @param {object|string} json + * @return {object} + * @access public + */ +exports.parse = function(json) { + if (typeof json === "string") { + json = JSON.parse(json); + } + + var profile = {}; + + profile.id = json.id; + + profile.displayName = json.first_name + " " + json.last_name; + profile.name = { familyName: json.last_name, givenName: json.first_name }; + + if (json.email) { + profile.emails = [{ value: json.email }]; + } + + if (json.pic_url) { + profile.photos = [{ value: json.pic_url }]; + } + + return profile; +}; diff --git a/lib/strategy.js b/lib/strategy.js new file mode 100644 index 0000000..dbaf6d9 --- /dev/null +++ b/lib/strategy.js @@ -0,0 +1,81 @@ +var util = require("util"); +var OAuth2Strategy = require("passport-oauth2"); +var InternalOAuthError = require("passport-oauth2").InternalOAuthError; +var Profile = require("./profile"); + +/** + * `Strategy` constructor. + * + * Options: + * - `clientID` Zoom application's App ID + * - `clientSecret` Zoom application's App Secret + * - `callbackURL` URL to which Zoom will redirect the user after granting authorization + * + * Examples: + * + * passport.use(new ZoomStrategy({ + * clientID: ZOOM_CLIENT_ID, + * clientSecret: ZOOM_CLIENT_SECRET, + * callbackURL: 'https://www.example.net/oauth/zoom/callback' + * }, + * function(accessToken, refreshToken, profile, done) { + * User.findOrCreate(..., function (err, user) { + * done(err, user); + * }); + * } + * )); + * + * @constructor + * @param {object} options + * @param {function} verify + * @access public + */ + */ +function Strategy(options, verify) { + options = options || {}; + + options.authorizationURL = options.authorizationURL || "https://zoom.us/oauth/authorize"; + options.tokenURL = options.tokenURL || "https://zoom.us/oauth/token"; + + OAuth2Strategy.call(this, options, verify); + + this.name = "zoom"; + this.options = options; + this._profileUrl = options.profileUrl || "https://api.zoom.us/v2/users/me"; +} + +// Inherit from `OAuth2Strategy` +util.inherits(Strategy, OAuth2Strategy); + +/** + * Retrieve user profile from Zoom. + * + * @param {string} accessToken + * @param {function} done + * @access protected + */ +Strategy.prototype.userProfile = function(accessToken, done) { + this._oauth2.get(this._profileUrl, accessToken, function(err, body, res) { + var json; + + if (err) { + throw new InternalOAuthError("Failed to fetch user profile", err); + } + + try { + json = JSON.parse(body); + } catch (ex) { + return done(new Error("Failed to parse user profile")); + } + + var profile = Profile.parse(json); + + profile.provider = "zoom"; + profile._raw = body; + profile._json = json; + + done(null, profile); + }); +}; + +module.exports = Strategy; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..bdd4618 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,45 @@ +{ + "name": "@giorgosavgeris/passport-zoom-oauth2", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" + }, + "oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE=" + }, + "passport-oauth2": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.5.0.tgz", + "integrity": "sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ==", + "requires": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" + }, + "uid2": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", + "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..285c25c --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "@giorgosavgeris/passport-zoom-oauth2", + "version": "1.0.0", + "description": "Passport Strategy for Zoom OAuth 2.0", + "main": "./lib", + "directories": { + "lib": "lib" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/giorgosavgeris/passport-zoom-oauth2.git" + }, + "keywords": [ + "passport", + "zoom", + "oauth2" + ], + "author": "Giorgos Avgeris ", + "license": "MIT", + "bugs": { + "url": "https://github.com/giorgosavgeris/passport-zoom-oauth2/issues" + }, + "homepage": "https://github.com/giorgosavgeris/passport-zoom-oauth2#readme", + "dependencies": { + "passport-oauth2": "^1.5.0" + } +}