You're Invited: Meet the Socket team at BSidesSF and RSAC - April 27 - May 1.RSVP
Socket
Sign inDemoInstall
Socket

@frontegg/client

Package Overview
Dependencies
Maintainers
1
Versions
184
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@frontegg/client - npm Package Compare versions

Comparing version

to
1.2.3

dist/src/middleware/ContextHolder.d.ts

8

dist/src/authenticator/index.js

@@ -61,3 +61,3 @@ "use strict";

switch (_a.label) {
case 0: return [4 /*yield*/, this.authenticate()];
case 0: return [4 /*yield*/, this.authenticate(true)];
case 1:

@@ -86,3 +86,4 @@ _a.sent();

};
FronteggAuthenticator.prototype.authenticate = function () {
FronteggAuthenticator.prototype.authenticate = function (force) {
if (force === void 0) { force = false; }
return __awaiter(this, void 0, void 0, function () {

@@ -94,2 +95,5 @@ var response, e_1, _a, token, expiresIn, nextRefresh;

case 0:
if (this.accessToken !== '' && !force) {
return [2 /*return*/];
}
logger_1.default.info('posting authentication request');

@@ -96,0 +100,0 @@ _b.label = 1;

@@ -72,11 +72,12 @@ "use strict";

return __awaiter(this, void 0, void 0, function () {
var authenticator, response, publicKey;
return __generator(this, function (_a) {
switch (_a.label) {
var authenticator, _a, FRONTEGG_CLIENT_ID, FRONTEGG_API_KEY, response, publicKey;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
authenticator = new authenticator_1.FronteggAuthenticator();
logger_1.default.info('going to authenticate');
return [4 /*yield*/, authenticator.init(middleware_1.FRONTEGG_CLIENT_ID || process.env.FRONTEGG_CLIENT_ID || '', middleware_1.FRONTEGG_API_KEY || process.env.FRONTEGG_API_KEY || '')];
_a = middleware_1.ContextHolder.getContext(), FRONTEGG_CLIENT_ID = _a.FRONTEGG_CLIENT_ID, FRONTEGG_API_KEY = _a.FRONTEGG_API_KEY;
return [4 /*yield*/, authenticator.init(FRONTEGG_CLIENT_ID || process.env.FRONTEGG_CLIENT_ID || '', FRONTEGG_API_KEY || process.env.FRONTEGG_API_KEY || '')];
case 1:
_a.sent();
_b.sent();
logger_1.default.info('going to get identity service configuration');

@@ -89,3 +90,3 @@ return [4 /*yield*/, axios_1.default.get(config_1.config.urls.identityService + "/resources/configurations/v1", {

case 2:
response = _a.sent();
response = _b.sent();
logger_1.default.info('got identity service configuration');

@@ -92,0 +93,0 @@ publicKey = response.data.publicKey;

@@ -1,36 +0,4 @@

/// <reference types="node" />
import { NextFunction, Request, Response } from 'express';
import { IncomingMessage, ServerResponse } from 'http';
import { FronteggPermissions } from '../permissions';
export declare let FRONTEGG_CLIENT_ID: string;
export declare let FRONTEGG_API_KEY: string;
declare type fronteggContextResolver = (req: Request) => Promise<{
tenantId: string;
userId: string;
permissions: FronteggPermissions[];
}>;
declare type AuthMiddleware = (req: Request, res: Response, next: NextFunction) => Promise<any> | any;
export interface IFronteggOptions {
clientId: string;
apiKey: string;
contextResolver: fronteggContextResolver;
authMiddleware?: AuthMiddleware;
disableCors?: boolean;
cookieDomainRewrite?: string;
maxRetries?: number;
}
export declare function frontegg(options: IFronteggOptions): (req: any, res: any) => Promise<any>;
declare type ProxyIncomingMessage = IncomingMessage & Partial<{
host: string;
hostname: string;
originalUrl: string;
}>;
declare type ProxyServerResponse<T = any> = ServerResponse & {
status: (statusCode: number) => ProxyServerResponse<T>;
send: (body: T) => void;
};
declare type INextJsFronteggOptions = IFronteggOptions & {
prefixRoute: string;
};
export declare const fronteggNextJs: (options: INextJsFronteggOptions) => (req: ProxyIncomingMessage, res: ProxyServerResponse<any>) => Promise<any>;
export {};
export * from './fronteggMiddleware';
export * from './fronteggNextJs';
export * from './types';
export * from './ContextHolder';
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var _this = this;
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
var httpProxy = require("http-proxy");
var authenticator_1 = require("../authenticator");
var logger_1 = require("../helpers/logger");
var permissions_1 = require("../permissions");
var FronteggRoutes_1 = require("./FronteggRoutes");
var proxy = httpProxy.createProxyServer({ secure: false, changeOrigin: true });
var target = process.env.FRONTEGG_API_GATEWAY_URL || 'https://api.frontegg.com/';
var authenticator = new authenticator_1.FronteggAuthenticator();
var Whitelist = ['/metadata'];
var MAX_RETRIES = 3;
function getUrlWithoutQueryParams(req) {
return req.url.split('?').shift();
}
function rewriteCookieDomain(header, oldDomain, newDomain) {
if (Array.isArray(header)) {
return header.map(function (headerElement) {
return rewriteCookieDomain(headerElement, oldDomain, newDomain);
});
}
return header.replace(new RegExp("(;\\s*domain=)" + oldDomain + ";", 'i'), "$1" + newDomain + ";");
}
function proxyRequest(req, res, context) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
logger_1.default.log("going to proxy request - " + req.originalUrl + " to " + target);
return [4 /*yield*/, proxy.web(req, res, {
target: target,
headers: {
'x-access-token': authenticator.accessToken,
'frontegg-tenant-id': context && context.tenantId ? context.tenantId : '',
'frontegg-user-id': context && context.userId ? context.userId : '',
'frontegg-vendor-host': req.hostname,
},
})];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
}
function flattenPermissions(permissions) {
var output = [];
for (var _i = 0, permissions_2 = permissions; _i < permissions_2.length; _i++) {
var p = permissions_2[_i];
// noinspection SuspiciousTypeOfGuard
if (typeof (p) === 'string') {
output.push(p);
}
else if (Array.isArray(p)) {
for (var _a = 0, p_1 = p; _a < p_1.length; _a++) {
var item = p_1[_a];
output.push(item);
}
}
else {
logger_1.default.log('running keys on - ', p);
var keys = Object.keys(p);
for (var _b = 0, keys_1 = keys; _b < keys_1.length; _b++) {
var key = keys_1[_b];
output.push.apply(output, flattenPermissions([p[key]]));
}
}
}
return output;
}
function validatePermissions(req, res, context) {
return __awaiter(this, void 0, void 0, function () {
var permissions, url, _i, Whitelist_1, whiteListed, allowedOperations, _a, allowedOperations_1, operation, allowedMethod, route;
return __generator(this, function (_b) {
permissions = context.permissions;
if (!permissions) {
logger_1.default.error('No permissions were passed for frontegg middleware');
throw new Error('No permissions were passed for frontegg middleware');
}
if (!permissions.length) {
logger_1.default.error('Permissions array is empty for frontegg middleware');
throw new Error('Permissions array is empty for frontegg middleware');
}
// We allow OPTIONS
if (req.method === 'OPTIONS') {
logger_1.default.log('OPTIONS is allowed');
return [2 /*return*/];
}
if (permissions.includes(permissions_1.FronteggPermissions.All)) {
logger_1.default.log('User is authorized for ALL actions in the system');
return [2 /*return*/];
}
url = getUrlWithoutQueryParams(req);
for (_i = 0, Whitelist_1 = Whitelist; _i < Whitelist_1.length; _i++) {
whiteListed = Whitelist_1[_i];
if (url.startsWith(whiteListed)) {
logger_1.default.log("URL " + url + " is whitelisted");
return [2 /*return*/];
}
}
allowedOperations = flattenPermissions(permissions);
logger_1.default.log("allowedOperations for this user - ", allowedOperations);
for (_a = 0, allowedOperations_1 = allowedOperations; _a < allowedOperations_1.length; _a++) {
operation = allowedOperations_1[_a];
if (operation === '*') {
logger_1.default.log("All operations are allowed for this user");
return [2 /*return*/];
}
allowedMethod = operation.split(' ')[0];
route = operation.split(' ')[1];
if (allowedMethod === '*' && url.startsWith(route)) {
logger_1.default.log("User is authorized for ALL route");
return [2 /*return*/];
}
if (url === route && req.method === allowedMethod) {
logger_1.default.log("User is authorized for " + req.method + " " + req.baseUrl);
return [2 /*return*/];
}
}
logger_1.default.error("No matching permission for " + req.method + " " + url + ". Permissions - " + allowedOperations);
throw new Error("No matching permission for " + req.method + " " + url);
});
});
}
function callMiddleware(req, res, middleware) {
return __awaiter(this, void 0, void 0, function () {
var middlewareWrap, nextValue;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
middlewareWrap = new Promise(function (next, reject) { return __awaiter(_this, void 0, void 0, function () {
var e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, middleware(req, res, next)];
case 1:
_a.sent();
return [3 /*break*/, 3];
case 2:
e_1 = _a.sent();
reject(e_1);
return [3 /*break*/, 3];
case 3:
next();
return [2 /*return*/];
}
});
}); });
return [4 /*yield*/, middlewareWrap];
case 1:
nextValue = _a.sent();
if (nextValue) {
throw new Error(nextValue);
}
return [2 /*return*/];
}
});
});
}
function frontegg(options) {
var _this = this;
var _a = options.maxRetries, maxRetries = _a === void 0 ? MAX_RETRIES : _a;
logger_1.default.debug('you got to my frontegg middleware');
if (!options) {
throw new Error('Missing options');
}
if (!options.clientId) {
throw new Error('Missing client ID');
}
if (!options.apiKey) {
throw new Error('Missing api key');
}
if (!options.contextResolver) {
throw new Error('Missing context resolver');
}
exports.FRONTEGG_CLIENT_ID = options.clientId;
exports.FRONTEGG_API_KEY = options.apiKey;
var authInitedPromise = authenticator.init(options.clientId, options.apiKey);
proxy.on('error', function (err, req, res, _) { return __awaiter(_this, void 0, void 0, function () {
var context;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
logger_1.default.error("Failed proxy request to " + req.url + " - ", err);
req.frontegg.retryCount++;
logger_1.default.info("retry count of " + req.url + " - ", req.frontegg.retryCount);
if (req.frontegg.retryCount >= maxRetries) {
res.writeHead(500).end('Frontegg request failed');
return [2 /*return*/];
}
return [4 /*yield*/, options.contextResolver(req)];
case 1:
context = _a.sent();
return [2 /*return*/, proxyRequest(req, res, context)];
}
});
}); });
proxy.on('proxyRes', function (proxyRes, req, res) { return __awaiter(_this, void 0, void 0, function () {
var context, host_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
logger_1.default.debug("proxyRes - returned for " + req.originalUrl);
if (!options.disableCors) {
enableCors(req, proxyRes);
}
else {
delete proxyRes.headers['access-control-allow-methods'];
delete proxyRes.headers['access-control-allow-headers'];
delete proxyRes.headers['access-control-allow-origin'];
delete proxyRes.headers['access-control-allow-credentials'];
}
if (!(proxyRes.statusCode === 401)) return [3 /*break*/, 3];
req.frontegg.retryCount = req.frontegg.retryCount + 1;
logger_1.default.log(req.url + " failed with authentication error from proxy - retryCount - ", req.frontegg.retryCount);
if (!(req.frontegg.retryCount <= MAX_RETRIES)) return [3 /*break*/, 3];
logger_1.default.warn('going to refresh authentication');
return [4 /*yield*/, authenticator.refreshAuthentication()];
case 1:
_a.sent();
logger_1.default.warn('refreshed authentication');
return [4 /*yield*/, options.contextResolver(req)];
case 2:
context = _a.sent();
return [2 /*return*/, proxyRequest(req, res, context)];
case 3:
if (options.cookieDomainRewrite) {
host_1 = req.headers.host;
Object.keys(proxyRes.headers).forEach(function (key) {
if (key.toLowerCase() === 'set-cookie') {
proxyRes.headers[key] = rewriteCookieDomain(proxyRes.headers[key], host_1, options.cookieDomainRewrite);
}
});
}
return [2 /*return*/];
}
});
}); });
function enableCors(req, res) {
if (req.headers['access-control-request-method']) {
logger_1.default.debug("enableCors - going to set access-control-request-method");
res.headers['access-control-allow-methods'] = req.headers['access-control-request-method'];
}
if (req.headers['access-control-request-headers']) {
logger_1.default.debug("enableCors - going to set access-control-request-headers");
res.headers['access-control-allow-headers'] = req.headers['access-control-request-headers'];
}
if (req.headers.origin) {
logger_1.default.debug("enableCors - going to set access-control-allow-origin to " + req.headers.origin);
res.headers['access-control-allow-origin'] = req.headers.origin;
res.headers['access-control-allow-credentials'] = 'true';
}
}
proxy.on('proxyReq', function (proxyReq, req, res, _) {
if (req.hostname) {
proxyReq.setHeader('frontegg-vendor-host', req.hostname);
}
if (req.body) {
var bodyData = Buffer.isBuffer(req.body) ? req.body : JSON.stringify(req.body);
// in case if content-type is application/x-www-form-urlencoded -> we need to change to application/json
proxyReq.setHeader('Content-Type', 'application/json');
proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
// stream the content
proxyReq.write(bodyData);
}
});
// tslint:disable-next-line:only-arrow-functions
return function (req, res) { return __awaiter(_this, void 0, void 0, function () {
var _a, e_2, context, e_3;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, authInitedPromise];
case 1:
_b.sent();
_a = options.authMiddleware;
if (!_a) return [3 /*break*/, 3];
return [4 /*yield*/, FronteggRoutes_1.fronteggRoutes.isFronteggPublicRoute(req)];
case 2:
_a = !(_b.sent());
_b.label = 3;
case 3:
if (!_a) return [3 /*break*/, 7];
logger_1.default.debug('will pass request threw the auth middleware');
_b.label = 4;
case 4:
_b.trys.push([4, 6, , 7]);
return [4 /*yield*/, callMiddleware(req, res, options.authMiddleware)];
case 5:
_b.sent();
if (res.headersSent) {
// response was already sent from the middleware, we have nothing left to do
return [2 /*return*/];
}
return [3 /*break*/, 7];
case 6:
e_2 = _b.sent();
logger_1.default.error("Failed to call middleware - ", e_2);
return [2 /*return*/, res.status(401).send(e_2.message)];
case 7:
logger_1.default.debug("going to resolve resolve context");
return [4 /*yield*/, options.contextResolver(req)];
case 8:
context = _b.sent();
logger_1.default.debug("context resolved - " + JSON.stringify(context));
if (req.method === 'OPTIONS') {
// tslint:disable-next-line:no-console
console.log('OPTIONS call to frontegg middleware - returning STATUS 204');
res.status(204).send();
return [2 /*return*/];
}
logger_1.default.debug("going to validate permissions for - ", req.url);
_b.label = 9;
case 9:
_b.trys.push([9, 11, , 12]);
return [4 /*yield*/, validatePermissions(req, res, context)];
case 10:
_b.sent();
return [3 /*break*/, 12];
case 11:
e_3 = _b.sent();
logger_1.default.error('Failed at permissions check - ', e_3);
return [2 /*return*/, res.status(403).send()];
case 12:
if (!req.frontegg) {
req.frontegg = {};
}
req.frontegg.retryCount = 0;
logger_1.default.debug("going to proxy request");
return [2 /*return*/, proxyRequest(req, res, context)];
}
});
}); };
}
exports.frontegg = frontegg;
exports.fronteggNextJs = function (options) {
var fronteggProxy = frontegg(__assign({ maxRetries: 0 }, options));
return function (req, res) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (!req.url) {
res.status(500).send('Internal Server Error');
return [2 /*return*/];
}
req.host = req.headers.host;
req.hostname = req.headers.host;
req.originalUrl = req.url;
if (req.url.startsWith(options.prefixRoute)) {
req.url = req.url.substring(options.prefixRoute.length);
}
return [2 /*return*/, fronteggProxy(req, res)];
});
}); };
};
__export(require("./fronteggMiddleware"));
__export(require("./fronteggNextJs"));
__export(require("./ContextHolder"));
//# sourceMappingURL=index.js.map
{
"name": "@frontegg/client",
"version": "1.2.2",
"version": "1.2.3",
"description": "Frontegg Javascript Library for backend",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet