New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
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 4.2.0-alpha.2 to 4.2.0-alpha.3

dist/src/cache/cache.manager.interface.d.ts

2

dist/src/clients/hosted-login/types/code-exchange-response.d.ts

@@ -1,2 +0,2 @@

import { IUser } from '../../../middlewares';
import { IUser } from "../../identity/types";
export interface CodeExchangeResponse {

@@ -3,0 +3,0 @@ /**

@@ -1,3 +0,3 @@

import { IFronteggContext } from '../../components/frontegg-context';
import { IUser, IWithAuthenticationOptions } from '../../middlewares';
import { AuthHeaderType, IValidateTokenOptions, TEntity } from './types';
import { IFronteggContext } from '../../components/frontegg-context/types';
export declare class IdentityClient {

@@ -10,4 +10,4 @@ static getInstance(): IdentityClient;

getPublicKey(): Promise<string>;
validateIdentityOnToken(token: string, options?: IWithAuthenticationOptions): Promise<IUser>;
validateIdentityOnToken(token: string, options?: IValidateTokenOptions, type?: AuthHeaderType): Promise<TEntity>;
private fetchPublicKey;
}

@@ -41,3 +41,2 @@ "use strict";

var axios_1 = require("axios");
var jsonwebtoken_1 = require("jsonwebtoken");
var authenticator_1 = require("../../authenticator");

@@ -47,2 +46,6 @@ var config_1 = require("../../config");

var frontegg_context_1 = require("../../components/frontegg-context");
var types_1 = require("./types");
var token_resolvers_1 = require("./token-resolvers");
var failed_to_authenticate_exception_1 = require("./exceptions/failed-to-authenticate.exception");
var tokenResolvers = [token_resolvers_1.authorizationHeaderResolver, token_resolvers_1.accessTokenHeaderResolver];
var IdentityClient = /** @class */ (function () {

@@ -76,80 +79,40 @@ function IdentityClient(context) {

};
IdentityClient.prototype.validateIdentityOnToken = function (token, options) {
IdentityClient.prototype.validateIdentityOnToken = function (token, options, type) {
if (type === void 0) { type = types_1.AuthHeaderType.JWT; }
return __awaiter(this, void 0, void 0, function () {
var _this = this;
var publicKey, e_1, resolver, entity;
return __generator(this, function (_a) {
/* eslint-disable no-async-promise-executor */
return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
var publicKey, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
try {
token = token.replace('Bearer ', '');
}
catch (e) {
logger_1.default.error('Failed to extract token - ', token);
reject({ statusCode: 401, message: 'Failed to verify authentication' });
return [2 /*return*/];
}
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.getPublicKey()];
case 2:
publicKey = _a.sent();
return [3 /*break*/, 4];
case 3:
e_1 = _a.sent();
logger_1.default.error('failed to get public key - ', e_1);
reject({ statusCode: 401, message: 'Failed to verify authentication' });
return [2 /*return*/];
case 4:
(0, jsonwebtoken_1.verify)(token, publicKey, { algorithms: ['RS256'] }, function (err, decoded) {
var user = decoded;
if (err) {
logger_1.default.error('Failed to verify jwt - ', err);
reject({ statusCode: 401, message: 'Failed to verify authentication' });
return;
}
if (options) {
var roles = options.roles, permissions = options.permissions;
if (roles && roles.length > 0) {
var haveAtLeastOneRole = false;
for (var _i = 0, roles_1 = roles; _i < roles_1.length; _i++) {
var requestedRole = roles_1[_i];
if (user.roles && user.roles.includes(requestedRole)) {
haveAtLeastOneRole = true;
break;
}
}
if (!haveAtLeastOneRole) {
logger_1.default.info('Insufficient role');
reject({ statusCode: 403, message: 'Insufficient role' });
return;
}
}
if (permissions && permissions.length > 0) {
var haveAtLeastOnePermission = false;
for (var _a = 0, permissions_1 = permissions; _a < permissions_1.length; _a++) {
var requestedPermission = permissions_1[_a];
if (user.permissions && user.permissions.includes(requestedPermission)) {
haveAtLeastOnePermission = true;
break;
}
}
if (!haveAtLeastOnePermission) {
logger_1.default.info('Insufficient permission');
reject({ statusCode: 403, message: 'Insufficient permission' });
return;
}
}
}
// Store the decoded user on the request
resolve(user);
});
return [2 /*return*/];
switch (_a.label) {
case 0:
if (type === types_1.AuthHeaderType.JWT) {
try {
token = token.replace('Bearer ', '');
}
});
}); })];
catch (e) {
logger_1.default.error('Failed to extract token - ', token);
throw new failed_to_authenticate_exception_1.FailedToAuthenticateException();
}
}
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.getPublicKey()];
case 2:
publicKey = _a.sent();
return [3 /*break*/, 4];
case 3:
e_1 = _a.sent();
logger_1.default.error('failed to get public key - ', e_1);
throw new failed_to_authenticate_exception_1.FailedToAuthenticateException();
case 4:
resolver = tokenResolvers.find(function (resolver) { return resolver.shouldHandle(type); });
if (!resolver) {
logger_1.default.error('Failed to find token resolver');
throw new failed_to_authenticate_exception_1.FailedToAuthenticateException();
}
return [4 /*yield*/, resolver.validateToken(token, publicKey, options)];
case 5:
entity = _a.sent();
return [2 /*return*/, entity];
}
});

@@ -156,0 +119,0 @@ });

@@ -1,12 +0,15 @@

export interface IFronteggContext {
FRONTEGG_CLIENT_ID: string;
FRONTEGG_API_KEY: string;
}
import { IFronteggContext, IFronteggOptions } from './types';
export declare class FronteggContext {
static getInstance(): FronteggContext;
static init(context: IFronteggContext): void;
static init(context: IFronteggContext, options?: IFronteggOptions): void;
static getContext(): IFronteggContext;
static getOptions(): IFronteggOptions;
private static instance;
private context;
private options;
private constructor();
private validateOptions;
private validateAccessTokensOptions;
private validateIORedisOptions;
private validateRedisOptions;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FronteggContext = void 0;
var package_loader_1 = require("../../utils/package-loader");
var FronteggContext = /** @class */ (function () {
function FronteggContext() {
this.context = null;
this.options = {};
}

@@ -14,4 +16,6 @@ FronteggContext.getInstance = function () {

};
FronteggContext.init = function (context) {
FronteggContext.init = function (context, options) {
FronteggContext.getInstance().context = context;
FronteggContext.getInstance().validateOptions(options);
FronteggContext.getInstance().options = options !== null && options !== void 0 ? options : {};
};

@@ -24,2 +28,39 @@ FronteggContext.getContext = function () {

};
FronteggContext.getOptions = function () {
return FronteggContext.getInstance().options || {};
};
FronteggContext.prototype.validateOptions = function (options) {
if (options === null || options === void 0 ? void 0 : options.accessTokensOptions) {
this.validateAccessTokensOptions(options.accessTokensOptions);
}
};
FronteggContext.prototype.validateAccessTokensOptions = function (accessTokensOptions) {
if (!accessTokensOptions.cache) {
throw new Error("'cache' is missing from access tokens options");
}
if (accessTokensOptions.cache.type === 'ioredis') {
this.validateIORedisOptions(accessTokensOptions.cache.options);
}
else if (accessTokensOptions.cache.type === 'redis') {
this.validateRedisOptions(accessTokensOptions.cache.options);
}
};
FronteggContext.prototype.validateIORedisOptions = function (redisOptions) {
package_loader_1.PackageUtils.loadPackage('ioredis');
var requiredProperties = ['host', 'password', 'port', 'db'];
requiredProperties.forEach(function (requiredProperty) {
if (redisOptions[requiredProperty] === undefined) {
throw new Error("".concat(requiredProperty, " is missing from ioredis cache options"));
}
});
};
FronteggContext.prototype.validateRedisOptions = function (redisOptions) {
package_loader_1.PackageUtils.loadPackage('redis');
var requiredProperties = ['url'];
requiredProperties.forEach(function (requiredProperty) {
if (redisOptions[requiredProperty] === undefined) {
throw new Error("".concat(requiredProperty, " is missing from redis cache options"));
}
});
};
return FronteggContext;

@@ -26,0 +67,0 @@ }());

@@ -6,29 +6,2 @@ import { Request, Response } from 'express';

}
export declare enum tokenTypes {
UserApiToken = "userApiToken",
TenantApiToken = "tenantApiToken",
UserToken = "userToken"
}
export declare type Role = string;
export declare type Permission = string;
export interface IUser {
id?: string;
sub: string;
tenantId: string;
roles: Role[];
permissions: Permission[];
metadata: Record<string, any>;
createdByUserId: string;
type: tokenTypes;
name?: string;
email?: string;
email_verified?: boolean;
invisible?: true;
tenantIds?: string[];
profilePictureUrl?: string;
}
export interface StatusCodeError {
statusCode: number;
message: string;
}
export declare function withAuthentication({ roles, permissions }?: IWithAuthenticationOptions): (req: Request, res: Response, next: any) => Promise<any>;

@@ -50,11 +50,6 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.withAuthentication = exports.tokenTypes = void 0;
exports.withAuthentication = void 0;
var clients_1 = require("../clients");
var logger_1 = require("../components/logger");
var tokenTypes;
(function (tokenTypes) {
tokenTypes["UserApiToken"] = "userApiToken";
tokenTypes["TenantApiToken"] = "tenantApiToken";
tokenTypes["UserToken"] = "userToken";
})(tokenTypes = exports.tokenTypes || (exports.tokenTypes = {}));
var types_1 = require("../clients/identity/types");
function withAuthentication(_a) {

@@ -64,15 +59,15 @@ var _this = this;

return function (req, res, next) { return __awaiter(_this, void 0, void 0, function () {
var authorizationHeader, token, user, e_1, _a, statusCode, message;
var authHeader, token, type, user, e_1, _a, statusCode, message;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
authorizationHeader = req.header('authorization');
if (!authorizationHeader) {
authHeader = getAuthHeader(req);
if (!authHeader) {
return [2 /*return*/, res.status(401).send('Unauthenticated')];
}
token = authorizationHeader.replace('Bearer ', '');
token = authHeader.token, type = authHeader.type;
_b.label = 1;
case 1:
_b.trys.push([1, 3, , 4]);
return [4 /*yield*/, clients_1.IdentityClient.getInstance().validateIdentityOnToken(token, { roles: roles, permissions: permissions })];
return [4 /*yield*/, clients_1.IdentityClient.getInstance().validateIdentityOnToken(token, { roles: roles, permissions: permissions }, type)];
case 2:

@@ -92,10 +87,12 @@ user = _b.sent();

};
switch (req.frontegg.user.type) {
case tokenTypes.UserToken:
switch (user.type) {
case types_1.tokenTypes.UserToken:
// The subject of the token (OpenID token) is saved on the req.frontegg.user as well for easier readability
req.frontegg.user.id = user.sub;
break;
case tokenTypes.UserApiToken:
case types_1.tokenTypes.UserApiToken:
req.frontegg.user.id = user.createdByUserId;
break;
case types_1.tokenTypes.UserAccessToken:
req.frontegg.user.id = user.userId;
}

@@ -110,2 +107,13 @@ // And move to the next handler

exports.withAuthentication = withAuthentication;
function getAuthHeader(req) {
var token = req.header('authorization');
if (token) {
return { token: token.replace('Bearer ', ''), type: types_1.AuthHeaderType.JWT };
}
token = req.header('x-api-key');
if (token) {
return { token: token, type: types_1.AuthHeaderType.AccessToken };
}
return null;
}
//# sourceMappingURL=with-authentication.js.map

@@ -0,1 +1,8 @@

# [4.2.0-alpha.3](https://github.com/frontegg/nodejs-sdk/compare/4.2.0-alpha.2...4.2.0-alpha.3) (2023-01-22)
### Features
* **access-tokens:** support access tokens ([#133](https://github.com/frontegg/nodejs-sdk/issues/133)) ([7911b81](https://github.com/frontegg/nodejs-sdk/commit/7911b81ac165a4dc91dbf5ff93e5f86a5464a960))
# [4.2.0-alpha.2](https://github.com/frontegg/nodejs-sdk/compare/4.2.0-alpha.1...4.2.0-alpha.2) (2023-01-22)

@@ -2,0 +9,0 @@

{
"name": "@frontegg/client",
"version": "4.2.0-alpha.2",
"version": "4.2.0-alpha.3",
"description": "Frontegg Javascript Library for backend",

@@ -9,2 +9,3 @@ "main": "dist/index.js",

"build": "rm -rf dist && tsc",
"build:watch": "rm -rf dist && tsc --watch",
"lint": "eslint --ignore-path .eslintignore --ext .js,.ts .",

@@ -28,4 +29,17 @@ "format": "prettier --write \"**/*.+(js|ts|json)\"",

"jsonwebtoken": "^9.0.0",
"node-cache": "^5.1.2",
"winston": "^3.8.2"
},
"peerDependencies": {
"ioredis": "^5.0.0",
"redis": "^4.0.0"
},
"peerDependenciesMeta": {
"ioredis": {
"optional": true
},
"redis": {
"optional": true
}
},
"devDependencies": {

@@ -45,2 +59,4 @@ "@semantic-release/changelog": "^6.0.1",

"express": "^4.18.1",
"ioredis": "^5.2.5",
"ioredis-mock": "^8.2.2",
"jest": "^28.1.3",

@@ -47,0 +63,0 @@ "jest-environment-node": "^26.6.2",

@@ -29,2 +29,3 @@ <br />

### Version 3.0.0 is Deprecated. Please use versions 4.x.x
### If you are upgrading from version 2.x.x skip version 3.0.0 by installing the latest version

@@ -37,3 +38,4 @@

### As of version 3.0.0 and 4.0.0, we will no longer provide proxy middlewares
To see an example implementation of a proxy, head over to our
To see an example implementation, head over to our
<a href="https://github.com/frontegg-samples/nodejs-proxy-sample">sample proxy project</a>

@@ -52,2 +54,3 @@

---
## Usage

@@ -58,2 +61,3 @@

Initialize the frontegg context when initializing your app
```javascript

@@ -63,6 +67,7 @@ const { FronteggContext } = require('@frontegg/client');

FronteggContext.init({
FRONTEGG_CLIENT_ID: '<YOUR_CLIENT_ID>',
FRONTEGG_API_KEY: '<YOUR_API_KEY>',
FRONTEGG_CLIENT_ID: '<YOUR_CLIENT_ID>',
FRONTEGG_API_KEY: '<YOUR_API_KEY>',
});
```
### Middleware

@@ -73,2 +78,3 @@

A simple usage example:
```javascript

@@ -79,9 +85,73 @@ const { withAuthentication } = require('@frontegg/client');

app.use('/protected', withAuthentication(), (req, res) => {
// Authenticated user data will be available on the req.frontegg object
callSomeAction(req.frontegg.user)
res.status(200);
// Authenticated user data will be available on the req.frontegg object
callSomeAction(req.frontegg.user);
res.status(200);
});
```
Head over to the <a href="https://docs.frontegg.com/docs/using-frontegg-sdk">Docs</a> to find more usage examples of the guard.
### Access tokens
When using M2M authentication, access tokens will be cached by the SDK.
By default access tokens will be cached locally, however you can use two other kinds of cache:
- ioredis
- redis
#### Use ioredis as your cache
When initializing your context, pass an access tokens options object with your ioredis parameters
```javascript
const { FronteggContext } = require('@frontegg/client');
const accessTokensOptions = {
cache: {
type: 'ioredis',
options: {
host: 'localhost',
port: 6379,
password: '',
db: 10,
},
},
};
FronteggContext.init(
{
FRONTEGG_CLIENT_ID: '<YOUR_CLIENT_ID>',
FRONTEGG_API_KEY: '<YOUR_API_KEY>',
},
{
accessTokensOptions,
},
);
```
#### Use redis as your cache
When initializing your context, pass an access tokens options object with your redis parameters
```javascript
const { FronteggContext } = require('@frontegg/client');
const accessTokensOptions = {
cache: {
type: 'redis',
options: {
url: 'redis[s]://[[username][:password]@][host][:port][/db-number]',
},
},
};
FronteggContext.init(
{
FRONTEGG_CLIENT_ID: '<YOUR_CLIENT_ID>',
FRONTEGG_API_KEY: '<YOUR_API_KEY>',
},
{
accessTokensOptions,
},
);
```
### Clients

@@ -97,3 +167,3 @@

const { AuditsClient } = require('@frontegg/client');
const audits = new AuditsClient()
const audits = new AuditsClient();

@@ -108,9 +178,9 @@ // initialize the module

await audits.sendAudit({
tenantId: 'my-tenant-id',
time: Date(),
user: 'info@frontegg.com',
resource: 'Portal',
action: 'Login',
severity: 'Medium',
ip: '1.2.3.4'
tenantId: 'my-tenant-id',
time: Date(),
user: 'info@frontegg.com',
resource: 'Portal',
action: 'Login',
severity: 'Medium',
ip: '1.2.3.4',
});

@@ -123,8 +193,8 @@ ```

const { data, total } = await audits.getAudits({
tenantId: 'my-tenant-id',
filter: 'any-text-filter',
sortBy: 'my-sort-field',
sortDirection: 'asc | desc',
offset: 0, // Offset for starting the page
count: 50 // Number of desired items
tenantId: 'my-tenant-id',
filter: 'any-text-filter',
sortBy: 'my-sort-field',
sortDirection: 'asc | desc',
offset: 0, // Offset for starting the page
count: 50, // Number of desired items
});

@@ -141,3 +211,3 @@ ```

const authenticator = new FronteggAuthenticator();
await authenticator.init('<YOUR_CLIENT_ID>', '<YOUR_API_KEY>')
await authenticator.init('<YOUR_CLIENT_ID>', '<YOUR_API_KEY>');

@@ -147,15 +217,21 @@ // You can optionally set the base url from the HttpClient

await httpClient.post('identity/resources/auth/v1/user', {
await httpClient.post(
'identity/resources/auth/v1/user',
{
email: 'johndoe@acme.com',
password: 'my-super-duper-password'
}, {
password: 'my-super-duper-password',
},
{
// When providing vendor-host, it will replace(<...>) https://<api>.frontegg.com with vendor host
'frontegg-vendor-host': 'acme.frontegg'
});
'frontegg-vendor-host': 'acme.frontegg',
},
);
```
### Validating JWT manually
If required you can implement your own middleware which will validate the Frontegg JWT using the `IdentityClient`
First, let's import the `IdentityClient`
```javascript

@@ -166,2 +242,3 @@ const { IdentityClient } = require('@frontegg/client');

Then, initialize the client
```javascript

@@ -172,17 +249,18 @@ const identityClient = new IdentityClient({ FRONTEGG_CLIENT_ID: 'your-client-id', FRONTEGG_API_KEY: 'your-api-key' });

And use this client to validate
```javascript
app.use('/protected', (req, res, next) => {
const token = req.headers.authorization;
let user: IUser;
try {
user = identityClient.validateIdentityOnToken(token, { roles: ['admin'], permissions: ['read'] });
req.user = user;
} catch (e) {
console.error(e);
next(e);
return;
}
next();
const token = req.headers.authorization;
let user: IUser;
try {
user = identityClient.validateIdentityOnToken(token, { roles: ['admin'], permissions: ['read'] });
req.user = user;
} catch (e) {
console.error(e);
next(e);
return;
}
next();
});
```

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

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc