From c8140fd85eca01c16076a0e5f820fcb4c02bcc3e Mon Sep 17 00:00:00 2001 From: Vijay Budhram Date: Tue, 29 Apr 2025 16:09:44 -0400 Subject: [PATCH] chore(deps): Remove browserid-verifier packages and references --- .gitignore | 4 - _dev/docker/docker-compose.yml | 10 - _scripts/ports.txt | 1 - catalog-info.yaml | 1 - packages/browserid-verifier/.eslintrc.json | 5 - packages/browserid-verifier/.nsprc | 14 -- packages/browserid-verifier/.prettierignore | 4 - packages/browserid-verifier/README.md | 141 ----------- packages/browserid-verifier/backstage.yaml | 19 -- .../browserid-verifier/config/production.json | 15 -- .../lib/ccverifier/index.js | 77 ------ .../lib/ccverifier/worker.js | 27 --- packages/browserid-verifier/lib/config.js | 167 ------------- packages/browserid-verifier/lib/log/index.js | 7 - packages/browserid-verifier/lib/server.js | 186 -------------- packages/browserid-verifier/lib/summary.js | 34 --- packages/browserid-verifier/lib/v1.js | 129 ---------- packages/browserid-verifier/lib/v2.js | 129 ---------- packages/browserid-verifier/lib/version.js | 71 ------ packages/browserid-verifier/loadtest/Makefile | 36 --- .../browserid-verifier/loadtest/README.txt | 26 -- .../loadtest/config/bench.ini | 3 - .../loadtest/config/megabench.ini | 9 - .../loadtest/config/test.ini | 3 - .../browserid-verifier/loadtest/loadtest.py | 129 ---------- packages/browserid-verifier/package.json | 57 ----- packages/browserid-verifier/pm2.config.js | 29 --- packages/browserid-verifier/server.js | 7 - packages/browserid-verifier/tests/audience.js | 102 -------- packages/browserid-verifier/tests/basic.js | 91 ------- .../tests/cascading-config.js | 60 ----- .../browserid-verifier/tests/content-type.js | 228 ------------------ packages/browserid-verifier/tests/fallback.js | 111 --------- .../browserid-verifier/tests/force-issuer.js | 131 ---------- .../browserid-verifier/tests/health-check.js | 99 -------- .../lib/should-return-security-headers.js | 24 -- .../tests/lib/test-server.js | 6 - .../browserid-verifier/tests/lib/verifier.js | 148 ------------ .../tests/missing-assertion.js | 43 ---- .../tests/service-failure.js | 80 ------ .../tests/trusted-issuers.js | 102 -------- .../tests/unverified-email.js | 136 ----------- .../scripts/start-services.sh | 1 - packages/fxa-auth-server/backstage.yaml | 1 - .../scripts/start-services.sh | 1 - 45 files changed, 2704 deletions(-) delete mode 100644 packages/browserid-verifier/.eslintrc.json delete mode 100644 packages/browserid-verifier/.nsprc delete mode 100644 packages/browserid-verifier/.prettierignore delete mode 100644 packages/browserid-verifier/README.md delete mode 100644 packages/browserid-verifier/backstage.yaml delete mode 100644 packages/browserid-verifier/config/production.json delete mode 100644 packages/browserid-verifier/lib/ccverifier/index.js delete mode 100644 packages/browserid-verifier/lib/ccverifier/worker.js delete mode 100644 packages/browserid-verifier/lib/config.js delete mode 100644 packages/browserid-verifier/lib/log/index.js delete mode 100644 packages/browserid-verifier/lib/server.js delete mode 100644 packages/browserid-verifier/lib/summary.js delete mode 100644 packages/browserid-verifier/lib/v1.js delete mode 100644 packages/browserid-verifier/lib/v2.js delete mode 100644 packages/browserid-verifier/lib/version.js delete mode 100644 packages/browserid-verifier/loadtest/Makefile delete mode 100644 packages/browserid-verifier/loadtest/README.txt delete mode 100644 packages/browserid-verifier/loadtest/config/bench.ini delete mode 100644 packages/browserid-verifier/loadtest/config/megabench.ini delete mode 100644 packages/browserid-verifier/loadtest/config/test.ini delete mode 100644 packages/browserid-verifier/loadtest/loadtest.py delete mode 100644 packages/browserid-verifier/package.json delete mode 100644 packages/browserid-verifier/pm2.config.js delete mode 100755 packages/browserid-verifier/server.js delete mode 100644 packages/browserid-verifier/tests/audience.js delete mode 100644 packages/browserid-verifier/tests/basic.js delete mode 100644 packages/browserid-verifier/tests/cascading-config.js delete mode 100644 packages/browserid-verifier/tests/content-type.js delete mode 100644 packages/browserid-verifier/tests/fallback.js delete mode 100644 packages/browserid-verifier/tests/force-issuer.js delete mode 100644 packages/browserid-verifier/tests/health-check.js delete mode 100644 packages/browserid-verifier/tests/lib/should-return-security-headers.js delete mode 100755 packages/browserid-verifier/tests/lib/test-server.js delete mode 100644 packages/browserid-verifier/tests/lib/verifier.js delete mode 100644 packages/browserid-verifier/tests/missing-assertion.js delete mode 100644 packages/browserid-verifier/tests/service-failure.js delete mode 100644 packages/browserid-verifier/tests/trusted-issuers.js delete mode 100644 packages/browserid-verifier/tests/unverified-email.js diff --git a/.gitignore b/.gitignore index 328fe7748b..1f17753e6d 100644 --- a/.gitignore +++ b/.gitignore @@ -88,10 +88,6 @@ Thumbs.db # circleci .circleci/local.yml -# browserid-verifier -packages/browserid-verifier/loadtest/venv -packages/browserid-verifier/loadtest/*.pyc - # fxa-admin-server packages/fxa-admin-server/src/config/local.json diff --git a/_dev/docker/docker-compose.yml b/_dev/docker/docker-compose.yml index 1764dd93ce..b58cbde385 100644 --- a/_dev/docker/docker-compose.yml +++ b/_dev/docker/docker-compose.yml @@ -10,16 +10,6 @@ services: # init: true # ports: # - "8080:8080" - browserid-verifier: - image: browserid-verifier:build - command: node server.js - environment: - - PORT=5050 - - IP_ADDRESS=0.0.0.0 - - FORCE_INSECURE_LOOKUP_OVER_HTTP=true - init: true - ports: - - "5050:5050" auth: image: fxa-auth-server:build entrypoint: /bin/bash -c diff --git a/_scripts/ports.txt b/_scripts/ports.txt index 873c28c30f..49fc2c8350 100644 --- a/_scripts/ports.txt +++ b/_scripts/ports.txt @@ -11,7 +11,6 @@ 9292 # Fortress 8080 # 123done 10139 # 321done -5050 # browserid-verifier 3031 # payments server 7100 # support admin panel 8002 # pushbox diff --git a/catalog-info.yaml b/catalog-info.yaml index 19a2e570d1..17b429d056 100644 --- a/catalog-info.yaml +++ b/catalog-info.yaml @@ -11,7 +11,6 @@ spec: - ./backstage/mysql.resources.yaml - ./backstage/redis.resources.yaml - ./packages/123done/backstage.yaml - - ./packages/browserid-verifier/backstage.yaml - ./packages/fxa-admin-panel/backstage.yaml - ./packages/fxa-admin-server/backstage.yaml - ./packages/fxa-auth-server/backstage.yaml diff --git a/packages/browserid-verifier/.eslintrc.json b/packages/browserid-verifier/.eslintrc.json deleted file mode 100644 index cb5a8a9d51..0000000000 --- a/packages/browserid-verifier/.eslintrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": ["plugin:fxa/recommended"], - "plugins": ["fxa"], - "root": true -} diff --git a/packages/browserid-verifier/.nsprc b/packages/browserid-verifier/.nsprc deleted file mode 100644 index ce8c5675ac..0000000000 --- a/packages/browserid-verifier/.nsprc +++ /dev/null @@ -1,14 +0,0 @@ -{ - "comment": "532, 534, 545 are various ReDoS that don't affect us.", - "comment_566": "Hoek merge vuln, which we don't use.", - "comment_1179": "1179 is prototype pollution in minimist, used by eslint, optimist, and mocha. Doesn't affect us, as we don't pass untrusted external inputs to any of these.", - "comment_1488": "Acorn DoS vuln (dep of browserify), only applies if passed untrusted user input.", - "exceptions": [ - "https://nodesecurity.io/advisories/532", - "https://nodesecurity.io/advisories/534", - "https://nodesecurity.io/advisories/535", - "https://nodesecurity.io/advisories/566", - "https://npmjs.com/advisories/1179", - "https://npmjs.com/advisories/1488" - ] -} diff --git a/packages/browserid-verifier/.prettierignore b/packages/browserid-verifier/.prettierignore deleted file mode 100644 index 4cb323c715..0000000000 --- a/packages/browserid-verifier/.prettierignore +++ /dev/null @@ -1,4 +0,0 @@ -LICENSE -.* -Dockerfile -loadtest/* \ No newline at end of file diff --git a/packages/browserid-verifier/README.md b/packages/browserid-verifier/README.md deleted file mode 100644 index 5927c28018..0000000000 --- a/packages/browserid-verifier/README.md +++ /dev/null @@ -1,141 +0,0 @@ -## A BrowserID verification server - -This repository contains a flexible BrowserID verification server authored in -Node.JS which uses the [local verification library](https://github.com/mozilla/browserid-local-verify). - -## Getting Started - -To run the verification server locally: - - $ git clone https://github.com/mozilla/browserid-verifier - $ cd browserid-verifier - $ yarn install - $ yarn start - -At this point, your verifier will be running and available to use locally over -HTTP. - -## Configuration - -There are several configuration variables which can change the behavior of the -server. You can inspect available configuration variables in `lib/config.js`. -You can specify a set of `json` configuration files using the `CONFIG_FILES` -environment variable (separate each path with a comma (`,`)). Finally, you can -inspect the current server configuration with: - - $ node ./lib/server.js -c - -## Health Checks - -The server exports an endpoint at `/status` that can be polled for server health. -When the server is healthy, a `200` HTTP response is returned with a body of `OK`. - -## Testing - -This package uses [Mocha](https://mochajs.org/) to test its code. By default `npm test` will test all JS files under `tests/`. - -Test specific tests with the following commands: - -```bash -# Test only tests/health-check.js -npx mocha tests/health-check.js - -# Grep for "test servers should start" -npx mocha -g "test servers should start" -``` - -Refer to Mocha's [CLI documentation](https://mochajs.org/#command-line-usage) for more advanced test configuration. - -## API - -The server exports an HTTP endpoint at `/v2` that can be POSTed to verify BrowserID -assertions. Arguments may be provided inside a JSON object. The following are -required: - -1. Requests must be an HTTP POST. -2. Content-Type must equal `application/json` -3. POST body must be valid JSON. - -The following arguments are supported: - -### **required** (string) `assertion` - -A BrowserID assertion - -### **required** (string) `audience` - -The origin of the site to which the assertion is expected to be bound. - -### **optional** (array of strings) `trustedIssuers` - -An array of domain names that are _trusted_ issuers. Assertions -signed by any of the domains in this set will be honored regardless of -the presence of a subject or principal in a BrowserID assertion. - -### Error Response - -Example: - - $ curl -H 'Content-Type: application/json' \ - -d '{ "audience": "http://example.com", "assertion": "bogus" }' \ - https://verifier.mozcloud.org/v2 - { - "status": "failure", - "reason": "no certificates provided" - } - -Upon failure, the verifier returns a non-200 HTTP status code. Additionally, the -response body contains a JSON formated response containing a `status` key with the -value of `failure`. Additionally, more verbose developer readable information will -be available in a string value on the `reason` key. - -### Success Response - -Example: - - $ curl -H 'Content-Type: application/json' \ - -d '{ "audience": "http://123done.org" , "assertion": "eyJhbG...ZEe7A" }' - https://verifier.mozcloud.org/v2 - { - "audience": "http://123done.org", - "expires": 1389791993675, - "issuer": "mockmyid.com", - "email": "lloyd@mockmyid.com", - "status": "okay" - } - -Upon successful assertion verification, a 200 response will be sent with a JSON formatted body. -The body will always include `audience`, `issuer`, `status` (of "okay"), and `expires`. - -### Extra IdP claims - -The verifier will extract any number of additional claims from the -Identity Certificate generated by the Identity Provider. These claims -will be returned under a `idpClaims` top level key in the success response. Hence, an identity -certificate which looks like this: - - { - "pubkey": { "...": "..." }, - "sub": "60ae5097-8118-4c58-bb80-7db2742d137e", - "iat": 1389964111, - "exp": 1421500111, - "iss": "example.com", - "fxa-version": 1, - "fxa-generation": 504, - "email": "user@example.com" - } - -Upon successful verification (which could only occur via `.trustedIssuers` because authority lookup will fail), will -result in a verifier response like this: - - { - "audience": "...", - "expires": 1421500111, - "issuer": "example.com", - "idpClaims": { - "fxa-version": 1, - "fxa-generation": 504, - "email": "user@example.com" - }, - "status": "okay" - } diff --git a/packages/browserid-verifier/backstage.yaml b/packages/browserid-verifier/backstage.yaml deleted file mode 100644 index 888e9e8a2c..0000000000 --- a/packages/browserid-verifier/backstage.yaml +++ /dev/null @@ -1,19 +0,0 @@ ---- -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: fxa-browserid-verifier - description: Verifies BrowserID assertions. - tags: - - typescript - - javascript - - node - - hapi - annotations: - sentry.io/project-slug: mozilla/fxa-browserid-verify - circleci.com/project-slug: github/mozilla/fxa -spec: - type: service - lifecycle: production - owner: fxa-devs - system: mozilla-accounts diff --git a/packages/browserid-verifier/config/production.json b/packages/browserid-verifier/config/production.json deleted file mode 100644 index b24dbc7813..0000000000 --- a/packages/browserid-verifier/config/production.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "logging": { - "handlers": { - "console": { - "class": "intel/handlers/console", - "formatter": "json" - } - }, - "loggers": { - "bid.summary": { - "propagate": true - } - } - } -} diff --git a/packages/browserid-verifier/lib/ccverifier/index.js b/packages/browserid-verifier/lib/ccverifier/index.js deleted file mode 100644 index a5957a5e5f..0000000000 --- a/packages/browserid-verifier/lib/ccverifier/index.js +++ /dev/null @@ -1,77 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * This is browserid-local-verify wrapped in node-compute-cluster. - * - * It provides a "Verifier" class with a "verify" method just like the one - * in browserid-local-verify, except that it farms out work to subprocesses - * via node-compute-cluster rather than doing it inline. - * - * It's not a drop-in replacement for browserid-local-verify: - * - * * There is only verify(), not lookup() or other methods. - * - * * It doesn't emit async events like "debug" or "metrics" because - * there"s no support for that in node-compute-cluster. Yet... - * - */ - -const util = require('util'), - events = require('events'), - path = require('path'), - log = require('../log')('ccverifier'), - config = require('../config'), - cc = require('compute-cluster'), - _ = require('underscore'); - -function Verifier(args) { - events.EventEmitter.call(this); - this.args = args; - this.cc = new cc({ - module: path.join(__dirname, 'worker.js'), - max_processes: config.get('computecluster.maxProcesses'), - max_backlog: config.get('computecluster.maxBacklog'), - }) - .on('error', function (err) { - log.error('computeCluster.error', { err }); - }) - .on('info', function (msg) { - log.info('computeCluster.info', { message: msg }); - }) - .on('debug', function (msg) { - log.debug('computeCluster.debug', { message: msg }); - }); -} - -util.inherits(Verifier, events.EventEmitter); - -const testServiceFailure = config.get('testServiceFailure'); - -Verifier.prototype.verify = function (args, cb) { - if (!cb) { - cb = args; - args = {}; - } - args = _.extend({}, this.args, args); - this.cc.enqueue({ args: args }, function (err, res) { - if (err || testServiceFailure) { - // An error from the cluster itself. - return cb('compute cluster error: ' + err); - } - if (res.err) { - // An error from inside the verifier. - return cb(res.err); - } else { - // A valid result from the verifier. - return cb(null, res.res); - } - }); -}; - -Verifier.prototype.shutdown = function () { - this.cc.exit(); -}; - -module.exports = Verifier; diff --git a/packages/browserid-verifier/lib/ccverifier/worker.js b/packages/browserid-verifier/lib/ccverifier/worker.js deleted file mode 100644 index e82ef8ffbf..0000000000 --- a/packages/browserid-verifier/lib/ccverifier/worker.js +++ /dev/null @@ -1,27 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const LocalVerifier = require('browserid-local-verify'); - -var verifier = new LocalVerifier(); - -process.on('message', function (message) { - if (!message.args) { - message.args = {}; - } - try { - verifier.verify(message.args, function (err, res) { - if (err) { - return process.send({ err: err }); - } - return process.send({ res: res }); - }); - } catch (err) { - return process.send({ err: err }); - } -}); - -process.on('uncaughtException', function () { - process.exit(8); -}); diff --git a/packages/browserid-verifier/lib/config.js b/packages/browserid-verifier/lib/config.js deleted file mode 100644 index 3971c484e6..0000000000 --- a/packages/browserid-verifier/lib/config.js +++ /dev/null @@ -1,167 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -var convict = require('convict'); -convict.addFormats(require('convict-format-with-moment')); -convict.addFormats(require('convict-format-with-validator')); - -function loadConf() { - var conf = convict({ - ip: { - doc: 'The IP address to bind.', - format: String, - default: 'localhost', - env: 'IP_ADDRESS', - }, - port: { - doc: 'The port to bind.', - format: 'port', - default: 0, - env: 'PORT', - }, - fallback: { - doc: 'The domain of the fallback server, authoritative when lookup fails.', - format: String, - default: '', - env: 'FALLBACK_DOMAIN', - }, - httpTimeout: { - doc: '(s) how long to spend attempting to fetch support documents', - format: Number, - default: 8.0, - env: 'HTTP_TIMEOUT', - }, - insecureSSL: { - doc: '(testing only) Ignore invalid SSL certificates', - format: Boolean, - default: false, - env: 'INSECURE_SSL', - }, - forceInsecureLookupOverHTTP: { - doc: '(testing only) Lookup /.well-known/browserid documents over HTTP', - format: Boolean, - default: false, - env: 'FORCE_INSECURE_LOOKUP_OVER_HTTP', - }, - toobusy: { - maxLag: { - doc: 'Max event-loop lag before toobusy reports failure', - format: Number, - default: 70, - env: 'TOOBUSY_MAX_LAG', - }, - }, - computecluster: { - maxProcesses: { - doc: 'Max worker processes to spawn for the compute cluster', - format: Number, - default: undefined, - env: 'COMPUTECLUSTER_MAX_PROCESSES', - }, - maxBacklog: { - doc: 'Max length of work queue for the compute cluster', - format: Number, - default: undefined, - env: 'COMPUTECLUSTER_MAX_BACKLOG', - }, - }, - logging: { - app: { - default: 'browserid-verifier', - }, - fmt: { - format: ['heka', 'pretty'], - default: 'heka', - }, - level: { - env: 'LOG_LEVEL', - default: 'debug', - }, - debug: { - env: 'LOG_DEBUG', - default: false, - }, - }, - sentry: { - dsn: { - doc: 'Sentry DSN for error and log reporting', - default: '', - format: 'String', - env: 'SENTRY_DSN', - }, - env: { - doc: 'Environment name to report to sentry', - default: 'local', - format: ['local', 'ci', 'dev', 'stage', 'prod'], - env: 'SENTRY_ENV', - }, - sampleRate: { - doc: 'Rate at which sentry errors are captured.', - default: 1.0, - format: 'Number', - env: 'SENTRY_SAMPLE_RATE', - }, - serverName: { - doc: 'Name used by sentry to identify the server.', - default: 'browserid-verifier', - format: 'String', - env: 'SENTRY_SERVER_NAME', - }, - tracesSampleRate: { - doc: 'Rate at which sentry traces are captured', - default: 0, - format: 'Number', - env: 'SENTRY_TRACES_SAMPLE_RATE', - }, - }, - testServiceFailure: { - doc: '(testing only) trigger a service failure in the verifier', - format: Boolean, - default: false, - env: 'TEST_SERVICE_FAILURE', - }, - }); - - // load environment dependent configuration - if (process.env.CONFIG_FILES) { - var files = process.env.CONFIG_FILES.split(','); - files.forEach(function (file) { - conf.loadFile(file); - }); - } - - // validation configuration - conf.validate(); - - module.exports = conf; - - process.nextTick(function () { - require('./log')('config').debug( - 'current configuration:', - JSON.stringify(conf.get(), null, 2) - ); - }); -} - -loadConf(); - -// command line options - -var args = require('optimist') - .alias('h', 'help') - .describe('h', 'display this usage message') - .alias('c', 'config') - .describe('c', 'Display current configuration.'); - -var argv = args.argv; - -if (argv.h) { - args.showHelp(); - process.exit(1); -} - -if (argv.c) { - console.log(module.exports.get()); - process.exit(0); -} diff --git a/packages/browserid-verifier/lib/log/index.js b/packages/browserid-verifier/lib/log/index.js deleted file mode 100644 index 2fd7297ca3..0000000000 --- a/packages/browserid-verifier/lib/log/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -module.exports = require('mozlog'); - -module.exports.config(require('../config').get('logging')); diff --git a/packages/browserid-verifier/lib/server.js b/packages/browserid-verifier/lib/server.js deleted file mode 100644 index 6b050271d0..0000000000 --- a/packages/browserid-verifier/lib/server.js +++ /dev/null @@ -1,186 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const Sentry = require('@sentry/node'); - -const express = require('express'), - bodyParser = require('body-parser'), - morgan = require('morgan'), - http = require('http'), - toobusy = require('toobusy-js'), - log = require('./log')('server'), - summary = require('./summary'), - config = require('./config'), - CCVerifier = require('./ccverifier'), - version = require('./version'), - v1api = require('./v1'), - v2api = require('./v2'); - -const { - tagCriticalEvent, - buildSentryConfig, - tagFxaName, -} = require('fxa-shared/sentry'); - -log.debug('starting'); - -var app = express(); -var server = http.createServer(app); - -// Initialize Sentry -const sentryConfig = config.get('sentry'); -if (sentryConfig.dsn) { - const release = require('../package.json').version; - const opts = buildSentryConfig( - { - sentry: sentryConfig, - release, - }, - log - ); - Sentry.init({ - ...opts, - beforeSend(event, _hint) { - event = tagCriticalEvent(event); - event = tagFxaName(event, opts.serverName); - return event; - }, - }); - Sentry.setupExpressErrorHandler(app); -} - -var verifier = new CCVerifier({ - httpTimeout: config.get('httpTimeout'), - insecureSSL: config.get('insecureSSL'), - forceInsecureLookupOverHTTP: config.get('forceInsecureLookupOverHTTP'), - testServiceFailure: config.get('testServiceFailure'), -}); - -// handle shutdown -function shutdown(signal) { - return function () { - log.info('shutdown', { signal }); - toobusy.shutdown(); - verifier.shutdown(); - server.close(); - }; -} - -['SIGINT', 'SIGTERM', 'SIGQUIT'].forEach(function (signal) { - process.on(signal, shutdown(signal.substr(3))); -}); - -// header manipulation -app.use(function (req, res, next) { - // no caching allowed, this is an API server. - res.setHeader( - 'Cache-Control', - 'private, no-cache, no-store, must-revalidate, max-age=0' - ); - - // security headers - res.setHeader('X-XSS-Protection', '1; mode=block'); - res.setHeader('X-Content-Type-Options', 'nosniff'); - res.setHeader('X-Frame-Options', 'DENY'); - res.setHeader('Strict-Transport-Security', 'max-age=31536000'); - res.setHeader( - 'Content-Security-Policy', - "default-src 'none'; frame-ancestors 'none'; report-uri /__cspreport__" - ); - - // shave some needless bytes - res.removeHeader('X-Powered-By'); - res.setHeader('Connection', 'close'); - next(); -}); - -// health checks - registered before all other middleware. -app.use(function (req, res, next) { - switch (req.url) { - case '/status': - res.setHeader('Content-Type', 'text/plain'); - res.send('OK'); - break; - case '/__heartbeat__': - case '/__lbheartbeat__': - res.send({}); - break; - case '/__version__': - version.getVersionInfo(function (info) { - res.send(info); - }); - break; - default: - next(); - } -}); - -// return 503 when the server is too busy -toobusy.maxLag(config.get('toobusy.maxLag')); -app.use(function (req, res, next) { - if (toobusy()) { - log.warn('tooBusy'); - res.json(503, { status: 'failure', reason: 'too busy' }); - } else { - next(); - } -}); - -// log HTTP requests -app.use( - morgan('common', { - stream: { - write: function (message) { - // trim newlines as our logger inserts them for us. - if (typeof message === 'string') { - message = message.trim(); - } - log.info('message', { message }); - }, - }, - }) -); - -// log summary - GH24 -app.use(summary()); - -app.use(bodyParser.json({ limit: '10kb' })); -app.use(bodyParser.urlencoded({ limit: '10kb' })); - -app.post('/verify', v1api.bind(v1api, verifier)); -app.post('/', v1api.bind(v1api, verifier)); -app.post('/v2', v2api.bind(v2api, verifier)); - -function wrongMethod(req, res) { - return res.sendStatus(405); -} - -['/verify', '/', '/v2'].forEach(function (route) { - app.get(route, wrongMethod); -}); - -if (sentryConfig.dsn) { - // Send errors to sentry. - app.use(Sentry.Handlers.errorHandler()); -} - -// error handler goes last, to receive any errors from previous middleware -app.use(function (err, req, res, next) { - if (err) { - if (err.status) { - res.statusCode = err.status; - } else { - res.statusCode = 500; - log.error(err); - } - res.end(); - } - next(); -}); - -server.listen(config.get('port'), config.get('ip'), function () { - log.info('running', { - url: 'http://' + server.address().address + ':' + server.address().port, - }); -}); diff --git a/packages/browserid-verifier/lib/summary.js b/packages/browserid-verifier/lib/summary.js deleted file mode 100644 index 664eef7dcc..0000000000 --- a/packages/browserid-verifier/lib/summary.js +++ /dev/null @@ -1,34 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const logger = require('./log')('summary'); - -module.exports = function middlewareFactory() { - return function summary(req, res, next) { - function log() { - res.removeListener('finish', log); - res.removeListener('close', log); - - var summary = res._summary; - summary.code = res.statusCode; - - logger.info('info', summary); - } - - res._summary = {}; - - // Add useful request-level info to the summary automatically. - res._summary.agent = req.headers['user-agent'] || ''; - var xff = (req.headers['x-forwarded-for'] || '').split(/\s*,\s*/); - xff.push(req.connection.remoteAddress); - res._summary.remoteAddressChain = xff.filter(function (x) { - return x; - }); - - res.on('finish', log); - res.on('close', log); - - next(); - }; -}; diff --git a/packages/browserid-verifier/lib/v1.js b/packages/browserid-verifier/lib/v1.js deleted file mode 100644 index 86b18effd5..0000000000 --- a/packages/browserid-verifier/lib/v1.js +++ /dev/null @@ -1,129 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const log = require('./log')('v1'), - config = require('./config'), - _ = require('underscore'), - util = require('util'); - -function verify(verifier, req, res) { - req.query = req.query || {}; - req.body = req.body || {}; - - res._summary.api = 1; - - var assertion = req.query.assertion - ? req.query.assertion - : req.body.assertion; - var audience = req.query.audience ? req.query.audience : req.body.audience; - var forceIssuer = req.query.experimental_forceIssuer - ? req.query.experimental_forceIssuer - : req.body.experimental_forceIssuer; - var allowUnverified = req.query.experimental_allowUnverified - ? req.query.experimental_allowUnverified - : req.body.experimental_allowUnverified; - - res._summary.rp = audience; - - if (!(assertion && audience)) { - // why couldn't we extract these guys? Is it because the request parameters weren't encoded as we expect? GH-643 - const want_ct = ['application/x-www-form-urlencoded', 'application/json']; - var reason; - var ct = 'none'; - try { - ct = req.headers['content-type'] || ct; - if (ct.indexOf(';') !== -1) { - ct = ct.substr(0, ct.indexOf(';')); - } - if (want_ct.indexOf(ct) === -1) { - throw new Error('wrong content type'); - } - } catch (e) { - reason = util.format( - 'Unsupported Content-Type: %s (expected ' + want_ct.join(' or ') + ')', - ct - ); - log.info('verify', { - result: 'failure', - reason: reason, - rp: audience, - }); - res._summary.err = e; - return res.json(415, { status: 'failure', reason: reason }); - } - reason = util.format( - 'missing %s parameter', - assertion ? 'audience' : 'assertion' - ); - log.info('verify', { - result: 'failure', - reason: reason, - rp: audience, - }); - res._summary.err = reason; - return res.json(400, { status: 'failure', reason: reason }); - } - - var trustedIssuers = []; - if (forceIssuer) { - trustedIssuers.push(forceIssuer); - } - - var startTime = new Date(); - verifier.verify( - { - assertion: assertion, - audience: audience, - trustedIssuers: trustedIssuers, - fallback: config.get('fallback'), - }, - function (err, r) { - var reqTime = new Date() - startTime; - log.info('assertion_verification_time', { reqTime }); - res._summary.assertion_verification_time = reqTime; - - if (err) { - if (typeof err !== 'string') { - err = 'unexpected error'; - } - if (err.indexOf('compute cluster') === 0) { - log.info('service_failure'); - res.json(503, { status: 'failure', reason: 'service unavailable' }); - } else { - log.info('assertion_failure'); - res.json(200, { status: 'failure', reason: err }); //Could be 500 or 200 OK if invalid cert - } - res._summary.err = err; - log.info('verify', { - result: 'failure', - reason: err, - assertion: assertion, - trustedIssuers: trustedIssuers, - rp: audience, - }); - } else { - if (allowUnverified) { - if (r.idpClaims && r.idpClaims['unverified-email']) { - r['unverified-email'] = r.idpClaims['unverified-email']; - } - } - - res.json( - _.extend(r, { - status: 'okay', - audience: audience, // NOTE: we return the audience formatted as the RP provided it, not normalized in any way. - expires: new Date(r.expires).valueOf(), - }) - ); - - log.info('verify', { - result: 'success', - rp: r.audience, - }); - } - } - ); -} - -module.exports = verify; diff --git a/packages/browserid-verifier/lib/v2.js b/packages/browserid-verifier/lib/v2.js deleted file mode 100644 index 80f3027e36..0000000000 --- a/packages/browserid-verifier/lib/v2.js +++ /dev/null @@ -1,129 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const log = require('./log')('v2'), - config = require('./config'), - _ = require('underscore'), - util = require('util'); - -function validateTrustedIssuers(obj) { - var ti = obj.trustedIssuers; - if (!ti) { - return []; - } - if (!_.isArray(ti)) { - throw { - reason: 'trusted issuers must be an array', - code: 400, - }; - } - - ti.forEach(function (hostname) { - if (typeof hostname !== 'string') { - throw { - reason: 'trusted issuers must be an array of strings', - code: 400, - }; - } - }); - return ti; -} - -function verify(verifier, req, res) { - res._summary.api = 2; - try { - // content-type must be application/json - var ct = req.headers['content-type'] || 'none'; - if (ct.indexOf('application/json') !== 0) { - throw { - reason: util.format( - 'Unsupported Content-Type: %s (expected application/json)', - ct - ), - code: 415, - }; - } - - req.body = req.body || {}; - res._summary.rp = req.body.audience; - - // assertion and audience are required - ['assertion', 'audience'].forEach(function (field) { - if (!req.body[field]) { - throw { - reason: util.format('missing %s parameter', field), - code: 400, - }; - } - }); - - // validate and extract trusted issuers - var trustedIssuers = validateTrustedIssuers(req.body); - - var startTime = new Date(); - verifier.verify( - { - assertion: req.body.assertion, - audience: req.body.audience, - trustedIssuers: trustedIssuers, - fallback: config.get('fallback'), - }, - function (err, r) { - var reqTime = new Date() - startTime; - log.info('assertion_verification_time', { reqTime }); - res._summary.assertion_verification_time = reqTime; - - if (err) { - if (typeof err !== 'string') { - err = 'unexpected error'; - } - if (err.indexOf('compute cluster') === 0) { - log.info('service_failure'); - res.json(503, { status: 'failure', reason: 'service unavailable' }); - } else { - log.info('assertion_failure'); - res.json(200, { status: 'failure', reason: err }); //Could be 500 or 200 OK if invalid cert - } - res._summary.err = err; - log.info('verify', { - result: 'failure', - reason: err, - assertion: req.body.assertion, - trustedIssuers: trustedIssuers, - rp: req.body.audience, - }); - } else { - res.json( - _.extend(r, { - status: 'okay', - audience: req.body.audience, // NOTE: we return the audience formatted as the RP provided it, not normalized in any way. - expires: new Date(r.expires).valueOf(), - }) - ); - - log.info('verify', { - result: 'success', - rp: r.audience, - }); - } - } - ); - } catch (err) { - var reason = err.reason ? err.reason : err.toString(); - - res._summary.err = reason; - log.info('verify', { - result: 'failure', - reason: reason, - rp: req.body.audience, - }); - - res.json(err.code ? err.code : 500, { - status: 'failure', - reason: reason, - }); - } -} - -module.exports = verify; diff --git a/packages/browserid-verifier/lib/version.js b/packages/browserid-verifier/lib/version.js deleted file mode 100644 index b6092be6b8..0000000000 --- a/packages/browserid-verifier/lib/version.js +++ /dev/null @@ -1,71 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const path = require('path'), - cp = require('child_process'); - -const UNKNOWN = 'unknown'; - -// For production builds, we write version into to a json -// file for easy reporting in /__version__ endpoint. -var commitHash; -var sourceRepo; -const version = require('../package.json').version; -try { - var versionJson = path.join(__dirname, '..', 'version.json'); - var info = require(versionJson); - commitHash = info.version.hash; - sourceRepo = info.version.source; -} catch (e) { - /* ignore */ -} - -module.exports = { - getVersionInfo: function getVersionInfo(cb) { - if (commitHash) { - return cb({ - version: version, - commit: commitHash, - source: sourceRepo, - }); - } - // ignore errors and default to 'unknown' if not found - var gitDir = path.resolve(__dirname, '..', '..', '..', '.git'); - cp.exec('git rev-parse HEAD', { cwd: gitDir }, function (err, stdout1) { - if (err != null) { - console.error('Error getting git commit hash: ' + err.message); - return cb({ - version: version, - commit: UNKNOWN, - source: UNKNOWN, - }); - } - - var configPath = path.join(gitDir, 'config'); - var cmd = 'git config --get remote.origin.url'; - cp.exec( - cmd, - { env: { GIT_CONFIG: configPath } }, - function (err, stdout2) { - if (err != null) { - console.error('Error getting git config: ' + err.message); - return cb({ - version: version, - commit: UNKNOWN, - source: UNKNOWN, - }); - } - - commitHash = (stdout1 && stdout1.trim()) || UNKNOWN; - sourceRepo = (stdout2 && stdout2.trim()) || UNKNOWN; - return cb({ - version: version, - commit: commitHash, - source: sourceRepo, - }); - } - ); - }); - }, -}; diff --git a/packages/browserid-verifier/loadtest/Makefile b/packages/browserid-verifier/loadtest/Makefile deleted file mode 100644 index 728c3c4d97..0000000000 --- a/packages/browserid-verifier/loadtest/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -SERVER_URL = https://verifier.stage.mozaws.net - -# Hackety-hack around OSX system python bustage. -# The need for this should go away with a future osx/xcode update. -ARCHFLAGS = -Wno-error=unused-command-line-argument-hard-error-in-future -INSTALL = ARCHFLAGS=$(ARCHFLAGS) ./venv/bin/pip install - -.PHONY: build clean test bench megabench - -# Build virtualenv, to ensure we have all the dependencies. -build: - virtualenv --no-site-packages ./venv - $(INSTALL) pexpect - $(INSTALL) gevent - $(INSTALL) https://github.com/mozilla-services/loads/archive/master.zip - $(INSTALL) PyBrowserID - -# Clean all the things installed by `make build`. -clean: - rm -rf ./venv *.pyc - -# Run a single test from the venv machine, for sanity-checking. -test: - ./venv/bin/loads-runner --config=./config/test.ini --server-url=$(SERVER_URL) loadtest.VerifierLoadTest.test_verifier - -# Run a bench of 20 concurrent users. -bench: - ./venv/bin/loads-runner --config=./config/bench.ini --server-url=$(SERVER_URL) loadtest.VerifierLoadTest.test_verifier - -# Run a much bigger bench, by submitting to broker in AWS. -megabench: - ./venv/bin/loads-runner --config=./config/megabench.ini --user-id=$(USER) --server-url=$(SERVER_URL) loadtest.VerifierLoadTest.test_verifier - -# Purge any currently-running loadtest runs. -purge: - ./venv/bin/loads-runner --config=./config/megabench.ini --purge-broker diff --git a/packages/browserid-verifier/loadtest/README.txt b/packages/browserid-verifier/loadtest/README.txt deleted file mode 100644 index c74522e3b6..0000000000 --- a/packages/browserid-verifier/loadtest/README.txt +++ /dev/null @@ -1,26 +0,0 @@ -This directory contains some very simple loadtests, written using -the "loads" framework: - - https://github.com/mozilla/loads - - -To run them, you will need the following dependencies: - - * Python development files (e.g. python-dev or python-devel package) - * Virtualenv (e.g. python-virtualenv package) - * ZeroMQ development files (e.g. libzmq-dev package) - * (for megabench) ssh access to the mozilla loads cluster - -Then do the following: - - $> make build # installs local environment with all dependencies - $> make test # runs a single test, to check that everything's working - $> make bench # runs a longer, higher-concurrency test. - $> make megabench # runs a really-long, really-high-concurrency test - # using https://loads.services.mozilla.com - -To hit a specific server you can specify the SERVER_URL make variable, like -this: - - $> make test SERVER_URL=https://verifier.stage.mozaws.net - diff --git a/packages/browserid-verifier/loadtest/config/bench.ini b/packages/browserid-verifier/loadtest/config/bench.ini deleted file mode 100644 index 4b644c9b41..0000000000 --- a/packages/browserid-verifier/loadtest/config/bench.ini +++ /dev/null @@ -1,3 +0,0 @@ -[loads] -users = 20 -duration = 300 diff --git a/packages/browserid-verifier/loadtest/config/megabench.ini b/packages/browserid-verifier/loadtest/config/megabench.ini deleted file mode 100644 index 1ef047dca5..0000000000 --- a/packages/browserid-verifier/loadtest/config/megabench.ini +++ /dev/null @@ -1,9 +0,0 @@ -[loads] -users = 20 -duration = 1800 -include_file = ./loadtest.py -python_dep = PyBrowserID -agents = 5 -detach = true -observer = irc -ssh = ubuntu@loads.services.mozilla.com diff --git a/packages/browserid-verifier/loadtest/config/test.ini b/packages/browserid-verifier/loadtest/config/test.ini deleted file mode 100644 index f61120d2a8..0000000000 --- a/packages/browserid-verifier/loadtest/config/test.ini +++ /dev/null @@ -1,3 +0,0 @@ -[loads] -hits = 1 -users = 1 diff --git a/packages/browserid-verifier/loadtest/loadtest.py b/packages/browserid-verifier/loadtest/loadtest.py deleted file mode 100644 index 2be9014717..0000000000 --- a/packages/browserid-verifier/loadtest/loadtest.py +++ /dev/null @@ -1,129 +0,0 @@ - -import json -import time -import random - -import browserid -import browserid.jwt -from browserid.tests.support import make_assertion - -from loads import TestCase - - -PERCENT_INVALID_REQUESTS = 5 - -ONE_YEAR = 60 * 60 * 24 * 365 - -MOCKMYID_DOMAIN = "mockmyid.s3-us-west-2.amazonaws.com" -MOCKMYID_PRIVATE_KEY = browserid.jwt.DS128Key({ - "algorithm": "DS", - "x": "385cb3509f086e110c5e24bdd395a84b335a09ae", - "y": "738ec929b559b604a232a9b55a5295afc368063bb9c20fac4e53a74970a4db795" - "6d48e4c7ed523405f629b4cc83062f13029c4d615bbacb8b97f5e56f0c7ac9bc1" - "d4e23809889fa061425c984061fca1826040c399715ce7ed385c4dd0d40225691" - "2451e03452d3c961614eb458f188e3e8d2782916c43dbe2e571251ce38262", - "p": "ff600483db6abfc5b45eab78594b3533d550d9f1bf2a992a7a8daa6dc34f8045a" - "d4e6e0c429d334eeeaaefd7e23d4810be00e4cc1492cba325ba81ff2d5a5b305a" - "8d17eb3bf4a06a349d392e00d329744a5179380344e82a18c47933438f891e22a" - "eef812d69c8f75e326cb70ea000c3f776dfdbd604638c2ef717fc26d02e17", - "q": "e21e04f911d1ed7991008ecaab3bf775984309c3", - "g": "c52a4a0ff3b7e61fdf1867ce84138369a6154f4afa92966e3c827e25cfa6cf508b" - "90e5de419e1337e07a2e9e2a3cd5dea704d175f8ebf6af397d69e110b96afb17c7" - "a03259329e4829b0d03bbc7896b15b4ade53e130858cc34d96269aa89041f40913" - "6c7242a38895c9d5bccad4f389af1d7a4bd1398bd072dffa896233397a", -}) - - -INVALID_PRIVATE_KEY = browserid.jwt.DS128Key({ - "algorithm": "DS", - "x": "abcdef0123456789abcdef0123456789abcdef01", - "y": "738ec929b559b604a232a9b55a5295afc368063bb9c20fac4e53a74970a4db795" - "6d48e4c7ed523405f629b4cc83062f13029c4d615bbacb8b97f5e56f0c7ac9bc1" - "d4e23809889fa061425c984061fca1826040c399715ce7ed385c4dd0d40225691" - "2451e03452d3c961614eb458f188e3e8d2782916c43dbe2e571251ce38262", - "p": "ff600483db6abfc5b45eab78594b3533d550d9f1bf2a992a7a8daa6dc34f8045a" - "d4e6e0c429d334eeeaaefd7e23d4810be00e4cc1492cba325ba81ff2d5a5b305a" - "8d17eb3bf4a06a349d392e00d329744a5179380344e82a18c47933438f891e22a" - "eef812d69c8f75e326cb70ea000c3f776dfdbd604638c2ef717fc26d02e17", - "q": "e21e04f911d1ed7991008ecaab3bf775984309c3", - "g": "c52a4a0ff3b7e61fdf1867ce84138369a6154f4afa92966e3c827e25cfa6cf508b" - "90e5de419e1337e07a2e9e2a3cd5dea704d175f8ebf6af397d69e110b96afb17c7" - "a03259329e4829b0d03bbc7896b15b4ade53e130858cc34d96269aa89041f40913" - "6c7242a38895c9d5bccad4f389af1d7a4bd1398bd072dffa896233397a", -}) - - -class VerifierLoadTest(TestCase): - - server_url = "https://verifier.stage.mozaws.net" - - def _make_assertion(self, email=None, audience=None, **kwds): - if email is None: - email = "user%d@%s" % (random.randint(0, 1000000), MOCKMYID_DOMAIN) - if audience is None: - audience = "https://secret.mozilla.com" - if "exp" not in kwds: - kwds["exp"] = int((time.time() + ONE_YEAR) * 1000) - if "issuer" not in kwds: - kwds["issuer"] = MOCKMYID_DOMAIN - if "issuer_keypair" not in kwds: - kwds["issuer_keypair"] = (None, MOCKMYID_PRIVATE_KEY) - return make_assertion(email, audience, **kwds) - - def _verify_assertion(self, assertion, audience=None, **kwds): - if assertion is None: - assertion = self._make_assertion() - if audience is None: - audience = "https://secret.mozilla.com" - body = { - "assertion": assertion, - "audience": audience, - } - body.update(kwds) - body = json.dumps(body) - r = self.session.post(self.server_url + "/v2", body, headers={ - "Content-Type": "application/json" - }) - self.assertEquals(r.status_code, 200) - return json.loads(r.content) - - def test_verifier(self): - if random.randint(0, 99) < PERCENT_INVALID_REQUESTS: - self.test_invalid_assertion() - else: - self.test_valid_assertion() - - def test_valid_assertion(self): - assertion = self._make_assertion() - data = self._verify_assertion(assertion) - self.assertEquals(data["status"], "okay") - - def test_invalid_assertion(self): - # Randomly pick and run a _test_invalid_assertion_() method. - tests = [] - for nm in dir(self): - if nm.startswith("_test_invalid_assertion"): - tests.append(getattr(self, nm)) - random.choice(tests)() - - def _test_invalid_assertion_nonprimary(self): - assertion = self._make_assertion("test@mozilla.com") - data = self._verify_assertion(assertion) - self.assertEquals(data["status"], "failure") - - def _test_invalid_assertion_expired(self): - exp = int(time.time() - ONE_YEAR) * 1000, - assertion = self._make_assertion(exp=exp) - data = self._verify_assertion(assertion) - self.assertEquals(data["status"], "failure") - - def _test_invalid_assertion_wrongissuer(self): - assertion = self._make_assertion(issuer="login.mozilla.org") - data = self._verify_assertion(assertion) - self.assertEquals(data["status"], "failure") - - def _test_invalid_assertion_wrongkey(self): - issuer_keypair = (None, INVALID_PRIVATE_KEY) - assertion = self._make_assertion(issuer_keypair=issuer_keypair) - data = self._verify_assertion(assertion) - self.assertEquals(data["status"], "failure") diff --git a/packages/browserid-verifier/package.json b/packages/browserid-verifier/package.json deleted file mode 100644 index 0b94cf9e58..0000000000 --- a/packages/browserid-verifier/package.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "author": "Mozilla (https://mozilla.org/)", - "license": "MPL-2.0", - "name": "browserid-verifier", - "description": "A node.js verification server for BrowserID assertions.", - "version": "0.0.0", - "repository": { - "type": "git", - "url": "https://github.com/mozilla/fxa.git" - }, - "homepage": "https://github.com/mozilla/fxa/tree/main/packages/browserid-verifier/", - "bugs": "https://github.com/mozilla/fxa/issues/", - "main": "lib/server.js", - "dependencies": { - "async": "3.2.4", - "body-parser": "^1.20.3", - "browserid-local-verify": "0.5.2", - "compute-cluster": "0.0.9", - "convict": "^6.2.4", - "convict-format-with-moment": "^6.2.0", - "convict-format-with-validator": "^6.2.0", - "express": "^4.21.2", - "intel": "1.2.0", - "morgan": "^1.10.0", - "mozlog": "^3.0.2", - "optimist": "0.6.1", - "toobusy-js": "0.5.1", - "underscore": "^1.13.1" - }, - "devDependencies": { - "audit-filter": "0.5.0", - "eslint": "^7.32.0", - "fxa-shared": "workspace:*", - "mocha": "^10.4.0", - "pm2": "^5.4.2", - "prettier": "^3.5.3", - "request": "^2.88.2", - "should": "13.2.3", - "temp": "0.9.4", - "walk": "^2.3.15" - }, - "scripts": { - "audit": "npm audit --json | audit-filter --nsp-config=.nsprc --audit=-", - "lint": "eslint .", - "test": "mocha --exit -t 5000 -R spec tests/*.js", - "format": "prettier --write --config ../../_dev/.prettierrc '**'", - "start": "pm2 start pm2.config.js", - "stop": "pm2 stop pm2.config.js", - "restart": "pm2 restart pm2.config.js", - "delete": "pm2 delete pm2.config.js" - }, - "nx": { - "tags": [ - "scope:server" - ] - } -} diff --git a/packages/browserid-verifier/pm2.config.js b/packages/browserid-verifier/pm2.config.js deleted file mode 100644 index 0f7e65f474..0000000000 --- a/packages/browserid-verifier/pm2.config.js +++ /dev/null @@ -1,29 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const PATH = process.env.PATH.split(':') - .filter((p) => !p.includes(process.env.TMPDIR)) - .join(':'); - -module.exports = { - apps: [ - { - name: 'browserid', - script: 'node server.js', - cwd: __dirname, - env: { - PATH, - PORT: '5050', - IP_ADDRESS: '0.0.0.0', - FORCE_INSECURE_LOOKUP_OVER_HTTP: 'true', - SENTRY_ENV: 'local', - SENTRY_DSN: process.env.SENTRY_DSN_BROWSERID, - }, - filter_env: ['npm_'], - max_restarts: '1', - min_uptime: '2m', - time: true, - }, - ], -}; diff --git a/packages/browserid-verifier/server.js b/packages/browserid-verifier/server.js deleted file mode 100755 index b0f0653e22..0000000000 --- a/packages/browserid-verifier/server.js +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env node - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -require('./lib/server.js'); diff --git a/packages/browserid-verifier/tests/audience.js b/packages/browserid-verifier/tests/audience.js deleted file mode 100644 index 2f0d9f616c..0000000000 --- a/packages/browserid-verifier/tests/audience.js +++ /dev/null @@ -1,102 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* global describe,it,before,after */ - -var IdP = require('browserid-local-verify/testing').IdP, - Client = require('browserid-local-verify/testing').Client, - Verifier = require('./lib/verifier.js'), - should = require('should'), - shouldReturnSecurityHeaders = require('./lib/should-return-security-headers.js'), - request = require('request'); - -describe('audience tests', function () { - var verifier = new Verifier(); - var idp = new IdP(); - var client; - - before(async () => { - await new Promise((resolve) => idp.start(resolve)); - await new Promise((resolve) => verifier.start(resolve)); - client = new Client({ idp: idp }); - }); - - after(async () => { - await new Promise((resolve) => verifier.stop(resolve)); - await new Promise((resolve) => idp.stop(resolve)); - }); - - var assertion; - - it('test assertion should be created', function (done) { - client.assertion({ audience: 'http://example.com' }, function (err, ass) { - assertion = ass; - done(err); - }); - }); - - function submitWithAudience(audience, cb) { - request( - { - method: 'post', - url: verifier.url(), - json: true, - body: { - assertion: assertion, - audience: audience, - }, - }, - cb - ); - } - - it('should verify with complete audience', function (done) { - submitWithAudience('http://example.com', function (err, r) { - should.not.exist(err); - 'okay'.should.equal(r.body.status); - shouldReturnSecurityHeaders(r); - done(); - }); - }); - - it('should fail to verify with different domain as audience', function (done) { - submitWithAudience('incorrect.com', function (err, r) { - should.not.exist(err); - r.body.status.should.equal('failure'); - r.body.reason.should.equal('audience mismatch: domain mismatch'); - shouldReturnSecurityHeaders(r); - done(err); - }); - }); - - it('should fail to verify with different port', function (done) { - submitWithAudience('http://example.com:8080', function (err, r) { - should.not.exist(err); - r.body.status.should.equal('failure'); - r.body.reason.should.equal('audience mismatch: port mismatch'); - shouldReturnSecurityHeaders(r); - done(err); - }); - }); - - it('should fail to verify with incorrect scheme', function (done) { - submitWithAudience('https://example.com', function (err, r) { - should.not.exist(err); - r.body.status.should.equal('failure'); - r.body.reason.should.equal('audience mismatch: scheme mismatch'); - shouldReturnSecurityHeaders(r); - done(err); - }); - }); - - it('should fail to verify if audience is missing', function (done) { - submitWithAudience(undefined, function (err, r) { - should.not.exist(err); - r.body.status.should.equal('failure'); - r.body.reason.should.equal('missing audience parameter'); - shouldReturnSecurityHeaders(r); - done(err); - }); - }); -}); diff --git a/packages/browserid-verifier/tests/basic.js b/packages/browserid-verifier/tests/basic.js deleted file mode 100644 index d051688514..0000000000 --- a/packages/browserid-verifier/tests/basic.js +++ /dev/null @@ -1,91 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* global describe,it,before,after */ - -var IdP = require('browserid-local-verify/testing').IdP, - Client = require('browserid-local-verify/testing').Client, - Verifier = require('./lib/verifier.js'), - should = require('should'), - shouldReturnSecurityHeaders = require('./lib/should-return-security-headers.js'), - request = require('request'); - -describe('basic verifier test', function () { - var idp = new IdP(); - var verifier = new Verifier(); - - before(async () => { - await new Promise((resolve) => idp.start(resolve)); - await new Promise((resolve) => verifier.start(resolve)); - }); - - after(async () => { - await new Promise((resolve) => verifier.stop(resolve)); - await new Promise((resolve) => idp.stop(resolve)); - }); - - it('should verify an assertion', function (done) { - var client = new Client({ idp: idp }); - - client.assertion( - { audience: 'http://example.com' }, - function (err, assertion) { - should.not.exist(err); - request( - { - method: 'post', - url: verifier.url(), - json: true, - body: { - assertion: assertion, - audience: 'http://example.com', - }, - }, - function (err, r) { - should.not.exist(err); - r.body.email.should.equal(client.email()); - r.body.issuer.should.equal(idp.domain()); - r.body.status.should.equal('okay'); - r.body.audience.should.equal('http://example.com'); - r.statusCode.should.equal(200); - shouldReturnSecurityHeaders(r); - done(); - } - ); - } - ); - }); - - it('should return 405 for GET requests', function (done) { - request( - { - method: 'get', - url: verifier.url(), - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(405); - shouldReturnSecurityHeaders(r); - done(); - } - ); - }); - - it('should handle any errors', function (done) { - request( - { - method: 'post', - url: verifier.url(), - body: "{ 'a' }", - headers: { 'content-type': 'application/json' }, - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(400); - shouldReturnSecurityHeaders(r); - done(); - } - ); - }); -}); diff --git a/packages/browserid-verifier/tests/cascading-config.js b/packages/browserid-verifier/tests/cascading-config.js deleted file mode 100644 index a18e92bd49..0000000000 --- a/packages/browserid-verifier/tests/cascading-config.js +++ /dev/null @@ -1,60 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* global describe,it */ - -const should = require('should'); - -var Verifier = require('./lib/verifier.js'), - async = require('async'), - temp = require('temp'), - fs = require('fs'); - -describe('cascading configuration files', function () { - var verifier; - - it('create a couple configuration files', function (done) { - var aPath = temp.path({ suffix: '.json' }), - bPath = temp.path({ suffix: '.json' }); - - // because "b" is specified later, it should over-ride "a" - verifier = new Verifier({ - files: aPath + ',' + bPath, - }); - - async.parallel( - [ - function (cb) { - fs.writeFile( - aPath, - JSON.stringify({ fallback: 'a.example.com' }), - cb - ); - }, - function (cb) { - fs.writeFile( - bPath, - JSON.stringify({ fallback: 'b.example.com' }), - cb - ); - }, - ], - done - ); - }); - - it('test servers should start and finish cleanly', async () => { - verifier.buffer(true); - should(verifier.process).equal(undefined); - await new Promise((resolve, error) => verifier.start(resolve)); - should(verifier.process).not.equal(null); - await new Promise((resolve, error) => verifier.stop(resolve)); - should(verifier.process).equal(null); - }); - - it('verifier should have determined proper configuration', () => { - verifier.buffer().indexOf('a.example.com').should.equal(-1); - verifier.buffer().indexOf('b.example.com').should.not.equal(-1); - }); -}); diff --git a/packages/browserid-verifier/tests/content-type.js b/packages/browserid-verifier/tests/content-type.js deleted file mode 100644 index 0826482a93..0000000000 --- a/packages/browserid-verifier/tests/content-type.js +++ /dev/null @@ -1,228 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* global describe,it,before,after */ - -var IdP = require('browserid-local-verify/testing').IdP, - Client = require('browserid-local-verify/testing').Client, - Verifier = require('./lib/verifier.js'), - should = require('should'), - shouldReturnSecurityHeaders = require('./lib/should-return-security-headers.js'), - request = require('request'); - -describe('content-type tests', function () { - var verifier = new Verifier(); - var idp = new IdP(); - var client; - - before(async () => { - await new Promise((resolve) => idp.start(resolve)); - await new Promise((resolve) => verifier.start(resolve)); - client = new Client({ idp: idp }); - }); - - after(async () => { - await new Promise((resolve) => verifier.stop(resolve)); - await new Promise((resolve) => idp.stop(resolve)); - }); - - var assertion; - - it('test assertion should be created', function (done) { - client.assertion({ audience: 'http://example.com' }, function (err, ass) { - assertion = ass; - done(err); - }); - }); - - it('(v2 api) should fail to verify when content-type is unsupported', function (done) { - request( - { - method: 'post', - url: verifier.url(), - headers: { - 'Content-Type': 'text/plain', - }, - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(415); - (function () { - r.body = JSON.parse(r.body); - }.should.not.throw()); - r.body.status.should.equal('failure'); - r.body.reason.should.startWith('Unsupported Content-Type: text/plain'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - }); - - it('(v2 api) should fail to verify when content-type is not specified', function (done) { - request( - { - method: 'post', - url: verifier.url(), - headers: {}, - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(415); - (function () { - r.body = JSON.parse(r.body); - }.should.not.throw()); - r.body.status.should.equal('failure'); - r.body.reason.should.startWith('Unsupported Content-Type: none'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - }); - - it('(v1 api) should fail to verify when content-type is unsupported', function (done) { - request( - { - method: 'post', - url: verifier.v1url(), - headers: { - 'Content-Type': 'text/plain', - }, - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(415); - (function () { - r.body = JSON.parse(r.body); - }.should.not.throw()); - r.body.status.should.equal('failure'); - r.body.reason.should.startWith('Unsupported Content-Type: text/plain'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - }); - - it('(v1 api) should fail to verify when content-type is not specified', function (done) { - request( - { - method: 'post', - url: verifier.v1url(), - headers: {}, - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(415); - (function () { - r.body = JSON.parse(r.body); - }.should.not.throw()); - r.body.status.should.equal('failure'); - r.body.reason.should.startWith('Unsupported Content-Type: none'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - }); - - it("(v2 api) shouldn't get confused when extended content-types are used", function (done) { - request( - { - method: 'post', - url: verifier.url(), - headers: { - 'Content-Type': 'application/json; charset: utf-8', - }, - body: JSON.stringify({ - assertion: assertion, - }), - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(400); - (function () { - r.body = JSON.parse(r.body); - }.should.not.throw()); - r.body.status.should.equal('failure'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - }); - - it("(v1 api) shouldn't get confused when extended content-types are used", function (done) { - request( - { - method: 'post', - url: verifier.v1url(), - headers: { - 'Content-Type': 'application/json; charset: utf-8', - }, - body: JSON.stringify({ - assertion: assertion, - }), - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(400); - (function () { - r.body = JSON.parse(r.body); - }.should.not.throw()); - r.body.status.should.equal('failure'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - }); - - it("(v2 api) shouldn't support x-www-form-urlencoded", function (done) { - request( - { - method: 'post', - url: verifier.url(), - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: require('querystring').stringify({ - assertion: assertion, - }), - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(415); - (function () { - r.body = JSON.parse(r.body); - }.should.not.throw()); - r.body.status.should.equal('failure'); - r.body.reason.should.startWith('Unsupported Content-Type'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - }); - - it('(v1 api) should support x-www-form-urlencoded', function (done) { - request( - { - method: 'post', - url: verifier.v1url(), - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: require('querystring').stringify({ - assertion: assertion, - }), - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(400); - (function () { - r.body = JSON.parse(r.body); - }.should.not.throw()); - r.body.status.should.equal('failure'); - r.body.reason.should.startWith('missing audience'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - }); -}); diff --git a/packages/browserid-verifier/tests/fallback.js b/packages/browserid-verifier/tests/fallback.js deleted file mode 100644 index bdb18c155e..0000000000 --- a/packages/browserid-verifier/tests/fallback.js +++ /dev/null @@ -1,111 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* global describe,it,before,after */ - -var IdP = require('browserid-local-verify/testing').IdP, - Client = require('browserid-local-verify/testing').Client, - Verifier = require('./lib/verifier.js'), - should = require('should'), - shouldReturnSecurityHeaders = require('./lib/should-return-security-headers.js'), - request = require('request'); - -describe('fallback configuration test', function () { - var idp = new IdP(); - var verifier = new Verifier(); - - before(async function () { - this.timeout(10000); - await new Promise((resolve) => idp.start(resolve)); - verifier.setFallback(idp); - await new Promise((resolve) => verifier.start(resolve)); - }); - - after(async () => { - await new Promise((resolve) => verifier.stop(resolve)); - await new Promise((resolve) => idp.stop(resolve)); - }); - - it('should verify an assertion vouched by the configured fallback', function (done) { - var client = new Client({ - idp: idp, - email: 'lloyd@nonidp.example.com', - }); - - client.assertion( - { - audience: 'http://rp.example.com', - }, - function (err, assertion) { - should.not.exist(err); - request( - { - method: 'post', - url: verifier.url(), - json: true, - body: { - assertion: assertion, - audience: 'http://rp.example.com', - }, - }, - function (err, r) { - should.not.exist(err); - r.body.status.should.equal('okay'); - r.body.email.should.equal(client.email()); - r.body.issuer.should.equal(idp.domain()); - r.body.audience.should.equal('http://rp.example.com'); - r.statusCode.should.equal(200); - shouldReturnSecurityHeaders(r); - done(); - } - ); - } - ); - }); - - it('verifier should restart with cleared fallback', function (done) { - verifier.setFallback(null); - verifier.stop(function (e) { - verifier.start(function (e1) { - done(e || e1); - }); - }); - }); - - it('should fail to verify an assertion when fallback is not configured', function (done) { - var client = new Client({ - idp: idp, - email: 'lloyd@nonidp.example.com', - }); - - client.assertion( - { - audience: 'http://rp.example.com', - }, - function (err, assertion) { - should.not.exist(err); - request( - { - method: 'post', - url: verifier.url(), - json: true, - body: { - assertion: assertion, - audience: 'http://rp.example.com', - }, - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(200); - r.body.status.should.equal('failure'); - // XXX: better error message - r.body.reason.should.startWith('untrusted issuer'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - } - ); - }); -}); diff --git a/packages/browserid-verifier/tests/force-issuer.js b/packages/browserid-verifier/tests/force-issuer.js deleted file mode 100644 index 763f96ef5c..0000000000 --- a/packages/browserid-verifier/tests/force-issuer.js +++ /dev/null @@ -1,131 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* global describe,it,before,after */ - -var IdP = require('browserid-local-verify/testing').IdP, - Client = require('browserid-local-verify/testing').Client, - Verifier = require('./lib/verifier.js'), - should = require('should'), - shouldReturnSecurityHeaders = require('./lib/should-return-security-headers.js'), - request = require('request'); - -describe('force issuer', function () { - var idp = new IdP(); - var fallback = new IdP(); - var client; - var verifier = new Verifier(); - - before(async () => { - await new Promise((resolve, error) => idp.start(resolve)); - await new Promise((resolve, error) => fallback.start(resolve)); - verifier.setFallback(idp); - await new Promise((resolve, error) => verifier.start(resolve)); - }); - - after(async () => { - await new Promise((resolve, error) => verifier.stop(resolve)); - await new Promise((resolve, error) => fallback.stop(resolve)); - await new Promise((resolve, error) => idp.stop(resolve)); - }); - - it('assertion by fallback when primary support is present should fail', function (done) { - // user has an email from idp, but fallback will be used for certificate - client = new Client({ - idp: fallback, - email: 'user@' + idp.domain(), - }); - - client.assertion( - { audience: 'http://example.com' }, - function (err, assertion) { - request( - { - method: 'post', - url: verifier.url(), - json: true, - body: { - assertion: assertion, - audience: 'http://example.com', - }, - }, - function (_, r) { - should.not.exist(err); - r.statusCode.should.equal(200); - r.body.status.should.equal('failure'); - r.body.reason.should.startWith('untrusted issuer'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - } - ); - }); - - it('(v1) forceIssuer should over-ride authority discovery', function (done) { - // user has an email from idp, but fallback will be used for certificate - client = new Client({ - idp: fallback, - email: 'user@' + idp.domain(), - }); - - client.assertion( - { audience: 'http://example.com' }, - function (_, assertion) { - request( - { - method: 'post', - url: verifier.v1url(), - json: true, - body: { - assertion: assertion, - audience: 'http://example.com', - experimental_forceIssuer: fallback.domain(), - }, - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(200); - r.body.status.should.equal('okay'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - } - ); - }); - - it('(v2) trustedIssuers should over-ride authority discovery', function (done) { - // user has an email from idp, but fallback will be used for certificate - client = new Client({ - idp: fallback, - email: 'user@' + idp.domain(), - }); - - client.assertion( - { audience: 'http://example.com' }, - function (_, assertion) { - request( - { - method: 'post', - url: verifier.url(), - json: true, - body: { - assertion: assertion, - audience: 'http://example.com', - trustedIssuers: [fallback.domain()], - }, - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(200); - r.body.status.should.equal('okay'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - } - ); - }); -}); diff --git a/packages/browserid-verifier/tests/health-check.js b/packages/browserid-verifier/tests/health-check.js deleted file mode 100644 index 6f5aa64e1c..0000000000 --- a/packages/browserid-verifier/tests/health-check.js +++ /dev/null @@ -1,99 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* global describe,it,before,after */ - -require('should'); - -var Verifier = require('./lib/verifier.js'), - shouldReturnSecurityHeaders = require('./lib/should-return-security-headers.js'), - request = require('request'); - -describe('health check', function () { - var verifier = new Verifier(); - - before(async () => { - await new Promise((resolve) => verifier.start(resolve)); - }); - - after(async () => { - await new Promise((resolve) => verifier.stop(resolve)); - }); - - it('health check should return OK', function (done) { - request( - { - url: verifier.baseurl() + '/status', - }, - function (err, r) { - r.statusCode.should.equal(200); - r.body.should.equal('OK'); - shouldReturnSecurityHeaders(r); - done(err); - } - ); - }); - - it('__heartbeat__ should return success', function (done) { - request( - { - url: verifier.baseurl() + '/__heartbeat__', - }, - function (err, r) { - r.statusCode.should.equal(200); - r.body.should.equal('{}'); - shouldReturnSecurityHeaders(r); - done(err); - } - ); - }); - - it('__lbheartbeat__ should return success', function (done) { - request( - { - url: verifier.baseurl() + '/__lbheartbeat__', - }, - function (err, r) { - r.statusCode.should.equal(200); - r.body.should.equal('{}'); - shouldReturnSecurityHeaders(r); - done(err); - } - ); - }); - - it('__version__ should return version info', function (done) { - request( - { - url: verifier.baseurl() + '/__version__', - }, - function (err, r) { - r.statusCode.should.equal(200); - var obj = JSON.parse(r.body); - obj.version.should.match(/^[0-9.]+$/); - obj.commit.should.match(/^[a-z0-9]{40}$/); - obj.source.should.be.a.String(); - shouldReturnSecurityHeaders(r); - done(err); - } - ); - }); - - it('__version__ should return version info (cached)', function (done) { - request( - { - url: verifier.baseurl() + '/__version__', - }, - function (err, r) { - r.statusCode.should.equal(200); - var obj = JSON.parse(r.body); - obj.version.should.match(/^[0-9.]+$/); - obj.commit.should.match(/^[a-z0-9]{40}$/); - obj.source.should.be.a.String(); - shouldReturnSecurityHeaders(r); - done(err); - } - ); - }); -}); diff --git a/packages/browserid-verifier/tests/lib/should-return-security-headers.js b/packages/browserid-verifier/tests/lib/should-return-security-headers.js deleted file mode 100644 index fbb879402f..0000000000 --- a/packages/browserid-verifier/tests/lib/should-return-security-headers.js +++ /dev/null @@ -1,24 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -var should = require('should'); - -function shouldReturnSecurityHeaders(res) { - var expect = { - 'strict-transport-security': 'max-age=31536000', - 'x-content-type-options': 'nosniff', - 'x-xss-protection': '1; mode=block', - 'x-frame-options': 'DENY', - 'cache-control': 'private, no-cache, no-store, must-revalidate, max-age=0', - 'content-security-policy': - "default-src 'none'; frame-ancestors 'none'; report-uri /__cspreport__", - }; - - Object.keys(expect).forEach(function (header) { - should.exist(res.headers[header]); - res.headers[header].should.equal(expect[header]); - }); -} - -module.exports = shouldReturnSecurityHeaders; diff --git a/packages/browserid-verifier/tests/lib/test-server.js b/packages/browserid-verifier/tests/lib/test-server.js deleted file mode 100755 index 8958ada3a9..0000000000 --- a/packages/browserid-verifier/tests/lib/test-server.js +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env node - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -require('../../lib/server.js'); diff --git a/packages/browserid-verifier/tests/lib/verifier.js b/packages/browserid-verifier/tests/lib/verifier.js deleted file mode 100644 index eb19ee66cf..0000000000 --- a/packages/browserid-verifier/tests/lib/verifier.js +++ /dev/null @@ -1,148 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* jshint curly:false */ - -const cp = require('child_process'), - path = require('path'); - -function later(cb /* args */) { - var args = Array.prototype.slice.call(arguments, 1); - process.nextTick(function () { - cb.apply(null, args); - }); -} - -function Verifier(args) { - if (!args) { - args = {}; - } - this.config = args; -} - -Verifier.prototype.setFallback = function (idp) { - if (idp === null) delete this.config.fallback; - else this.config.fallback = idp.domain(); -}; - -Verifier.prototype.setHTTPTimeout = function (timeo) { - this.config.httpTimeout = timeo; -}; - -Verifier.prototype.buffer = function (b) { - if (b !== undefined) { - if (!b) { - delete this._outBuf; - } else if (!this._outBuf) { - this._outBuf = ''; - } - } - return this._outBuf; -}; - -Verifier.prototype.url = function () { - return this.baseurl() + '/v2'; -}; - -Verifier.prototype.v1url = function () { - return this.baseurl(); -}; - -Verifier.prototype.baseurl = function () { - if (!this._url) { - throw new Error('verifier not running'); - } - return this._url; -}; - -Verifier.prototype.start = function (cb) { - var self = this; - - var repoBaseDir = path.join(__dirname, '..', '..'); - - if (this.process) { - return later(cb, null); - } - - var e = { - INSECURE_SSL: true, - HTTP_TIMEOUT: this.config.httpTimeout || 8.0, - }; - - if (this.config.fallback) { - e.FALLBACK_DOMAIN = this.config.fallback; - } - - if (this.config.files) { - e.CONFIG_FILES = this.config.files; - } - - if (this.config.testServiceFailure) { - e.TEST_SERVICE_FAILURE = this.config.testServiceFailure; - } - - this.process = cp.spawn( - process.execPath, - [path.join(repoBaseDir, 'tests', 'lib', 'test-server.js')], - { - cwd: repoBaseDir, - stdio: 'pipe', - env: e, - timeout: 4 * 1000, - } - ); - - this.process.stdout.on('data', function (line) { - if (typeof self._outBuf === 'string') { - self._outBuf += line; - } - - // figure out the bound port - try { - var m = JSON.parse(line); - if (m.Type === 'server.running') { - self._url = m.Fields.url; - if (cb) { - cb(null, m.Fields.url); - } - cb = null; - } - } catch (err) {} - - if (process.env.VERBOSE) { - console.log(line.toString()); - } - }); - - this.errBuf = ''; - this.process.stderr.on('data', function (d) { - self.errBuf += d.toString(); - }); - - this.process.on('exit', function (code) { - var msg = 'exited'; - if (code !== 0) { - msg += ' with code ' + code + ' (' + self.errBuf + ')'; - } - if (cb) cb(msg); - cb = null; - self._url = null; - self.process = null; - }); -}; - -Verifier.prototype.stop = function (cb) { - if (!this.process || !this._url) { - throw new Error('verifier not running'); - } - this.process.on('exit', function (code) { - cb(!code ? null : 'non-zero exit code: ' + code); - }); - const pid = this.process.pid; - // Really really kill it. This shouldn't be necesary, but sometimes when - // running tests in a loop, the process doesn't die with just a SIGINT. - cp.spawn('kill', ['-9', pid]); -}; - -module.exports = Verifier; diff --git a/packages/browserid-verifier/tests/missing-assertion.js b/packages/browserid-verifier/tests/missing-assertion.js deleted file mode 100644 index 4141ed803b..0000000000 --- a/packages/browserid-verifier/tests/missing-assertion.js +++ /dev/null @@ -1,43 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* global describe,it,before,after */ - -var Verifier = require('./lib/verifier.js'), - should = require('should'), - shouldReturnSecurityHeaders = require('./lib/should-return-security-headers.js'), - request = require('request'); - -describe('missing assertion test', function () { - var verifier = new Verifier(); - - before(async () => { - await new Promise((resolve) => verifier.start(resolve)); - }); - - after(async () => { - await new Promise((resolve) => verifier.stop(resolve)); - }); - - it('should fail to verify when assertion is missing', function (done) { - request( - { - method: 'post', - url: verifier.url(), - json: true, - body: { - audience: 'http://example.com', - }, - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(400); - r.body.status.should.equal('failure'); - r.body.reason.should.equal('missing assertion parameter'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - }); -}); diff --git a/packages/browserid-verifier/tests/service-failure.js b/packages/browserid-verifier/tests/service-failure.js deleted file mode 100644 index c569b4c3d8..0000000000 --- a/packages/browserid-verifier/tests/service-failure.js +++ /dev/null @@ -1,80 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* global describe,it,before,after */ - -var IdP = require('browserid-local-verify/testing').IdP, - Client = require('browserid-local-verify/testing').Client, - Verifier = require('./lib/verifier.js'), - should = require('should'), - shouldReturnSecurityHeaders = require('./lib/should-return-security-headers.js'), - request = require('request'); - -describe('audience tests', function () { - var verifier = new Verifier({ testServiceFailure: true }); - var idp = new IdP(); - var client; - - before(async () => { - await new Promise((resolve) => idp.start(resolve)); - await new Promise((resolve) => verifier.start(resolve)); - client = new Client({ idp: idp }); - }); - - after(async () => { - await new Promise((resolve) => verifier.stop(resolve)); - await new Promise((resolve) => idp.stop(resolve)); - }); - - var assertion; - - it('test assertion should be created', function (done) { - client.assertion({ audience: 'http://example.com' }, function (err, ass) { - assertion = ass; - done(err); - }); - }); - - it('(v1 api) should return a 503 on service failure', function (done) { - request( - { - method: 'post', - url: verifier.v1url(), - json: true, - body: { - assertion: assertion, - audience: 'http://example.com', - }, - }, - function (err, r) { - should.not.exist(err); - (503).should.equal(r.statusCode); - 'failure'.should.equal(r.body.status); - shouldReturnSecurityHeaders(r); - done(); - } - ); - }); - - it('(v2 api) should return a 503 on service failure', function (done) { - request( - { - method: 'post', - url: verifier.url(), - json: true, - body: { - assertion: assertion, - audience: 'http://example.com', - }, - }, - function (err, r) { - should.not.exist(err); - (503).should.equal(r.statusCode); - 'failure'.should.equal(r.body.status); - shouldReturnSecurityHeaders(r); - done(); - } - ); - }); -}); diff --git a/packages/browserid-verifier/tests/trusted-issuers.js b/packages/browserid-verifier/tests/trusted-issuers.js deleted file mode 100644 index 6bf6870bfb..0000000000 --- a/packages/browserid-verifier/tests/trusted-issuers.js +++ /dev/null @@ -1,102 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* global describe,it,before,after */ - -var IdP = require('browserid-local-verify/testing').IdP, - Client = require('browserid-local-verify/testing').Client, - Verifier = require('./lib/verifier.js'), - should = require('should'), - shouldReturnSecurityHeaders = require('./lib/should-return-security-headers.js'), - request = require('request'); - -describe('audience tests', function () { - var verifier = new Verifier(); - var idp = new IdP(); - var client; - - before(async () => { - await new Promise((resolve) => idp.start(resolve)); - await new Promise((resolve) => verifier.start(resolve)); - client = new Client({ - idp: idp, - // note, using an email not rooted at the idp. trustIssuer is the only - // way this can work - email: 'user@example.com', - }); - }); - - after(async () => { - await new Promise((resolve) => verifier.stop(resolve)); - await new Promise((resolve) => idp.stop(resolve)); - }); - - var assertion; - - it('test assertion should be created', function (done) { - client.assertion({ audience: 'http://example.com' }, function (err, ass) { - assertion = ass; - done(err); - }); - }); - - function submitWithTrustedIssuers(ti, cb) { - request( - { - method: 'post', - url: verifier.url(), - json: true, - body: { - assertion: assertion, - audience: 'http://example.com', - trustedIssuers: ti, - }, - }, - cb - ); - } - - it('should verify when trusted issuers is specified', function (done) { - submitWithTrustedIssuers([idp.domain()], function (err, r) { - should.not.exist(err); - 'okay'.should.equal(r.body.status); - shouldReturnSecurityHeaders(r); - done(); - }); - }); - - it('should fail when trusted issuers is not specified', function (done) { - submitWithTrustedIssuers(undefined, function (err, r) { - should.not.exist(err); - 'failure'.should.equal(r.body.status); - shouldReturnSecurityHeaders(r); - done(); - }); - }); - - it('should fail when trusted issuers is not an array', function (done) { - submitWithTrustedIssuers(idp.domain(), function (err, r) { - should.not.exist(err); - 'failure'.should.equal(r.body.status); - 'trusted issuers must be an array'.should.equal(r.body.reason); - shouldReturnSecurityHeaders(r); - done(); - }); - }); - - it('should fail when trusted issuers contains non-strings', function (done) { - submitWithTrustedIssuers( - [idp.domain(), ['example.com']], - function (err, r) { - should.not.exist(err); - 'failure'.should.equal(r.body.status); - 'trusted issuers must be an array of strings'.should.equal( - r.body.reason - ); - shouldReturnSecurityHeaders(r); - done(); - } - ); - }); -}); diff --git a/packages/browserid-verifier/tests/unverified-email.js b/packages/browserid-verifier/tests/unverified-email.js deleted file mode 100644 index 9e4f84a2f3..0000000000 --- a/packages/browserid-verifier/tests/unverified-email.js +++ /dev/null @@ -1,136 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* global describe,it,before,after */ - -var IdP = require('browserid-local-verify/testing').IdP, - Client = require('browserid-local-verify/testing').Client, - Verifier = require('./lib/verifier.js'), - should = require('should'), - shouldReturnSecurityHeaders = require('./lib/should-return-security-headers.js'), - request = require('request'); - -describe('unverified email', function () { - var fallback = new IdP(); - var verifier = new Verifier(); - var client; - - before(async () => { - await new Promise((resolve) => fallback.start(resolve)); - verifier.setFallback(fallback); - await new Promise((resolve) => verifier.start(resolve)); - }); - - after(async () => { - await new Promise((resolve) => verifier.stop(resolve)); - await new Promise((resolve) => fallback.stop(resolve)); - }); - - it('(v1) assertion with unverified email address should fail to verify', function (done) { - client = new Client({ - idp: fallback, - principal: { 'unverified-email': 'bob@example.com' }, - }); - // clear email - client.email(null); - client.assertion( - { audience: 'http://example.com' }, - function (_, assertion) { - request( - { - method: 'post', - url: verifier.v1url(), - json: true, - body: { - assertion: assertion, - audience: 'http://example.com', - }, - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(200); - r.body.status.should.equal('failure'); - r.body.reason.should.startWith('untrusted assertion'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - } - ); - }); - - it('(v1) assertion with unverified email address and forceIssuer should verify', function (done) { - client = new Client({ - idp: fallback, - principal: { 'unverified-email': 'bob@example.com' }, - }); - client.assertion( - { audience: 'http://example.com' }, - function (_, assertion) { - request( - { - method: 'post', - url: verifier.url(), - json: true, - body: { - assertion: assertion, - audience: 'http://example.com', - experimental_forceIssuer: fallback.domain(), - }, - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(200); - r.body.status.should.equal('okay'); - r.body.idpClaims.should.be.type('object'); - r.body.idpClaims['unverified-email'].should.equal( - 'bob@example.com' - ); - r.body.should.not.have.property('unverified-email'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - } - ); - }); - - it('(v1) allowUnverified causes extraction of unverified email addresses', function (done) { - client = new Client({ - idp: fallback, - principal: { 'unverified-email': 'bob@example.com' }, - }); - - client.assertion( - { audience: 'http://example.com' }, - function (_, assertion) { - request( - { - method: 'post', - url: verifier.v1url(), - json: true, - body: { - assertion: assertion, - audience: 'http://example.com', - experimental_forceIssuer: fallback.domain(), - experimental_allowUnverified: true, - }, - }, - function (err, r) { - should.not.exist(err); - r.statusCode.should.equal(200); - r.body.status.should.equal('okay'); - r.body.idpClaims.should.be.type('object'); - r.body.idpClaims['unverified-email'].should.equal( - 'bob@example.com' - ); - r.body.should.have.property('unverified-email'); - shouldReturnSecurityHeaders(r); - done(); - } - ); - } - ); - }); -}); diff --git a/packages/functional-tests/scripts/start-services.sh b/packages/functional-tests/scripts/start-services.sh index 28231b00ca..a3c9fa734d 100755 --- a/packages/functional-tests/scripts/start-services.sh +++ b/packages/functional-tests/scripts/start-services.sh @@ -18,7 +18,6 @@ CI=false NODE_ENV=test npx nx run-many \ --verbose \ -p \ 123done \ - browserid-verifier \ fxa-auth-server \ fxa-content-server \ fxa-graphql-api \ diff --git a/packages/fxa-auth-server/backstage.yaml b/packages/fxa-auth-server/backstage.yaml index 7ad9e17b1e..25aaec9902 100644 --- a/packages/fxa-auth-server/backstage.yaml +++ b/packages/fxa-auth-server/backstage.yaml @@ -20,7 +20,6 @@ spec: providesApis: - api:fxa-auth dependsOn: - - component:fxa-browserid-verifier - component:fxa-customs-server - resource:fxa-auth-database - resource:fxa-oauth-database diff --git a/packages/fxa-content-server/scripts/start-services.sh b/packages/fxa-content-server/scripts/start-services.sh index 824d60b9e2..68d1d415fb 100755 --- a/packages/fxa-content-server/scripts/start-services.sh +++ b/packages/fxa-content-server/scripts/start-services.sh @@ -20,7 +20,6 @@ CI=false NODE_ENV=test npx nx run-many \ --parallel=3 \ -p \ 123done \ - browserid-verifier \ fxa-auth-server \ fxa-content-server \ fxa-graphql-api \