From 26735803e28884e526e1996f59372b4ae952450b Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Tue, 9 Jan 2024 17:18:01 -0800 Subject: [PATCH 01/13] manual oauth wip --- index.js | 54 +++++++------ package-lock.json | 200 +++------------------------------------------- package.json | 3 +- 3 files changed, 39 insertions(+), 218 deletions(-) diff --git a/index.js b/index.js index bcedea9..ea51bdf 100644 --- a/index.js +++ b/index.js @@ -2,7 +2,8 @@ require('dotenv').config(); const express = require('express'); const app = express(); const axios = require('axios'); -const ClientOAuth2 = require('client-oauth2') +const base64url = require('base64url'); +const crypto = require('crypto'); app.set('view engine', 'ejs'); app.use(express.urlencoded({ extended: true })); @@ -28,16 +29,6 @@ const token_request = { const host = process.env.RELAY_HOST -const oauthConfig = { - clientId: process.env.OAUTH_CLIENT_ID, - clientSecret: process.env.OAUTH_SECRET, - accessTokenUri: process.env.OAUTH_TOKEN_URI, - authorizationUri: process.env.OAUTH_AUTH_URI, - redirectUri: process.env.OAUTH_REDIRECT_URI -} - -const oauthClient = new ClientOAuth2(oauthConfig) - async function apiRequest(endpoint, payload = {}, method = 'POST') { var url = `https://${process.env.SIGNALWIRE_SPACE}${endpoint}` @@ -51,40 +42,53 @@ async function apiRequest(endpoint, payload = {}, method = 'POST') { } app.get('/', async (req, res) => { - const response = await apiRequest('/api/fabric/subscribers/tokens', token_request) + // const response = await apiRequest('/api/fabric/subscribers/tokens', token_request) res.render('index', { host, - token: response.token, + token: '', destination: process.env.DEFAULT_DESTINATION, firebaseConfig: FIREBASE_CONFIG, }); }); app.get('/minimal', async (req, res) => { - const response = await apiRequest('/api/fabric/subscribers/tokens', token_request) + // const response = await apiRequest('/api/fabric/subscribers/tokens', token_request) res.render('minimal', { host, - token: response.token, + token: '', destination: process.env.DEFAULT_DESTINATION, firebaseConfig: FIREBASE_CONFIG, }); }); app.get('/oauth', (req, res) => { - const authorizationUri = oauthClient.code.getUri() + const authEndpoint = process.env.OAUTH_AUTH_URI; + const verifier = base64url(crypto.pseudoRandomBytes(32)); + const challenge = crypto.createHash("sha256").update(verifier).digest(); + + const queryParams = new URLSearchParams({ + response_type: 'code', + // scope: '', + client_id: process.env.OAUTH_CLIENT_ID, + redirect_uri: process.env.OAUTH_REDIRECT_URI, + code_challenge: challenge, + code_challenge_method: 'S256' + }) + + const authorizationUri = `${authEndpoint}?${queryParams}` res.redirect(authorizationUri) }); app.get('/callback', async (req, res) => { - const credentials = await oauthClient.code.getToken(req.originalUrl); - - res.render('index', { - host, - token: credentials.accessToken, - destination: process.env.DEFAULT_DESTINATION, - firebaseConfig: FIREBASE_CONFIG, - }); + // const credentials = await oauthClient.code.getToken(req.originalUrl); + + // res.render('index', { + // host, + // token: credentials.accessToken, + // destination: process.env.DEFAULT_DESTINATION, + // firebaseConfig: FIREBASE_CONFIG, + // }); }) app.get('/service-worker.js', async (req, res) => { @@ -99,4 +103,4 @@ app.get('/service-worker.js', async (req, res) => { app.listen(process.env.PORT || 3000, () => { console.log("Server running on port 3000"); -}); \ No newline at end of file +}); diff --git a/package-lock.json b/package-lock.json index 67ffae9..2f4e6d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "ISC", "dependencies": { "axios": "^1.5.0", - "client-oauth2": "^4.3.3", + "base64url": "^3.0.1", "dotenv": "^16.3.1", "ejs": "^3.1.9", "express": "^4.18.2" @@ -1052,11 +1052,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@servie/events": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@servie/events/-/events-1.0.0.tgz", - "integrity": "sha512-sBSO19KzdrJCM3gdx6eIxV8M9Gxfgg6iDQmH5TIAGaUu+X9VDdsINXJOnoiZ1Kx3TrHdH4bt5UVglkjsEGBcvw==" - }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -1170,11 +1165,6 @@ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==" - }, "node_modules/@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -1405,6 +1395,14 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1505,11 +1503,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/byte-length/-/byte-length-1.0.2.tgz", - "integrity": "sha512-ovBpjmsgd/teRmgcPh23d4gJvxDoXtAzEL9xTfMU8Yc2kqCDb7L9jAG0XHl1nzuGl+h3ebCIF1i62UFyA9V/2Q==" - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1641,18 +1634,6 @@ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, - "node_modules/client-oauth2": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/client-oauth2/-/client-oauth2-4.3.3.tgz", - "integrity": "sha512-k8AvUYJon0vv75ufoVo4nALYb/qwFFicO3I0+39C6xEdflqVtr+f9cy+0ZxAduoVSTfhP5DX2tY2XICAd5hy6Q==", - "dependencies": { - "popsicle": "^12.0.5", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4.2.0" - } - }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -3465,19 +3446,6 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" - }, - "node_modules/make-error-cause": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-2.3.0.tgz", - "integrity": "sha512-etgt+n4LlOkGSJbBTV9VROHA5R7ekIPS4vfh+bCAoJgRrJWdqJCBbpS3osRJ/HrT7R68MzMiY3L3sDJ/Fd8aBg==", - "dependencies": { - "make-error": "^1.3.5" - } - }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -3946,82 +3914,6 @@ "node": ">=8" } }, - "node_modules/popsicle": { - "version": "12.1.2", - "resolved": "https://registry.npmjs.org/popsicle/-/popsicle-12.1.2.tgz", - "integrity": "sha512-xE2vEUa15TiHvFhGmKTtdKk9aSLL5CHX8Vw5kHfVM3R0YHiaTon6Ybsamw0XYqMR+Ng2RijX88iYUKPBMpLBww==", - "dependencies": { - "popsicle-content-encoding": "^1.0.0", - "popsicle-cookie-jar": "^1.0.1", - "popsicle-redirects": "^1.1.0", - "popsicle-transport-http": "^1.1.0", - "popsicle-transport-xhr": "^2.0.0", - "popsicle-user-agent": "^1.0.0", - "servie": "^4.3.3", - "throwback": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/popsicle-content-encoding": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/popsicle-content-encoding/-/popsicle-content-encoding-1.0.0.tgz", - "integrity": "sha512-4Df+vTfM8wCCJVTzPujiI6eOl3SiWQkcZg0AMrOkD1enMXsF3glIkFUZGvour1Sj7jOWCsNSEhBxpbbhclHhzw==", - "peerDependencies": { - "servie": "^4.0.0" - } - }, - "node_modules/popsicle-cookie-jar": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/popsicle-cookie-jar/-/popsicle-cookie-jar-1.0.1.tgz", - "integrity": "sha512-QVIZhADP8nDbXIQW6wq8GU9IOSE8INUACO/9KD9TFKQ7qq8r/y3qUDz59xIi6p6TH19lCJJyBAPSXP1liIoySw==", - "dependencies": { - "@types/tough-cookie": "^4.0.2", - "tough-cookie": "^4.1.3" - }, - "engines": { - "node": ">=8" - }, - "peerDependencies": { - "servie": "^4.0.0" - } - }, - "node_modules/popsicle-redirects": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/popsicle-redirects/-/popsicle-redirects-1.1.1.tgz", - "integrity": "sha512-mC2HrKjdTAWDalOjGxlXw9j6Qxrz/Yd2ui6bPxpi2IQDYWpF4gUAMxbA8EpSWJhLi0PuWKDwTHHPrUPGutAoIA==", - "peerDependencies": { - "servie": "^4.1.0" - } - }, - "node_modules/popsicle-transport-http": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/popsicle-transport-http/-/popsicle-transport-http-1.2.1.tgz", - "integrity": "sha512-i5r3IGHkGiBDm1oPFvOfEeSGWR0lQJcsdTqwvvDjXqcTHYJJi4iSi3ecXIttDiTBoBtRAFAE9nF91fspQr63FQ==", - "dependencies": { - "make-error-cause": "^2.2.0" - }, - "peerDependencies": { - "servie": "^4.2.0" - } - }, - "node_modules/popsicle-transport-xhr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/popsicle-transport-xhr/-/popsicle-transport-xhr-2.0.0.tgz", - "integrity": "sha512-5Sbud4Widngf1dodJE5cjEYXkzEUIl8CzyYRYR57t6vpy9a9KPGQX6KBKdPjmBZlR5A06pOBXuJnVr23l27rtA==", - "peerDependencies": { - "servie": "^4.2.0" - } - }, - "node_modules/popsicle-user-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/popsicle-user-agent/-/popsicle-user-agent-1.0.0.tgz", - "integrity": "sha512-epKaq3TTfTzXcxBxjpoKYMcTTcAX8Rykus6QZu77XNhJuRHSRxMd+JJrbX/3PFI0opFGSN0BabbAYCbGxbu0mA==", - "peerDependencies": { - "servie": "^4.0.0" - } - }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -4078,25 +3970,12 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", "dev": true }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, "node_modules/pure-rand": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", @@ -4127,11 +4006,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" - }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -4181,11 +4055,6 @@ "node": ">=0.10.0" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" - }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -4308,16 +4177,6 @@ "node": ">= 0.8.0" } }, - "node_modules/servie": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/servie/-/servie-4.3.3.tgz", - "integrity": "sha512-b0IrY3b1gVMsWvJppCf19g1p3JSnS0hQi6xu4Hi40CIhf0Lx8pQHcvBL+xunShpmOiQzg1NOia812NAWdSaShw==", - "dependencies": { - "@servie/events": "^1.0.0", - "byte-length": "^1.0.2", - "ts-expect": "^1.1.0" - } - }, "node_modules/set-function-length": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", @@ -4588,11 +4447,6 @@ "node": ">=8" } }, - "node_modules/throwback": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/throwback/-/throwback-4.1.0.tgz", - "integrity": "sha512-dLFe8bU8SeH0xeqeKL7BNo8XoPC/o91nz9/ooeplZPiso+DZukhoyZcSz9TFnUNScm+cA9qjU1m1853M6sPOng==" - }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -4640,25 +4494,6 @@ "nodetouch": "bin/nodetouch.js" } }, - "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ts-expect": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-expect/-/ts-expect-1.3.0.tgz", - "integrity": "sha512-e4g0EJtAjk64xgnFPD6kTBUtpnMVzDrMb12N1YZV0VvSlhnVT3SGxiYTLdGy8Q5cYHOIC/FAHmZ10eGrAguicQ==" - }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -4704,14 +4539,6 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, - "node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -4750,15 +4577,6 @@ "browserslist": ">= 4.21.0" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", diff --git a/package.json b/package.json index 7a2cccc..281ed34 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,12 @@ "dev": "nodemon index.js", "test": "npm run test:unit", "test:unit": "jest --passWithNoTests" - }, "author": "", "license": "ISC", "dependencies": { "axios": "^1.5.0", - "client-oauth2": "^4.3.3", + "base64url": "^3.0.1", "dotenv": "^16.3.1", "ejs": "^3.1.9", "express": "^4.18.2" From ac1485fd4668bc10797a9417c926f1a7df396105 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Tue, 9 Jan 2024 17:22:03 -0800 Subject: [PATCH 02/13] restore token --- index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index ea51bdf..46a48ee 100644 --- a/index.js +++ b/index.js @@ -42,20 +42,20 @@ async function apiRequest(endpoint, payload = {}, method = 'POST') { } app.get('/', async (req, res) => { - // const response = await apiRequest('/api/fabric/subscribers/tokens', token_request) + const response = await apiRequest('/api/fabric/subscribers/tokens', token_request) res.render('index', { host, - token: '', + token: response.token, destination: process.env.DEFAULT_DESTINATION, firebaseConfig: FIREBASE_CONFIG, }); }); app.get('/minimal', async (req, res) => { - // const response = await apiRequest('/api/fabric/subscribers/tokens', token_request) + const response = await apiRequest('/api/fabric/subscribers/tokens', token_request) res.render('minimal', { host, - token: '', + token: response.token, destination: process.env.DEFAULT_DESTINATION, firebaseConfig: FIREBASE_CONFIG, }); From 635f62083d4e25b291f0721a3923dc49f452062b Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Tue, 9 Jan 2024 18:21:11 -0800 Subject: [PATCH 03/13] store verifier --- index.js | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index 46a48ee..8058ff6 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,6 @@ require('dotenv').config(); const express = require('express'); +const session = require('express-session'); const app = express(); const axios = require('axios'); const base64url = require('base64url'); @@ -9,6 +10,7 @@ app.set('view engine', 'ejs'); app.use(express.urlencoded({ extended: true })); app.use(express.json()); app.use(express.static('public')); +app.use(session({ secret: '74cd5a0bea4542de9322fd95070e353d745bee2900e39576f98bc80a961209fa', resave: false, saveUninitialized: true })); const FIREBASE_CONFIG = JSON.stringify({ apiKey: process.env.FIREBASE_API_KEY, @@ -64,6 +66,7 @@ app.get('/minimal', async (req, res) => { app.get('/oauth', (req, res) => { const authEndpoint = process.env.OAUTH_AUTH_URI; const verifier = base64url(crypto.pseudoRandomBytes(32)); + req.session.verifier = verifier; const challenge = crypto.createHash("sha256").update(verifier).digest(); const queryParams = new URLSearchParams({ @@ -81,14 +84,22 @@ app.get('/oauth', (req, res) => { }); app.get('/callback', async (req, res) => { - // const credentials = await oauthClient.code.getToken(req.originalUrl); - - // res.render('index', { - // host, - // token: credentials.accessToken, - // destination: process.env.DEFAULT_DESTINATION, - // firebaseConfig: FIREBASE_CONFIG, - // }); + const verifier = req.session.verifier; + + response = await axios.post(process.env.OAUTH_TOKEN_URI, { + client_id: process.env.OAUTH_CLIENT_ID, + grant_type: 'authorization_code', + code: req.params.code + redirect_uri: process.env.OAUTH_REDIRECT_URI, + code_verifier: verifier + }); + + res.render('index', { + host, + token: response.access_token, + destination: process.env.DEFAULT_DESTINATION, + firebaseConfig: FIREBASE_CONFIG, + }); }) app.get('/service-worker.js', async (req, res) => { From 1e7d4712704e77fe3dcf664e9d4b4ce20f8fefa1 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Tue, 9 Jan 2024 19:09:11 -0800 Subject: [PATCH 04/13] more wip, up to 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.' --- index.js | 3 ++- package-lock.json | 56 ++++++++++++++++++++++++++++++++++++++++++++++- package.json | 3 ++- 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 8058ff6..54ac9cb 100644 --- a/index.js +++ b/index.js @@ -85,11 +85,12 @@ app.get('/oauth', (req, res) => { app.get('/callback', async (req, res) => { const verifier = req.session.verifier; + const code = req.query.code; response = await axios.post(process.env.OAUTH_TOKEN_URI, { client_id: process.env.OAUTH_CLIENT_ID, grant_type: 'authorization_code', - code: req.params.code + code: code, redirect_uri: process.env.OAUTH_REDIRECT_URI, code_verifier: verifier }); diff --git a/package-lock.json b/package-lock.json index 2f4e6d2..8fcb3eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,8 @@ "base64url": "^3.0.1", "dotenv": "^16.3.1", "ejs": "^3.1.9", - "express": "^4.18.2" + "express": "^4.18.2", + "express-session": "^1.17.3" }, "devDependencies": { "jest": "^29.7.0", @@ -2060,6 +2061,32 @@ "node": ">= 0.10.0" } }, + "node_modules/express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "dependencies": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -3736,6 +3763,14 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4006,6 +4041,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -4527,6 +4570,17 @@ "node": ">= 0.6" } }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", diff --git a/package.json b/package.json index 281ed34..b419355 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "base64url": "^3.0.1", "dotenv": "^16.3.1", "ejs": "^3.1.9", - "express": "^4.18.2" + "express": "^4.18.2", + "express-session": "^1.17.3" }, "devDependencies": { "jest": "^29.7.0", From a5ab427de1b94e21d51563001c6c35e257415731 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Tue, 9 Jan 2024 19:12:44 -0800 Subject: [PATCH 05/13] session secret --- env.example | 4 +++- index.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/env.example b/env.example index c035288..6266e85 100644 --- a/env.example +++ b/env.example @@ -18,4 +18,6 @@ OAUTH_CLIENT_ID= OAUTH_SECRET= OAUTH_TOKEN_URI=https://id.fabric.swire.io/oauth/token OAUTH_AUTH_URI=https://id.fabric.swire.io/login/oauth/authorize -OAUTH_REDIRECT_URI=https://.ngrok-free.app/callback \ No newline at end of file +OAUTH_REDIRECT_URI=https://.ngrok-free.app/callback + +SESSION_SECRET= diff --git a/index.js b/index.js index 54ac9cb..5712c22 100644 --- a/index.js +++ b/index.js @@ -10,7 +10,7 @@ app.set('view engine', 'ejs'); app.use(express.urlencoded({ extended: true })); app.use(express.json()); app.use(express.static('public')); -app.use(session({ secret: '74cd5a0bea4542de9322fd95070e353d745bee2900e39576f98bc80a961209fa', resave: false, saveUninitialized: true })); +app.use(session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: true })); const FIREBASE_CONFIG = JSON.stringify({ apiKey: process.env.FIREBASE_API_KEY, From 73107a20aa5e594f2268ba4bb0746d8826e5ac7a Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Tue, 9 Jan 2024 19:13:26 -0800 Subject: [PATCH 06/13] subscribers --- env.example | 3 +++ 1 file changed, 3 insertions(+) diff --git a/env.example b/env.example index 6266e85..06190a9 100644 --- a/env.example +++ b/env.example @@ -21,3 +21,6 @@ OAUTH_AUTH_URI=https://id.fabric.swire.io/login/oauth/authorize OAUTH_REDIRECT_URI=https://.ngrok-free.app/callback SESSION_SECRET= + +SUBSCRIBER_REFERENCE= +SUBSCRIBER_PASSWORD= From 9cc9e50b8fcec1303557e95a8df2d8f27a81b67c Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Tue, 9 Jan 2024 19:37:14 -0800 Subject: [PATCH 07/13] working on getting token --- index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 5712c22..a6b52d0 100644 --- a/index.js +++ b/index.js @@ -64,9 +64,11 @@ app.get('/minimal', async (req, res) => { }); app.get('/oauth', (req, res) => { + console.log("begin oauth initiation"); const authEndpoint = process.env.OAUTH_AUTH_URI; const verifier = base64url(crypto.pseudoRandomBytes(32)); req.session.verifier = verifier; + console.log("verifier during initiation = ", verifier); const challenge = crypto.createHash("sha256").update(verifier).digest(); const queryParams = new URLSearchParams({ @@ -85,10 +87,10 @@ app.get('/oauth', (req, res) => { app.get('/callback', async (req, res) => { const verifier = req.session.verifier; + console.log("verifier during callback = ", verifier); const code = req.query.code; response = await axios.post(process.env.OAUTH_TOKEN_URI, { - client_id: process.env.OAUTH_CLIENT_ID, grant_type: 'authorization_code', code: code, redirect_uri: process.env.OAUTH_REDIRECT_URI, From e0587e9a61a8561bf6057ceff86c5a8ec8fe3363 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Tue, 9 Jan 2024 20:20:26 -0800 Subject: [PATCH 08/13] get it working --- index.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index a6b52d0..a1e24ae 100644 --- a/index.js +++ b/index.js @@ -64,16 +64,16 @@ app.get('/minimal', async (req, res) => { }); app.get('/oauth', (req, res) => { - console.log("begin oauth initiation"); + console.log("oauth: begin initiation"); + // console.log("Request Headers: ", req.headers); + const authEndpoint = process.env.OAUTH_AUTH_URI; const verifier = base64url(crypto.pseudoRandomBytes(32)); req.session.verifier = verifier; - console.log("verifier during initiation = ", verifier); - const challenge = crypto.createHash("sha256").update(verifier).digest(); + const challenge = base64url(crypto.createHash('sha256').update(verifier).digest()); const queryParams = new URLSearchParams({ response_type: 'code', - // scope: '', client_id: process.env.OAUTH_CLIENT_ID, redirect_uri: process.env.OAUTH_REDIRECT_URI, code_challenge: challenge, @@ -82,15 +82,18 @@ app.get('/oauth', (req, res) => { const authorizationUri = `${authEndpoint}?${queryParams}` - res.redirect(authorizationUri) + res.redirect(authorizationUri); }); app.get('/callback', async (req, res) => { + console.log("oauth: process callback"); + // console.log("Request Headers: ", req.headers); + const verifier = req.session.verifier; - console.log("verifier during callback = ", verifier); const code = req.query.code; response = await axios.post(process.env.OAUTH_TOKEN_URI, { + client_id: process.env.OAUTH_CLIENT_ID, grant_type: 'authorization_code', code: code, redirect_uri: process.env.OAUTH_REDIRECT_URI, From 1aafff269b892f4a880d56562091028c42716dd0 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Tue, 9 Jan 2024 20:35:10 -0800 Subject: [PATCH 09/13] just use fetch --- index.js | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/index.js b/index.js index a1e24ae..793a7e3 100644 --- a/index.js +++ b/index.js @@ -89,24 +89,31 @@ app.get('/callback', async (req, res) => { console.log("oauth: process callback"); // console.log("Request Headers: ", req.headers); - const verifier = req.session.verifier; - const code = req.query.code; - - response = await axios.post(process.env.OAUTH_TOKEN_URI, { - client_id: process.env.OAUTH_CLIENT_ID, - grant_type: 'authorization_code', - code: code, - redirect_uri: process.env.OAUTH_REDIRECT_URI, - code_verifier: verifier + const params = new URLSearchParams(); + params.append('client_id', process.env.OAUTH_CLIENT_ID); + params.append('grant_type', 'authorization_code'); + params.append('code', req.query.code); + params.append('redirect_uri', process.env.OAUTH_REDIRECT_URI); + params.append('code_verifier', req.session.verifier); + + const response = await fetch(process.env.OAUTH_TOKEN_URI, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: params }); - res.render('index', { - host, - token: response.access_token, - destination: process.env.DEFAULT_DESTINATION, - firebaseConfig: FIREBASE_CONFIG, - }); -}) + if (response.ok) { + const data = await response.json(); + res.render('index', { + host, + token: data.access_token, + destination: process.env.DEFAULT_DESTINATION, + firebaseConfig: FIREBASE_CONFIG, + }); + } else { + throw new Error(`HTTP error! status: ${response.status}`); + } +}); app.get('/service-worker.js', async (req, res) => { res.set({ From 9ecb98a443ccbd17637e4262a8542d5023272878 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Wed, 10 Jan 2024 07:46:25 -0800 Subject: [PATCH 10/13] Update index.js Co-authored-by: Ammar Ansari --- index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/index.js b/index.js index 793a7e3..b7cbecb 100644 --- a/index.js +++ b/index.js @@ -65,7 +65,6 @@ app.get('/minimal', async (req, res) => { app.get('/oauth', (req, res) => { console.log("oauth: begin initiation"); - // console.log("Request Headers: ", req.headers); const authEndpoint = process.env.OAUTH_AUTH_URI; const verifier = base64url(crypto.pseudoRandomBytes(32)); From 3a86198d22f45d66822599c60a22fd9521420ef8 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Wed, 10 Jan 2024 07:46:33 -0800 Subject: [PATCH 11/13] Update index.js Co-authored-by: Ammar Ansari --- index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/index.js b/index.js index b7cbecb..f2767e2 100644 --- a/index.js +++ b/index.js @@ -86,7 +86,6 @@ app.get('/oauth', (req, res) => { app.get('/callback', async (req, res) => { console.log("oauth: process callback"); - // console.log("Request Headers: ", req.headers); const params = new URLSearchParams(); params.append('client_id', process.env.OAUTH_CLIENT_ID); From 40570f1bce6cbfb0f7407cf0b588701f4fedf55b Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Wed, 10 Jan 2024 08:15:07 -0800 Subject: [PATCH 12/13] migrate axios to fetch --- README.md | 4 +-- index.js | 23 +++++++++------ package-lock.json | 72 ----------------------------------------------- package.json | 1 - 4 files changed, 17 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index 43dd0cb..70f8c52 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ The `reference` field (aka subscriber) will be used in the future for inbound ca -In the example application, we use `axios` to retrieve the token. +In the example application, we use `fetch` to retrieve the token. ## Instantiate the client and call the destination @@ -53,4 +53,4 @@ const call = await client.dial({ await call.start() ``` -For now, please run with debugging on to help with reporting issues. \ No newline at end of file +For now, please run with debugging on to help with reporting issues. diff --git a/index.js b/index.js index f2767e2..0fbbd71 100644 --- a/index.js +++ b/index.js @@ -2,7 +2,6 @@ require('dotenv').config(); const express = require('express'); const session = require('express-session'); const app = express(); -const axios = require('axios'); const base64url = require('base64url'); const crypto = require('crypto'); @@ -34,13 +33,21 @@ const host = process.env.RELAY_HOST async function apiRequest(endpoint, payload = {}, method = 'POST') { var url = `https://${process.env.SIGNALWIRE_SPACE}${endpoint}` - resp = await axios.post(url, payload, { - auth: { - username: process.env.SIGNALWIRE_PROJECT_KEY, - password: process.env.SIGNALWIRE_TOKEN - } - }) - return resp.data + const response = await fetch(url, { + method: method, + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Basic ' + Buffer.from(process.env.SIGNALWIRE_PROJECT_KEY + ':' + process.env.SIGNALWIRE_TOKEN).toString('base64') + }, + body: JSON.stringify(payload) + }); + + if (response.ok) { + return await response.json(); + } else { + console.log(await response.text()); + throw new Error(`HTTP error! status: ${response.status}`); + } } app.get('/', async (req, res) => { diff --git a/package-lock.json b/package-lock.json index 8fcb3eb..95e0168 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,6 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "axios": "^1.5.0", "base64url": "^3.0.1", "dotenv": "^16.3.1", "ejs": "^3.1.9", @@ -1269,21 +1268,6 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/axios": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", - "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", - "dependencies": { - "follow-redirects": "^1.15.4", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -1681,17 +1665,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1814,14 +1787,6 @@ "node": ">= 0.4" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -2171,38 +2136,6 @@ "node": ">=8" } }, - "node_modules/follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -4000,11 +3933,6 @@ "node": ">= 0.10" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", diff --git a/package.json b/package.json index b419355..d9fa86b 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,6 @@ "author": "", "license": "ISC", "dependencies": { - "axios": "^1.5.0", "base64url": "^3.0.1", "dotenv": "^16.3.1", "ejs": "^3.1.9", From 71bd68ab718c29d574e9fe6bfbfc746378f40cd8 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Wed, 10 Jan 2024 08:27:49 -0800 Subject: [PATCH 13/13] use template string --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 0fbbd71..05a736a 100644 --- a/index.js +++ b/index.js @@ -37,7 +37,7 @@ async function apiRequest(endpoint, payload = {}, method = 'POST') { method: method, headers: { 'Content-Type': 'application/json', - 'Authorization': 'Basic ' + Buffer.from(process.env.SIGNALWIRE_PROJECT_KEY + ':' + process.env.SIGNALWIRE_TOKEN).toString('base64') + 'Authorization': `Basic ${Buffer.from(`${process.env.SIGNALWIRE_PROJECT_KEY}:${process.env.SIGNALWIRE_TOKEN}`).toString('base64')}` }, body: JSON.stringify(payload) });