vtex
Version:
The platform for e-commerce apps
92 lines (91 loc) • 4.11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const axios_1 = tslib_1.__importDefault(require("axios"));
const crypto_1 = require("crypto");
const jsonwebtoken_1 = tslib_1.__importDefault(require("jsonwebtoken"));
const opn_1 = tslib_1.__importDefault(require("opn"));
const path_1 = require("path");
const VTEXID_1 = require("../../../../api/clients/IOClients/external/VTEXID");
const storeUrl_1 = require("../../../../api/storeUrl");
const randomCryptoString_1 = require("../../../utils/randomCryptoString");
const spawnUnblockingChildProcess_1 = require("../../../utils/spawnUnblockingChildProcess");
const AuthProviderBase_1 = require("../AuthProviderBase");
const LoginServer_1 = require("./LoginServer");
class OAuthAuthenticator extends AuthProviderBase_1.AuthProviderBase {
async login(account) {
const secret = randomCryptoString_1.randomCryptoString(128, OAuthAuthenticator.SECRET_ALPHABET);
const secretHash = this.hashSecret(secret);
const vtexId = VTEXID_1.VTEXID.createClient({ account });
const loginServer = await LoginServer_1.LoginServer.create({
account,
secret,
});
try {
const loginState = await vtexId.startToolbeltLogin({
account,
secretHash,
loopbackUrl: loginServer.loginCallbackUrl,
});
loginServer.setLoginState(loginState);
const url = await this.loginUrl(account, loginState);
opn_1.default(url, { wait: false });
const token = await loginServer.token;
const decodedToken = jsonwebtoken_1.default.decode(token);
const login = decodedToken.sub;
this.closeChromeTabIfMac(loginServer.loginCallbackUrl);
return { login, token };
}
finally {
loginServer.close();
}
}
hashSecret(secret) {
return crypto_1.createHash('sha256')
.update(secret)
.digest('base64');
}
async loginUrl(account, loginState) {
const hasAdminLogin = await this.hasAdminLoginInstalled(account);
const returnUrl = `/api/vtexid/toolbelt/callback?state=${encodeURIComponent(loginState)}`;
let loginPathPrefix;
if (!hasAdminLogin) {
// If for some reason vtex.admin-login is not installed in the account, fallback to use auth-server login url
loginPathPrefix = storeUrl_1.storeUrl({
account,
addWorkspace: false,
path: OAuthAuthenticator.FALLBACK_AUTH_SERVER_LOGIN_URL_PATH,
});
}
else {
loginPathPrefix = storeUrl_1.storeUrl({ account, addWorkspace: false, path: OAuthAuthenticator.ADMIN_LOGIN_URL_PATH });
}
return `${loginPathPrefix}?returnUrl=${encodeURIComponent(returnUrl)}`;
}
async hasAdminLoginInstalled(account) {
var _a;
try {
const { data } = await axios_1.default.get(storeUrl_1.storeUrl({ account, addWorkspace: false, path: '/_v/segment/admin-login/v1/login' }));
return data.includes('vtex.admin-login');
}
catch (err) {
if (((_a = err.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
return false;
}
throw err;
}
}
closeChromeTabIfMac(loginCallbackUrl) {
if (process.platform === 'darwin') {
spawnUnblockingChildProcess_1.spawnUnblockingChildProcess('osascript', [
path_1.join(__dirname, '../../../../scripts/closeChrome.scpt'),
loginCallbackUrl,
]);
}
}
}
exports.OAuthAuthenticator = OAuthAuthenticator;
OAuthAuthenticator.AUTH_TYPE = 'oauth';
OAuthAuthenticator.SECRET_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
OAuthAuthenticator.ADMIN_LOGIN_URL_PATH = '/_v/segment/admin-login/v1/login';
OAuthAuthenticator.FALLBACK_AUTH_SERVER_LOGIN_URL_PATH = '/_v/private/auth-server/v1/login';