add otplib to generate OTP from key for eg, pg; gog only has mail
This commit is contained in:
parent
9e0d4434fe
commit
1a3d90f795
6 changed files with 141 additions and 3 deletions
12
README.md
12
README.md
|
|
@ -60,8 +60,10 @@ Available options/variables and their default values:
|
||||||
| PASSWORD | | Default password for any login. |
|
| PASSWORD | | Default password for any login. |
|
||||||
| EG_EMAIL | | Epic Games email for login. Overrides EMAIL. |
|
| EG_EMAIL | | Epic Games email for login. Overrides EMAIL. |
|
||||||
| EG_PASSWORD | | Epic Games password for login. Overrides PASSWORD. |
|
| EG_PASSWORD | | Epic Games password for login. Overrides PASSWORD. |
|
||||||
|
| EG_OTPKEY | | Epic Games MFA OTP key. |
|
||||||
| PG_EMAIL | | Prime Gaming email for login. Overrides EMAIL. |
|
| PG_EMAIL | | Prime Gaming email for login. Overrides EMAIL. |
|
||||||
| PG_PASSWORD | | Prime Gaming password for login. Overrides PASSWORD. |
|
| PG_PASSWORD | | Prime Gaming password for login. Overrides PASSWORD. |
|
||||||
|
| PG_OTPKEY | | Prime Gaming MFA OTP key. |
|
||||||
| GOG_EMAIL | | GOG email for login. Overrides EMAIL. |
|
| GOG_EMAIL | | GOG email for login. Overrides EMAIL. |
|
||||||
| GOG_PASSWORD | | GOG password for login. Overrides PASSWORD. |
|
| GOG_PASSWORD | | GOG password for login. Overrides PASSWORD. |
|
||||||
|
|
||||||
|
|
@ -71,6 +73,16 @@ See `config.js` for all options.
|
||||||
On Linux/macOS you can prefix the variables you want to set, for example `EMAIL=foo@bar.baz SHOW=1 node epic-games` will show the browser and skip asking you for your login email.
|
On Linux/macOS you can prefix the variables you want to set, for example `EMAIL=foo@bar.baz SHOW=1 node epic-games` will show the browser and skip asking you for your login email.
|
||||||
For Docker you can pass variables using `-e VAR=VAL`, for example `docker run -e EMAIL=foo@bar.baz ...` or using `--env-file` (see [docs](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file)). If you are using [docker compose](https://docs.docker.com/compose/environment-variables/), you can put them in the `environment:` section.
|
For Docker you can pass variables using `-e VAR=VAL`, for example `docker run -e EMAIL=foo@bar.baz ...` or using `--env-file` (see [docs](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file)). If you are using [docker compose](https://docs.docker.com/compose/environment-variables/), you can put them in the `environment:` section.
|
||||||
|
|
||||||
|
### Automatic login, two-factor authentication
|
||||||
|
If you set the options for email, password and OTP key, there will be no prompts and logins automatic. This is optional since all stores should stay logged in since cookies are refreshed.
|
||||||
|
To get the OTP key, it is easiest to follow the store's guide for adding an authenticator app. You should also scan the shown QR code with your favorite app to have an alternative.
|
||||||
|
|
||||||
|
- Epic Games: visit [password & security](https://www.epicgames.com/account/password), enable 'third-party authenticator app', copy the 'Manual Entry Key' and use it to set `EG_OTPKEY`.
|
||||||
|
- Prime Gaming: visit Amazon 'Your Account › Login & security', 2-step verification › Manage › Add new app › Can't scan the barcode, copy the bold key and use it to set `PG_OTPKEY`
|
||||||
|
- GOG: only offers OTP via email
|
||||||
|
|
||||||
|
Beware that storing passwords and OTP keys as clear text may be a security risk. Use a unique/generated password! TODO: maybe at least offer to base64 encode for storage.
|
||||||
|
|
||||||
### Epic Games Store
|
### Epic Games Store
|
||||||
Run `node epic-games` (locally or in Docker).
|
Run `node epic-games` (locally or in Docker).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,15 @@ export const cfg = {
|
||||||
height: Number(process.env.HEIGHT) || 1280, // height of the opened browser
|
height: Number(process.env.HEIGHT) || 1280, // height of the opened browser
|
||||||
timeout: (Number(process.env.TIMEOUT) || 20) * 1000, // 20s, default for playwright is 30s
|
timeout: (Number(process.env.TIMEOUT) || 20) * 1000, // 20s, default for playwright is 30s
|
||||||
novnc_port: process.env.NOVNC_PORT, // running in docker if set
|
novnc_port: process.env.NOVNC_PORT, // running in docker if set
|
||||||
|
// auth epic-games
|
||||||
eg_email: process.env.EG_EMAIL || process.env.EMAIL,
|
eg_email: process.env.EG_EMAIL || process.env.EMAIL,
|
||||||
eg_password: process.env.EG_PASSWORD || process.env.PASSWORD,
|
eg_password: process.env.EG_PASSWORD || process.env.PASSWORD,
|
||||||
|
eg_otpkey: process.env.EG_OTPKEY,
|
||||||
|
// auth prime-gaming
|
||||||
pg_email: process.env.PG_EMAIL || process.env.EMAIL,
|
pg_email: process.env.PG_EMAIL || process.env.EMAIL,
|
||||||
pg_password: process.env.PG_PASSWORD || process.env.PASSWORD,
|
pg_password: process.env.PG_PASSWORD || process.env.PASSWORD,
|
||||||
|
pg_otpkey: process.env.PG_OTPKEY,
|
||||||
|
// auth gog
|
||||||
gog_email: process.env.GOG_EMAIL || process.env.EMAIL,
|
gog_email: process.env.GOG_EMAIL || process.env.EMAIL,
|
||||||
gog_password: process.env.GOG_PASSWORD || process.env.PASSWORD,
|
gog_password: process.env.GOG_PASSWORD || process.env.PASSWORD,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import { firefox } from 'playwright'; // stealth plugin needs no outdated playwright-extra
|
import { firefox } from 'playwright'; // stealth plugin needs no outdated playwright-extra
|
||||||
|
import { authenticator } from 'otplib';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import { existsSync, writeFileSync } from 'fs';
|
||||||
import { dirs, jsonDb, datetime, stealth, filenamify } from './util.js';
|
import { dirs, jsonDb, datetime, stealth, filenamify } from './util.js';
|
||||||
import { cfg } from './config.js';
|
import { cfg } from './config.js';
|
||||||
import { existsSync, writeFileSync } from 'fs';
|
|
||||||
|
|
||||||
import prompts from 'prompts'; // alternatives: enquirer, inquirer
|
import prompts from 'prompts'; // alternatives: enquirer, inquirer
|
||||||
// import enquirer from 'enquirer'; const { prompt } = enquirer;
|
// import enquirer from 'enquirer'; const { prompt } = enquirer;
|
||||||
|
|
@ -85,7 +86,7 @@ try {
|
||||||
// handle MFA, but don't await it
|
// handle MFA, but don't await it
|
||||||
page.waitForNavigation({ url: '**/id/login/mfa**'}).then(async () => {
|
page.waitForNavigation({ url: '**/id/login/mfa**'}).then(async () => {
|
||||||
console.log('Enter the security code to continue - This appears to be a new device, browser or location. A security code has been sent to your email address at ...');
|
console.log('Enter the security code to continue - This appears to be a new device, browser or location. A security code has been sent to your email address at ...');
|
||||||
const otp = await prompt({type: 'text', message: 'Enter two-factor sign in code', validate: n => n.toString().length == 6 || 'The code must be 6 digits!'}); // can't use type: 'number' since it strips away leading zeros and codes sometimes have them
|
const otp = cfg.eg_otpkey && authenticator.generate(cfg.eg_otpkey) || await prompt({type: 'text', message: 'Enter two-factor sign in code', validate: n => n.toString().length == 6 || 'The code must be 6 digits!'}); // can't use type: 'number' since it strips away leading zeros and codes sometimes have them
|
||||||
await page.type('input[name="code-input-0"]', otp.toString());
|
await page.type('input[name="code-input-0"]', otp.toString());
|
||||||
await page.click('button[type="submit"]');
|
await page.click('button[type="submit"]');
|
||||||
}).catch(_ => { });
|
}).catch(_ => { });
|
||||||
|
|
|
||||||
118
package-lock.json
generated
118
package-lock.json
generated
|
|
@ -12,11 +12,54 @@
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"lowdb": "^5.0.5",
|
"lowdb": "^5.0.5",
|
||||||
|
"otplib": "^12.0.1",
|
||||||
"playwright": "^1.29.0",
|
"playwright": "^1.29.0",
|
||||||
"prompts": "^2.4.2",
|
"prompts": "^2.4.2",
|
||||||
"puppeteer-extra-plugin-stealth": "^2.11.1"
|
"puppeteer-extra-plugin-stealth": "^2.11.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@otplib/core": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@otplib/core/-/core-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-4sGntwbA/AC+SbPhbsziRiD+jNDdIzsZ3JUyfZwjtKyc/wufl1pnSIaG4Uqx8ymPagujub0o92kgBnB89cuAMA=="
|
||||||
|
},
|
||||||
|
"node_modules/@otplib/plugin-crypto": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@otplib/plugin-crypto/-/plugin-crypto-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-qPuhN3QrT7ZZLcLCyKOSNhuijUi9G5guMRVrxq63r9YNOxxQjPm59gVxLM+7xGnHnM6cimY57tuKsjK7y9LM1g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@otplib/core": "^12.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@otplib/plugin-thirty-two": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@otplib/plugin-thirty-two/-/plugin-thirty-two-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-MtT+uqRso909UkbrrYpJ6XFjj9D+x2Py7KjTO9JDPhL0bJUYVu5kFP4TFZW4NFAywrAtFRxOVY261u0qwb93gA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@otplib/core": "^12.0.1",
|
||||||
|
"thirty-two": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@otplib/preset-default": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@otplib/preset-default/-/preset-default-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-xf1v9oOJRyXfluBhMdpOkr+bsE+Irt+0D5uHtvg6x1eosfmHCsCC6ej/m7FXiWqdo0+ZUI6xSKDhJwc8yfiOPQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@otplib/core": "^12.0.1",
|
||||||
|
"@otplib/plugin-crypto": "^12.0.1",
|
||||||
|
"@otplib/plugin-thirty-two": "^12.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@otplib/preset-v11": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@otplib/preset-v11/-/preset-v11-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-9hSetMI7ECqbFiKICrNa4w70deTUfArtwXykPUvSHWOdzOlfa9ajglu7mNCntlvxycTiOAXkQGwjQCzzDEMRMg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@otplib/core": "^12.0.1",
|
||||||
|
"@otplib/plugin-crypto": "^12.0.1",
|
||||||
|
"@otplib/plugin-thirty-two": "^12.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/debug": {
|
"node_modules/@types/debug": {
|
||||||
"version": "4.1.7",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz",
|
||||||
|
|
@ -355,6 +398,16 @@
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/otplib": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/otplib/-/otplib-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-xDGvUOQjop7RDgxTQ+o4pOol0/3xSZzawTiPKRrHnQWAy0WjhNs/5HdIDJCrqC4MBynmjXgULc6YfioaxZeFgg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@otplib/core": "^12.0.1",
|
||||||
|
"@otplib/preset-default": "^12.0.1",
|
||||||
|
"@otplib/preset-v11": "^12.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/path-is-absolute": {
|
"node_modules/path-is-absolute": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
|
|
@ -593,6 +646,14 @@
|
||||||
"url": "https://github.com/sponsors/typicode"
|
"url": "https://github.com/sponsors/typicode"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/thirty-two": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.2.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/universalify": {
|
"node_modules/universalify": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||||
|
|
@ -622,6 +683,48 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@otplib/core": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@otplib/core/-/core-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-4sGntwbA/AC+SbPhbsziRiD+jNDdIzsZ3JUyfZwjtKyc/wufl1pnSIaG4Uqx8ymPagujub0o92kgBnB89cuAMA=="
|
||||||
|
},
|
||||||
|
"@otplib/plugin-crypto": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@otplib/plugin-crypto/-/plugin-crypto-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-qPuhN3QrT7ZZLcLCyKOSNhuijUi9G5guMRVrxq63r9YNOxxQjPm59gVxLM+7xGnHnM6cimY57tuKsjK7y9LM1g==",
|
||||||
|
"requires": {
|
||||||
|
"@otplib/core": "^12.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@otplib/plugin-thirty-two": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@otplib/plugin-thirty-two/-/plugin-thirty-two-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-MtT+uqRso909UkbrrYpJ6XFjj9D+x2Py7KjTO9JDPhL0bJUYVu5kFP4TFZW4NFAywrAtFRxOVY261u0qwb93gA==",
|
||||||
|
"requires": {
|
||||||
|
"@otplib/core": "^12.0.1",
|
||||||
|
"thirty-two": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@otplib/preset-default": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@otplib/preset-default/-/preset-default-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-xf1v9oOJRyXfluBhMdpOkr+bsE+Irt+0D5uHtvg6x1eosfmHCsCC6ej/m7FXiWqdo0+ZUI6xSKDhJwc8yfiOPQ==",
|
||||||
|
"requires": {
|
||||||
|
"@otplib/core": "^12.0.1",
|
||||||
|
"@otplib/plugin-crypto": "^12.0.1",
|
||||||
|
"@otplib/plugin-thirty-two": "^12.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@otplib/preset-v11": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@otplib/preset-v11/-/preset-v11-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-9hSetMI7ECqbFiKICrNa4w70deTUfArtwXykPUvSHWOdzOlfa9ajglu7mNCntlvxycTiOAXkQGwjQCzzDEMRMg==",
|
||||||
|
"requires": {
|
||||||
|
"@otplib/core": "^12.0.1",
|
||||||
|
"@otplib/plugin-crypto": "^12.0.1",
|
||||||
|
"@otplib/plugin-thirty-two": "^12.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/debug": {
|
"@types/debug": {
|
||||||
"version": "4.1.7",
|
"version": "4.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz",
|
||||||
|
|
@ -877,6 +980,16 @@
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"otplib": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/otplib/-/otplib-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-xDGvUOQjop7RDgxTQ+o4pOol0/3xSZzawTiPKRrHnQWAy0WjhNs/5HdIDJCrqC4MBynmjXgULc6YfioaxZeFgg==",
|
||||||
|
"requires": {
|
||||||
|
"@otplib/core": "^12.0.1",
|
||||||
|
"@otplib/preset-default": "^12.0.1",
|
||||||
|
"@otplib/preset-v11": "^12.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"path-is-absolute": {
|
"path-is-absolute": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
|
|
@ -1008,6 +1121,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/steno/-/steno-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/steno/-/steno-3.0.0.tgz",
|
||||||
"integrity": "sha512-uZtn7Ht9yXLiYgOsmo8btj4+f7VxyYheMt8g6F1ANjyqByQXEE2Gygjgenp3otHH1TlHsS4JAaRGv5wJ1wvMNw=="
|
"integrity": "sha512-uZtn7Ht9yXLiYgOsmo8btj4+f7VxyYheMt8g6F1ANjyqByQXEE2Gygjgenp3otHH1TlHsS4JAaRGv5wJ1wvMNw=="
|
||||||
},
|
},
|
||||||
|
"thirty-two": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA=="
|
||||||
|
},
|
||||||
"universalify": {
|
"universalify": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"lowdb": "^5.0.5",
|
"lowdb": "^5.0.5",
|
||||||
|
"otplib": "^12.0.1",
|
||||||
"playwright": "^1.29.0",
|
"playwright": "^1.29.0",
|
||||||
"prompts": "^2.4.2",
|
"prompts": "^2.4.2",
|
||||||
"puppeteer-extra-plugin-stealth": "^2.11.1"
|
"puppeteer-extra-plugin-stealth": "^2.11.1"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { firefox } from 'playwright'; // stealth plugin needs no outdated playwright-extra
|
import { firefox } from 'playwright'; // stealth plugin needs no outdated playwright-extra
|
||||||
|
import { authenticator } from 'otplib';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { dirs, jsonDb, datetime, stealth, filenamify } from './util.js';
|
import { dirs, jsonDb, datetime, stealth, filenamify } from './util.js';
|
||||||
import { cfg } from './config.js';
|
import { cfg } from './config.js';
|
||||||
|
|
@ -61,7 +62,7 @@ try {
|
||||||
page.waitForNavigation({ url: '**/ap/mfa**'}).then(async () => {
|
page.waitForNavigation({ url: '**/ap/mfa**'}).then(async () => {
|
||||||
console.log('Two-Step Verification - enter the One Time Password (OTP), e.g. generated by your Authenticator App');
|
console.log('Two-Step Verification - enter the One Time Password (OTP), e.g. generated by your Authenticator App');
|
||||||
await page.check('[name=rememberDevice]');
|
await page.check('[name=rememberDevice]');
|
||||||
const otp = await prompt({type: 'text', message: 'Enter two-factor sign in code', validate: n => n.toString().length == 6 || 'The code must be 6 digits!'}); // can't use type: 'number' since it strips away leading zeros and codes sometimes have them
|
const otp = cfg.pg_otpkey && authenticator.generate(cfg.pg_otpkey) || await prompt({type: 'text', message: 'Enter two-factor sign in code', validate: n => n.toString().length == 6 || 'The code must be 6 digits!'}); // can't use type: 'number' since it strips away leading zeros and codes sometimes have them
|
||||||
await page.type('input[name=otpCode]', otp.toString());
|
await page.type('input[name=otpCode]', otp.toString());
|
||||||
await page.click('input[type="submit"]');
|
await page.click('input[type="submit"]');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue