@salesforce/core
Version:
Core libraries to interact with SFDX projects, orgs, and APIs.
201 lines • 20.6 kB
JavaScript
"use strict";
/*
* Copyright (c) 2020, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
/* eslint-disable camelcase */
/* eslint-disable @typescript-eslint/ban-types */
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DeviceOauthService = void 0;
const transport_1 = __importDefault(require("@jsforce/jsforce-node/lib/transport"));
const kit_1 = require("@salesforce/kit");
const ts_types_1 = require("@salesforce/ts-types");
const form_data_1 = __importDefault(require("form-data"));
const logger_1 = require("./logger/logger");
const authInfo_1 = require("./org/authInfo");
const connection_1 = require("./org/connection");
const sfError_1 = require("./sfError");
const messages_1 = require("./messages");
;
const messages = new messages_1.Messages('@salesforce/core', 'auth', new Map([["targetOrgNotSet", "A default user is not set."], ["targetOrgNotSet.actions", ["Run the \"sfdx auth\" commands with --setdefaultusername to connect to an org and set it as your default org.", "Run \"force:org:create\" with --setdefaultusername to create a scratch org and set it as your default org.", "Run \"sfdx config:set defaultusername=<username>\" to set your default username."]], ["portInUse", "Cannot start the OAuth redirect server on port %s."], ["portInUse.actions", ["Kill the process running on port %s or use a custom connected app and update OauthLocalPort in the sfdx-project.json file."]], ["invalidRequestMethod", "Invalid request method: %s"], ["invalidRequestUri", "Invalid request uri: %s"], ["error.HttpApi", "HTTP response contains html content. Check that the org exists and can be reached."], ["pollingTimeout", "The device authorization request timed out. After executing force:auth:device:login, you must approve access to the device within 10 minutes. This can happen if the URL wasn\u2019t copied into the browser, login was not attempted, or the 2FA process was not completed within 10 minutes. Request authorization again."], ["serverErrorHTMLResponse", "<html><head><style>body {background-color:#F4F6F9; font-family: Arial, sans-serif; font-size: 0.8125rem; line-height: 1.5rem; color: #16325c;} #center {margin: auto; width: 370px; padding: 100px 0px 20px;} #logo-container {margin-left: auto; margin-right: auto; text-align: center;} #logo {max-width: 180px; max-height: 113px; margin-bottom: 2rem; border: 0;} #header {font-size: 1.5rem; text-align: center; margin-bottom: 1rem;} #message {background-color: #FFFFFF; margin: 0px auto; padding: 1.25rem; border-radius: 0.25rem; border: 1px solid #D8DDE6;} #footer {height: 24px; width: 370px; text-align: center; font-size: .75rem; position: absolute; bottom: 10;}</style></head><body><div id=\"center\"><div id=\"logo-container\"><img id=\"logo\" aria-hidden=\"true\" name=\"logo\" alt=\"Salesforce\" src=\"data:image/svg+xml;base64,%s\"></div><div id=\"header\">%s</div><div id=\"message\">%s<br/><br/>This is most likely <b>not</b> an error with the Salesforce CLI. Please ensure all information is accurate and try again.</div><div id=\"footer\">© %s Salesforce, Inc. All rights reserved.</div></div></body></html>"], ["missingAuthCode", "No authentication code found on login response."], ["serverSuccessHTMLResponse", "<html><head><style>body {background-color:#F4F6F9; font-family: Arial, sans-serif; font-size: 0.8125rem; line-height: 1.5rem; color: #16325c;} #center {margin: auto; width: 300px; padding: 100px 0px 20px;} #logo-container {margin-left: auto; margin-right: auto; text-align: center;} #logo {max-width: 180px; max-height: 113px; margin-bottom: 2rem; border: 0;} #header {font-size: 1.5rem; text-align: center; margin-bottom: 1rem;} #message {background-color: #FFFFFF; margin: 0px auto; padding: 1.25rem; border-radius: 0.25rem; border: 1px solid #D8DDE6;} #footer {height: 24px; width: 300px; text-align: center; font-size: .75rem; position: absolute; bottom: 10;}</style></head><body><div id=\"center\"><div id=\"logo-container\"><img id=\"logo\" aria-hidden=\"true\" name=\"logo\" alt=\"Salesforce\" src=\"data:image/svg+xml;base64,%s\"></div><div id=\"header\">Authentication Successful</div><div id=\"message\">You've successfully logged in. You can now close this browser tab or window.</div><div id=\"footer\">© %s Salesforce, Inc. All rights reserved.</div></div></body></html>"], ["serverSfdcImage", "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIxLjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAyNjIgMTg0IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyNjIgMTg0OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+Cgkuc3Qwe2ZpbGw6IzAwQTFFMDt9Cgkuc3Qxe2ZpbGw6I0ZGRkZGRjt9Cjwvc3R5bGU+Cjx0aXRsZT5sb2dvLXNhbGVzZm9yY2U8L3RpdGxlPgo8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KPGcgaWQ9IlRlc3QtQiI+Cgk8ZyBpZD0iTW9iaWxlLU5hdi0tLVRlc3QtQi1feDI4XzBfeDI5XyI+CgkJPGcgaWQ9Ikdyb3VwIj4KCQkJPGcgaWQ9ImxvZ28tc2FsZXNmb3JjZSI+CgkJCQk8cGF0aCBpZD0iRmlsbC0xIiBjbGFzcz0ic3QwIiBkPSJNMTA5LjIsMjAuOWM4LjQtOC43LDIwLjEtMTQuMiwzMy0xNC4yYzE3LjIsMCwzMi4xLDkuNiw0MC4xLDIzLjhjNi45LTMuMSwxNC42LTQuOCwyMi43LTQuOAoJCQkJCWMzMSwwLDU2LDI1LjMsNTYsNTYuNXMtMjUuMSw1Ni41LTU2LDU2LjVjLTMuOCwwLTcuNS0wLjQtMTEtMS4xYy03LDEyLjUtMjAuNCwyMS0zNS44LDIxYy02LjQsMC0xMi41LTEuNS0xNy45LTQuMQoJCQkJCWMtNy4xLDE2LjctMjMuNywyOC41LTQzLDI4LjVjLTIwLjEsMC0zNy4zLTEyLjctNDMuOS0zMC42Yy0yLjksMC42LTUuOSwwLjktOC45LDAuOWMtMjQsMC00My40LTE5LjYtNDMuNC00My45CgkJCQkJYzAtMTYuMiw4LjctMzAuNCwyMS43LTM4Yy0yLjctNi4xLTQuMi0xMi45LTQuMi0yMC4xQzE4LjUsMjMuNiw0MS4yLDEsNjksMUM4NS40LDEsMTAwLDguOCwxMDkuMiwyMC45Ii8+CgkJCQk8cGF0aCBpZD0iQ29tYmluZWQtU2hhcGUiIGNsYXNzPSJzdDEiIGQ9Ik0zOC43LDk1LjRsMS4xLTIuOWMwLjItMC41LDAuNS0wLjMsMC43LTAuMmMwLjMsMC4yLDAuNSwwLjMsMC45LDAuNmMzLjEsMiw2LDIsNi45LDIKCQkJCQljMi4zLDAsMy44LTEuMiwzLjgtMi45di0wLjFjMC0xLjgtMi4yLTIuNS00LjgtMy4zbC0wLjYtMC4yYy0zLjUtMS03LjMtMi41LTcuMy02Ljl2LTAuMWMwLTQuMiwzLjQtNy4yLDguMy03LjJsMC41LDAKCQkJCQljMi45LDAsNS42LDAuOCw3LjYsMi4xYzAuMiwwLjEsMC40LDAuMywwLjMsMC42Yy0wLjEsMC4zLTEsMi42LTEuMSwyLjljLTAuMiwwLjUtMC43LDAuMi0wLjcsMC4yYy0xLjgtMS00LjUtMS43LTYuOC0xLjcKCQkJCQljLTIuMSwwLTMuNCwxLjEtMy40LDIuNnYwLjFjMCwxLjcsMi4zLDIuNSw0LjksMy4zbDAuNSwwLjFjMy41LDEuMSw3LjIsMi42LDcuMiw2Ljl2MC4xYzAsNC42LTMuMyw3LjQtOC42LDcuNAoJCQkJCWMtMi42LDAtNS4xLTAuNC03LjgtMS44Yy0wLjUtMC4zLTEtMC41LTEuNS0wLjlDMzguNyw5NS45LDM4LjUsOTUuOCwzOC43LDk1LjR6IE0xMTYuNyw5NS40bDEuMS0yLjljMC4yLTAuNSwwLjYtMC4zLDAuNy0wLjIKCQkJCQljMC4zLDAuMiwwLjUsMC4zLDAuOSwwLjZjMy4xLDIsNiwyLDYuOSwyYzIuMywwLDMuOC0xLjIsMy44LTIuOXYtMC4xYzAtMS44LTIuMi0yLjUtNC44LTMuM2wtMC42LTAuMmMtMy41LTEtNy4zLTIuNS03LjMtNi45CgkJCQkJdi0wLjFjMC00LjIsMy40LTcuMiw4LjMtNy4ybDAuNSwwYzIuOSwwLDUuNiwwLjgsNy42LDIuMWMwLjIsMC4xLDAuNCwwLjMsMC4zLDAuNmMtMC4xLDAuMy0xLDIuNi0xLjEsMi45CgkJCQkJYy0wLjIsMC41LTAuNywwLjItMC43LDAuMmMtMS44LTEtNC41LTEuNy02LjgtMS43Yy0yLjEsMC0zLjQsMS4xLTMuNCwyLjZ2MC4xYzAsMS43LDIuMywyLjUsNC45LDMuM2wwLjUsMC4xCgkJCQkJYzMuNSwxLjEsNy4yLDIuNiw3LjIsNi45djAuMWMwLDQuNi0zLjMsNy40LTguNiw3LjRjLTIuNiwwLTUuMS0wLjQtNy44LTEuOGMtMC41LTAuMy0xLTAuNS0xLjUtMC45CgkJCQkJQzExNi44LDk1LjksMTE2LjYsOTUuOCwxMTYuNyw5NS40eiBNMTc0LjUsODEuN2MwLjQsMS41LDAuNywzLjEsMC43LDQuOHMtMC4yLDMuMy0wLjcsNC44Yy0wLjQsMS41LTEuMSwyLjgtMiwzLjkKCQkJCQljLTAuOSwxLjEtMi4xLDItMy40LDIuNmMtMS40LDAuNi0zLDAuOS00LjgsMC45Yy0xLjgsMC0zLjQtMC4zLTQuOC0wLjljLTEuNC0wLjYtMi41LTEuNS0zLjQtMi42Yy0wLjktMS4xLTEuNi0yLjQtMi0zLjkKCQkJCQljLTAuNC0xLjUtMC43LTMuMS0wLjctNC44YzAtMS43LDAuMi0zLjMsMC43LTQuOGMwLjQtMS41LDEuMS0yLjgsMi0zLjljMC45LTEuMSwyLjEtMiwzLjQtMi42YzEuNC0wLjYsMy0xLDQuOC0xCgkJCQkJYzEuOCwwLDMuNCwwLjMsNC44LDFjMS40LDAuNiwyLjUsMS41LDMuNCwyLjZDMTczLjQsNzguOSwxNzQuMSw4MC4yLDE3NC41LDgxLjd6IE0xNzAsODYuNGMwLTIuNi0wLjUtNC42LTEuNC02CgkJCQkJYy0wLjktMS40LTIuNC0yLjEtNC4zLTIuMWMtMiwwLTMuNCwwLjctNC4zLDIuMWMtMC45LDEuNC0xLjQsMy40LTEuNCw2YzAsMi42LDAuNSw0LjYsMS40LDYuMWMwLjksMS40LDIuMywyLjEsNC4zLDIuMQoJCQkJCWMyLDAsMy40LTAuNyw0LjMtMi4xQzE2OS42LDkxLjEsMTcwLDg5LDE3MCw4Ni40eiBNMjExLjEsOTMuOWwxLjEsM2MwLjEsMC40LTAuMiwwLjUtMC4yLDAuNWMtMS43LDAuNy00LDEuMS02LjMsMS4xCgkJCQkJYy0zLjksMC02LjgtMS4xLTguOC0zLjNjLTItMi4yLTMtNS4yLTMtOC45YzAtMS43LDAuMi0zLjMsMC43LTQuOGMwLjUtMS41LDEuMi0yLjgsMi4yLTMuOWMxLTEuMSwyLjItMiwzLjYtMi42CgkJCQkJYzEuNC0wLjYsMy4xLTEsNS0xYzEuMywwLDIuNCwwLjEsMy4zLDAuMmMxLDAuMiwyLjQsMC41LDMsMC44YzAuMSwwLDAuNCwwLjIsMC4zLDAuNWMtMC40LDEuMi0wLjcsMi0xLjEsMwoJCQkJCWMtMC4yLDAuNS0wLjUsMC4zLTAuNSwwLjNjLTEuNS0wLjUtMi45LTAuNy00LjctMC43Yy0yLjIsMC0zLjksMC43LTQuOSwyLjJjLTEuMSwxLjQtMS43LDMuMy0xLjcsNS45YzAsMi44LDAuNyw0LjgsMS45LDYuMQoJCQkJCWMxLjIsMS4zLDIuOSwxLjksNS4xLDEuOWMwLjksMCwxLjctMC4xLDIuNC0wLjJjMC43LTAuMSwxLjQtMC4zLDIuMS0wLjZDMjEwLjUsOTMuNiwyMTAuOSw5My41LDIxMS4xLDkzLjl6IE0yMzMuOCw4MC44CgkJCQkJYzEsMy40LDAuNSw2LjMsMC40LDYuNWMwLDAuNC0wLjQsMC40LTAuNCwwLjRsLTE1LjEsMGMwLjEsMi4zLDAuNiwzLjksMS44LDVjMS4xLDEuMSwyLjgsMS44LDUuMiwxLjhjMy42LDAsNS4xLTAuNyw2LjItMS4xCgkJCQkJYzAsMCwwLjQtMC4xLDAuNiwwLjNsMSwyLjhjMC4yLDAuNSwwLDAuNi0wLjEsMC43Yy0wLjksMC41LTMuMiwxLjUtNy42LDEuNWMtMi4xLDAtNC0wLjMtNS41LTAuOWMtMS41LTAuNi0yLjgtMS40LTMuOC0yLjUKCQkJCQljLTEtMS4xLTEuNy0yLjQtMi4yLTMuOGMtMC41LTEuNS0wLjctMy4xLTAuNy00LjhjMC0xLjcsMC4yLTMuMywwLjctNC44YzAuNC0xLjUsMS4xLTIuOCwyLTMuOWMwLjktMS4xLDIuMS0yLDMuNS0yLjYKCQkJCQljMS40LTAuNywzLjEtMSw1LTFjMS42LDAsMy4xLDAuMyw0LjMsMC45YzAuOSwwLjQsMS45LDEuMSwyLjksMi4yQzIzMi41LDc3LjksMjMzLjQsNzkuNCwyMzMuOCw4MC44eiBNMjE4LjgsODRoMTAuNwoJCQkJCWMtMC4xLTEuNC0wLjQtMi42LTEtMy42Yy0wLjktMS40LTIuMi0yLjItNC4yLTIuMmMtMiwwLTMuNCwwLjgtNC4zLDIuMkMyMTkuNCw4MS4zLDIxOS4xLDgyLjUsMjE4LjgsODR6IE0xMTMuMSw4MC44CgkJCQkJYzEsMy40LDAuNSw2LjMsMC41LDYuNWMwLDAuNC0wLjQsMC40LTAuNCwwLjRsLTE1LjEsMGMwLjEsMi4zLDAuNiwzLjksMS44LDVjMS4xLDEuMSwyLjgsMS44LDUuMiwxLjhjMy42LDAsNS4xLTAuNyw2LjItMS4xCgkJCQkJYzAsMCwwLjQtMC4xLDAuNiwwLjNsMSwyLjhjMC4yLDAuNSwwLDAuNi0wLjEsMC43Yy0wLjksMC41LTMuMiwxLjUtNy42LDEuNWMtMi4xLDAtNC0wLjMtNS41LTAuOWMtMS41LTAuNi0yLjgtMS40LTMuOC0yLjUKCQkJCQljLTEtMS4xLTEuNy0yLjQtMi4yLTMuOGMtMC41LTEuNS0wLjctMy4xLTAuNy00LjhjMC0xLjcsMC4yLTMuMywwLjctNC44YzAuNC0xLjUsMS4xLTIuOCwyLTMuOWMwLjktMS4xLDIuMS0yLDMuNS0yLjYKCQkJCQljMS40LTAuNywzLjEtMSw1LTFjMS42LDAsMy4xLDAuMyw0LjMsMC45YzAuOSwwLjQsMS45LDEuMSwyLjksMi4yQzExMS44LDc3LjksMTEyLjgsNzkuNCwxMTMuMSw4MC44eiBNOTguMSw4NGgxMC44CgkJCQkJYy0wLjEtMS40LTAuNC0yLjYtMS0zLjZjLTAuOS0xLjQtMi4yLTIuMi00LjItMi4yYy0yLDAtMy40LDAuOC00LjMsMi4yQzk4LjcsODEuMyw5OC40LDgyLjUsOTguMSw4NHogTTcxLjYsODMuMgoJCQkJCWMwLDAsMS4yLDAuMSwyLjUsMC4zdi0wLjZjMC0yLTAuNC0zLTEuMi0zLjZjLTAuOC0wLjYtMi4xLTEtMy43LTFjMCwwLTMuNywwLTYuNiwxLjVjLTAuMSwwLjEtMC4yLDAuMS0wLjIsMC4xCgkJCQkJcy0wLjQsMC4xLTAuNS0wLjJsLTEuMS0yLjljLTAuMi0wLjQsMC4xLTAuNiwwLjEtMC42YzEuNC0xLjEsNC42LTEuNyw0LjYtMS43YzEuMS0wLjIsMi45LTAuNCw0LTAuNGMzLDAsNS4zLDAuNyw2LjksMi4xCgkJCQkJYzEuNiwxLjQsMi40LDMuNiwyLjQsNi43bDAsMTMuOGMwLDAsMCwwLjQtMC4zLDAuNWMwLDAtMC42LDAuMi0xLjEsMC4zYy0wLjUsMC4xLTIuMywwLjUtMy44LDAuN2MtMS41LDAuMy0zLDAuNC00LjYsMC40CgkJCQkJYy0xLjUsMC0yLjgtMC4xLTQtMC40Yy0xLjItMC4zLTIuMi0wLjctMy4xLTEuM2MtMC44LTAuNi0xLjUtMS40LTItMi40Yy0wLjUtMC45LTAuNy0yLjEtMC43LTMuNGMwLTEuMywwLjMtMi41LDAuOC0zLjUKCQkJCQljMC41LTEsMS4zLTEuOCwyLjItMi41YzAuOS0wLjcsMi0xLjEsMy4xLTEuNWMxLjItMC4zLDIuNC0wLjUsMy43LTAuNUM3MC4yLDgzLjIsNzEsODMuMiw3MS42LDgzLjJ6IE02NS42LDkzLjgKCQkJCQljMCwwLDEuNCwxLjEsNC40LDAuOWMyLjItMC4xLDQuMS0wLjUsNC4xLTAuNXYtNi45YzAsMC0xLjktMC4zLTQuMS0wLjNjLTMuMSwwLTQuNCwxLjEtNC40LDEuMWMtMC45LDAuNi0xLjMsMS42LTEuMywyLjkKCQkJCQljMCwwLjgsMC4yLDEuNSwwLjUsMkM2NC45LDkzLjIsNjUsOTMuNCw2NS42LDkzLjh6IE0xOTMuMSw3NS41Yy0wLjEsMC40LTAuOSwyLjUtMS4xLDMuMmMtMC4xLDAuMy0wLjMsMC40LTAuNiwwLjQKCQkJCQljMCwwLTAuOS0wLjItMS43LTAuMmMtMC41LDAtMS4zLDAuMS0yLDAuM2MtMC43LDAuMi0xLjMsMC42LTEuOSwxLjFjLTAuNiwwLjUtMSwxLjMtMS4zLDIuMmMtMC4zLDAuOS0wLjUsMi40LTAuNSw0djExLjIKCQkJCQljMCwwLjMtMC4yLDAuNS0wLjUsMC41aC00Yy0wLjMsMC0wLjUtMC4yLTAuNS0wLjVWNzUuMmMwLTAuMywwLjItMC41LDAuNC0wLjVoMy45YzAuMywwLDAuNCwwLjIsMC40LDAuNVY3NwoJCQkJCWMwLjYtMC44LDEuNi0xLjUsMi41LTEuOWMwLjktMC40LDItMC43LDMuOS0wLjZjMSwwLjEsMi4zLDAuMywyLjUsMC40QzE5Myw3NSwxOTMuMiw3NS4xLDE5My4xLDc1LjV6IE0xNTYsNjUuMQoJCQkJCWMwLjEsMCwwLjQsMC4yLDAuMywwLjVsLTEuMiwzLjJjLTAuMSwwLjItMC4yLDAuNC0wLjcsMC4yYy0wLjEsMC0wLjMtMC4xLTAuOC0wLjJjLTAuMy0wLjEtMC44LTAuMS0xLjItMC4xCgkJCQkJYy0wLjYsMC0xLjEsMC4xLTEuNiwwLjJjLTAuNSwwLjEtMC45LDAuNC0xLjMsMC44Yy0wLjQsMC40LTAuOCwwLjktMS4xLDEuNmMtMC42LDEuNi0wLjgsMy4zLTAuOCwzLjRoNC44CgkJCQkJYzAuNCwwLDAuNSwwLjIsMC41LDAuNWwtMC42LDMuMWMtMC4xLDAuNS0wLjUsMC40LTAuNSwwLjRoLTVMMTQzLjYsOThjLTAuNCwyLTAuOCwzLjctMS4zLDUuMWMtMC41LDEuNC0xLjEsMi40LTIsMy40CgkJCQkJYy0wLjgsMC45LTEuNywxLjYtMi44LDEuOWMtMSwwLjQtMi4zLDAuNi0zLjcsMC42Yy0wLjcsMC0xLjQsMC0yLjItMC4yYy0wLjYtMC4xLTAuOS0wLjItMS40LTAuNGMtMC4yLTAuMS0wLjMtMC4zLTAuMi0wLjYKCQkJCQljMC4xLTAuMywxLTIuNywxLjEtMy4xYzAuMi0wLjQsMC41LTAuMiwwLjUtMC4yYzAuMywwLjEsMC41LDAuMiwwLjgsMC4zYzAuNCwwLjEsMC44LDAuMSwxLjIsMC4xYzAuNywwLDEuMy0wLjEsMS44LTAuMwoJCQkJCWMwLjYtMC4yLDEtMC42LDEuNC0xLjFjMC40LTAuNSwwLjctMS4yLDEuMS0yLjFjMC4zLTAuOSwwLjYtMi4yLDAuOS0zLjdsMy40LTE4LjloLTMuM2MtMC40LDAtMC41LTAuMi0wLjUtMC41bDAuNi0zLjEKCQkJCQljMC4xLTAuNSwwLjUtMC40LDAuNS0wLjRoMy40bDAuMi0xYzAuNS0zLDEuNS01LjMsMy02LjhjMS41LTEuNSwzLjctMi4zLDYuNC0yLjNjMC44LDAsMS41LDAuMSwyLjEsMC4yCgkJCQkJQzE1NSw2NC44LDE1NS41LDY0LjksMTU2LDY1LjF6IE04OC42LDk3LjZjMCwwLjMtMC4yLDAuNS0wLjQsMC41aC00Yy0wLjMsMC0wLjQtMC4yLTAuNC0wLjVWNjUuNWMwLTAuMiwwLjItMC41LDAuNC0wLjVoNAoJCQkJCWMwLjMsMCwwLjQsMC4yLDAuNCwwLjVWOTcuNnoiLz4KCQkJPC9nPgoJCTwvZz4KCTwvZz4KPC9nPgo8L3N2Zz4K"]]));
async function makeRequest(options) {
const rawResponse = await new transport_1.default().httpRequest(options);
if (rawResponse?.headers?.['content-type'] === 'text/html') {
const htmlResponseError = messages.createError('error.HttpApi');
htmlResponseError.setData(rawResponse.body);
throw htmlResponseError;
}
const response = (0, kit_1.parseJsonMap)(rawResponse.body);
if (response.error) {
const errorDescription = typeof response.error_description === 'string' ? response.error_description : '';
const error = typeof response.error === 'string' ? response.error : 'Unknown';
const err = new sfError_1.SfError(`Request Failed: ${error} ${errorDescription}`);
err.data = Object.assign(response, { status: rawResponse.statusCode });
throw err;
}
else {
return response;
}
}
/**
* Handles device based login flows
*
* Usage:
* ```
* const oauthConfig = {
* loginUrl: this.flags.instanceurl,
* clientId: this.flags.clientid,
* };
* const deviceOauthService = await DeviceOauthService.create(oauthConfig);
* const loginData = await deviceOauthService.requestDeviceLogin();
* console.log(loginData);
* const approval = await deviceOauthService.awaitDeviceApproval(loginData);
* const authInfo = await deviceOauthService.authorizeAndSave(approval);
* ```
*/
class DeviceOauthService extends kit_1.AsyncCreatable {
static RESPONSE_TYPE = 'device_code';
static GRANT_TYPE = 'device';
static SCOPE = 'refresh_token web api';
static POLLING_COUNT_MAX = 100;
logger;
options;
pollingCount = 0;
constructor(options) {
super(options);
this.options = options;
if (!this.options.clientId)
this.options.clientId = authInfo_1.DEFAULT_CONNECTED_APP_INFO.clientId;
if (!this.options.loginUrl)
this.options.loginUrl = authInfo_1.AuthInfo.getDefaultInstanceUrl();
}
/**
* Begin the authorization flow by requesting the login
*
* @returns {Promise<DeviceCodeResponse>}
*/
async requestDeviceLogin() {
const deviceFlowRequestUrl = this.getDeviceFlowRequestUrl();
const loginOptions = this.getLoginOptions(deviceFlowRequestUrl);
return makeRequest(loginOptions);
}
/**
* Polls the server until successful response OR max attempts have been made
*
* @returns {Promise<Nullable<DeviceCodePollingResponse>>}
*/
async awaitDeviceApproval(loginData) {
const deviceFlowRequestUrl = this.getDeviceFlowRequestUrl();
const pollingOptions = this.getPollingOptions(deviceFlowRequestUrl, loginData.device_code);
const interval = kit_1.Duration.seconds(loginData.interval).milliseconds;
return this.pollForDeviceApproval(pollingOptions, interval);
}
/**
* Creates and saves new AuthInfo
*
* @returns {Promise<AuthInfo>}
*/
async authorizeAndSave(approval) {
const authInfo = await authInfo_1.AuthInfo.create({
oauth2Options: {
loginUrl: approval.instance_url,
refreshToken: approval.refresh_token,
clientSecret: this.options.clientSecret,
clientId: this.options.clientId,
},
});
await authInfo.save();
return authInfo;
}
async init() {
this.logger = await logger_1.Logger.child(this.constructor.name);
this.logger.debug(`this.options.clientId: ${this.options.clientId}`);
this.logger.debug(`this.options.loginUrl: ${this.options.loginUrl}`);
}
getLoginOptions(url) {
const form = new form_data_1.default();
form.append('client_id', (0, ts_types_1.ensureString)(this.options.clientId));
form.append('response_type', DeviceOauthService.RESPONSE_TYPE);
form.append('scope', DeviceOauthService.SCOPE);
return {
url,
headers: { ...connection_1.SFDX_HTTP_HEADERS, ...form.getHeaders() },
method: 'POST',
body: form.getBuffer(),
};
}
getPollingOptions(url, code) {
const form = new form_data_1.default();
form.append('client_id', (0, ts_types_1.ensureString)(this.options.clientId));
form.append('grant_type', DeviceOauthService.GRANT_TYPE);
form.append('code', code);
return {
url,
headers: { ...connection_1.SFDX_HTTP_HEADERS, ...form.getHeaders() },
method: 'POST',
body: form.getBuffer(),
};
}
getDeviceFlowRequestUrl() {
return `${(0, ts_types_1.ensureString)(this.options.loginUrl)}/services/oauth2/token`;
}
async poll(httpRequest) {
this.logger.debug(`polling for device approval (attempt ${this.pollingCount} of ${DeviceOauthService.POLLING_COUNT_MAX})`);
try {
return await makeRequest(httpRequest);
}
catch (e) {
if (e instanceof sfError_1.SfError && e.name === 'HttpApiError') {
throw e;
}
const err = (e instanceof sfError_1.SfError ? e.data : sfError_1.SfError.wrap((0, ts_types_1.isString)(e) ? e : 'unknown').data);
if (err?.error && err?.status === 400 && err?.error === 'authorization_pending') {
// do nothing because we're still waiting
}
else {
if (err?.error && err?.error_description) {
this.logger.error(`Polling error: ${err.error}: ${err.error_description}`);
}
else {
this.logger.error('Unknown Polling Error:');
this.logger.error(err ?? e);
}
throw err ?? e;
}
}
}
shouldContinuePolling() {
return this.pollingCount < DeviceOauthService.POLLING_COUNT_MAX;
}
async pollForDeviceApproval(httpRequest, interval) {
this.logger.debug('BEGIN POLLING FOR DEVICE APPROVAL');
let result;
while (this.shouldContinuePolling()) {
// eslint-disable-next-line no-await-in-loop
result = await this.poll(httpRequest);
if (result) {
this.logger.debug('POLLING FOR DEVICE APPROVAL SUCCESS');
break;
}
else {
this.logger.debug(`waiting ${interval} ms...`);
// eslint-disable-next-line no-await-in-loop
await (0, kit_1.sleep)(interval);
this.pollingCount += 1;
}
}
if (this.pollingCount >= DeviceOauthService.POLLING_COUNT_MAX) {
// stop polling, the user has likely abandoned the command...
this.logger.error(`Polling timed out because max polling was hit: ${this.pollingCount}`);
throw messages.createError('pollingTimeout');
}
return result;
}
}
exports.DeviceOauthService = DeviceOauthService;
//# sourceMappingURL=deviceOauthService.js.map