New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@envelop/generic-auth

Package Overview
Dependencies
Maintainers
0
Versions
1360
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@envelop/generic-auth - npm Package Compare versions

Comparing version 8.0.0-alpha-20240812113941-0c30c454 to 8.0.0-alpha-20240812120620-e6a7b402

108

cjs/index.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useGenericAuth = exports.defaultProtectSingleValidateFn = exports.defaultProtectAllValidateFn = exports.createUnauthenticatedError = exports.SKIP_AUTH_DIRECTIVE_SDL = exports.DIRECTIVE_SDL = void 0;
const types_1 = require("util/types");
exports.useGenericAuth = exports.defaultExtractScopes = exports.defaultProtectSingleValidateFn = exports.defaultProtectAllValidateFn = exports.createUnauthenticatedError = exports.POLICY_DIRECTIVE_SDL = exports.REQUIRES_SCOPES_DIRECTIVE_SDL = exports.SKIP_AUTH_DIRECTIVE_SDL = exports.DIRECTIVE_SDL = void 0;
const graphql_1 = require("graphql");

@@ -14,4 +13,10 @@ const extended_validation_1 = require("@envelop/extended-validation");

`;
exports.REQUIRES_SCOPES_DIRECTIVE_SDL = `
directive @requiresScopes(scopes: [[String!]!]!) on FIELD_DEFINITION
`;
exports.POLICY_DIRECTIVE_SDL = `
directive @policy(policies: [String!]!) on FIELD_DEFINITION
`;
function createUnauthenticatedError(params) {
return (0, utils_1.createGraphQLError)('Unauthorized field or type', {
return (0, utils_1.createGraphQLError)(params?.message ?? 'Unauthorized field or type', {
nodes: params?.fieldNode ? [params.fieldNode] : undefined,

@@ -35,4 +40,41 @@ path: params?.path,

}
return validateScopes(params);
}
exports.defaultProtectAllValidateFn = defaultProtectAllValidateFn;
function areRolesValid(requiredRoles, userRoles) {
for (const roles of requiredRoles) {
if (roles.every(role => userRoles.includes(role))) {
return true;
}
}
return false;
}
function validateScopes(params) {
if (params.typeScopes && !areRolesValid(params.typeScopes, params.userScopes)) {
return createUnauthenticatedError({
fieldNode: params.fieldNode,
path: params.path,
});
}
if (params.fieldScopes && !areRolesValid(params.fieldScopes, params.userScopes)) {
return createUnauthenticatedError({
fieldNode: params.fieldNode,
path: params.path,
});
}
}
function validatePolicies(params) {
if (params.typePolicies && !areRolesValid(params.typePolicies, params.userPolicies)) {
return createUnauthenticatedError({
fieldNode: params.fieldNode,
path: params.path,
});
}
if (params.fieldPolicies && !areRolesValid(params.fieldPolicies, params.userPolicies)) {
return createUnauthenticatedError({
fieldNode: params.fieldNode,
path: params.path,
});
}
}
function defaultProtectSingleValidateFn(params) {

@@ -45,8 +87,27 @@ if (params.user == null && (params.fieldAuthArgs || params.typeAuthArgs)) {

}
const error = validateScopes(params);
if (error) {
return error;
}
return validatePolicies(params);
}
exports.defaultProtectSingleValidateFn = defaultProtectSingleValidateFn;
function defaultExtractScopes(user) {
if (user != null && typeof user === 'object' && 'scope' in user) {
if (typeof user.scope === 'string') {
return user.scope.split(' ');
}
if (Array.isArray(user.scope)) {
return user.scope;
}
}
return [];
}
exports.defaultExtractScopes = defaultExtractScopes;
const useGenericAuth = (options) => {
const contextFieldName = options.contextFieldName || 'currentUser';
if (options.mode === 'protect-all' || options.mode === 'protect-granular') {
const directiveOrExtensionFieldName = options.authDirectiveName ?? (options.mode === 'protect-all' ? 'skipAuth' : 'authenticated');
const authDirectiveName = options.authDirectiveName ?? (options.mode === 'protect-all' ? 'skipAuth' : 'authenticated');
const requiresScopesDirectiveName = options.scopesDirectiveName ?? 'requiresScopes';
const policyDirectiveName = options.policyDirectiveName ?? 'policy';
const validateUser = options.validateUser ??

@@ -56,3 +117,5 @@ (options.mode === 'protect-all'

: defaultProtectSingleValidateFn);
const extractScopes = options.extractScopes ?? defaultExtractScopes;
const rejectUnauthenticated = 'rejectUnauthenticated' in options ? options.rejectUnauthenticated !== false : true;
const policiesByContext = new WeakMap();
return {

@@ -85,5 +148,11 @@ onPluginInit({ addPlugin }) {

const typeDirectives = parentType && (0, utils_1.getDirectiveExtensions)(parentType, schema);
const typeAuthArgs = typeDirectives[directiveOrExtensionFieldName]?.[0];
const typeAuthArgs = typeDirectives[authDirectiveName]?.[0];
const typeScopes = typeDirectives[requiresScopesDirectiveName]?.[0]?.scopes;
const typePolicies = typeDirectives[policyDirectiveName]?.[0]?.policies;
const fieldDirectives = (0, utils_1.getDirectiveExtensions)(field, schema);
const fieldAuthArgs = fieldDirectives[directiveOrExtensionFieldName]?.[0];
const fieldAuthArgs = fieldDirectives[authDirectiveName]?.[0];
const fieldScopes = fieldDirectives[requiresScopesDirectiveName]?.[0]?.scopes;
const fieldPolicies = fieldDirectives[policyDirectiveName]?.[0]?.policies;
const userScopes = extractScopes(user);
const policies = policiesByContext.get(context) ?? [];
const resolvePath = [];

@@ -101,2 +170,4 @@ let curr = args.document;

parentType,
typeScopes,
typePolicies,
typeAuthArgs,

@@ -108,3 +179,7 @@ typeDirectives,

fieldAuthArgs,
fieldScopes,
fieldPolicies,
userScopes,
path: resolvePath,
userPolicies: policies,
});

@@ -156,20 +231,13 @@ };

},
onContextBuilding({ context, extendContext }) {
const user$ = options.resolveUserFn(context);
if ((0, types_1.isPromise)(user$)) {
return user$.then(user => {
// @ts-expect-error - Fix this
if (context[contextFieldName] !== user) {
// @ts-expect-error - Fix this
extendContext({
[contextFieldName]: user,
});
}
});
async onContextBuilding({ context, extendContext }) {
const user = await options.resolveUserFn(context);
if (options.extractPolicies) {
const policies = await options.extractPolicies(user, context);
policiesByContext.set(context, policies);
}
// @ts-expect-error - Fix this
if (context[contextFieldName] !== user$) {
if (context[contextFieldName] !== user) {
// @ts-expect-error - Fix this
extendContext({
[contextFieldName]: user$,
[contextFieldName]: user,
});

@@ -176,0 +244,0 @@ }

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

import { isPromise } from 'util/types';
import { getNamedType, isInterfaceType, isIntrospectionType, isObjectType, isUnionType, } from 'graphql';

@@ -11,4 +10,10 @@ import { useExtendedValidation } from '@envelop/extended-validation';

`;
export const REQUIRES_SCOPES_DIRECTIVE_SDL = /* GraphQL */ `
directive @requiresScopes(scopes: [[String!]!]!) on FIELD_DEFINITION
`;
export const POLICY_DIRECTIVE_SDL = /* GraphQL */ `
directive @policy(policies: [String!]!) on FIELD_DEFINITION
`;
export function createUnauthenticatedError(params) {
return createGraphQLError('Unauthorized field or type', {
return createGraphQLError(params?.message ?? 'Unauthorized field or type', {
nodes: params?.fieldNode ? [params.fieldNode] : undefined,

@@ -31,3 +36,40 @@ path: params?.path,

}
return validateScopes(params);
}
function areRolesValid(requiredRoles, userRoles) {
for (const roles of requiredRoles) {
if (roles.every(role => userRoles.includes(role))) {
return true;
}
}
return false;
}
function validateScopes(params) {
if (params.typeScopes && !areRolesValid(params.typeScopes, params.userScopes)) {
return createUnauthenticatedError({
fieldNode: params.fieldNode,
path: params.path,
});
}
if (params.fieldScopes && !areRolesValid(params.fieldScopes, params.userScopes)) {
return createUnauthenticatedError({
fieldNode: params.fieldNode,
path: params.path,
});
}
}
function validatePolicies(params) {
if (params.typePolicies && !areRolesValid(params.typePolicies, params.userPolicies)) {
return createUnauthenticatedError({
fieldNode: params.fieldNode,
path: params.path,
});
}
if (params.fieldPolicies && !areRolesValid(params.fieldPolicies, params.userPolicies)) {
return createUnauthenticatedError({
fieldNode: params.fieldNode,
path: params.path,
});
}
}
export function defaultProtectSingleValidateFn(params) {

@@ -40,7 +82,25 @@ if (params.user == null && (params.fieldAuthArgs || params.typeAuthArgs)) {

}
const error = validateScopes(params);
if (error) {
return error;
}
return validatePolicies(params);
}
export function defaultExtractScopes(user) {
if (user != null && typeof user === 'object' && 'scope' in user) {
if (typeof user.scope === 'string') {
return user.scope.split(' ');
}
if (Array.isArray(user.scope)) {
return user.scope;
}
}
return [];
}
export const useGenericAuth = (options) => {
const contextFieldName = options.contextFieldName || 'currentUser';
if (options.mode === 'protect-all' || options.mode === 'protect-granular') {
const directiveOrExtensionFieldName = options.authDirectiveName ?? (options.mode === 'protect-all' ? 'skipAuth' : 'authenticated');
const authDirectiveName = options.authDirectiveName ?? (options.mode === 'protect-all' ? 'skipAuth' : 'authenticated');
const requiresScopesDirectiveName = options.scopesDirectiveName ?? 'requiresScopes';
const policyDirectiveName = options.policyDirectiveName ?? 'policy';
const validateUser = options.validateUser ??

@@ -50,3 +110,5 @@ (options.mode === 'protect-all'

: defaultProtectSingleValidateFn);
const extractScopes = options.extractScopes ?? defaultExtractScopes;
const rejectUnauthenticated = 'rejectUnauthenticated' in options ? options.rejectUnauthenticated !== false : true;
const policiesByContext = new WeakMap();
return {

@@ -79,5 +141,11 @@ onPluginInit({ addPlugin }) {

const typeDirectives = parentType && getDirectiveExtensions(parentType, schema);
const typeAuthArgs = typeDirectives[directiveOrExtensionFieldName]?.[0];
const typeAuthArgs = typeDirectives[authDirectiveName]?.[0];
const typeScopes = typeDirectives[requiresScopesDirectiveName]?.[0]?.scopes;
const typePolicies = typeDirectives[policyDirectiveName]?.[0]?.policies;
const fieldDirectives = getDirectiveExtensions(field, schema);
const fieldAuthArgs = fieldDirectives[directiveOrExtensionFieldName]?.[0];
const fieldAuthArgs = fieldDirectives[authDirectiveName]?.[0];
const fieldScopes = fieldDirectives[requiresScopesDirectiveName]?.[0]?.scopes;
const fieldPolicies = fieldDirectives[policyDirectiveName]?.[0]?.policies;
const userScopes = extractScopes(user);
const policies = policiesByContext.get(context) ?? [];
const resolvePath = [];

@@ -95,2 +163,4 @@ let curr = args.document;

parentType,
typeScopes,
typePolicies,
typeAuthArgs,

@@ -102,3 +172,7 @@ typeDirectives,

fieldAuthArgs,
fieldScopes,
fieldPolicies,
userScopes,
path: resolvePath,
userPolicies: policies,
});

@@ -150,20 +224,13 @@ };

},
onContextBuilding({ context, extendContext }) {
const user$ = options.resolveUserFn(context);
if (isPromise(user$)) {
return user$.then(user => {
// @ts-expect-error - Fix this
if (context[contextFieldName] !== user) {
// @ts-expect-error - Fix this
extendContext({
[contextFieldName]: user,
});
}
});
async onContextBuilding({ context, extendContext }) {
const user = await options.resolveUserFn(context);
if (options.extractPolicies) {
const policies = await options.extractPolicies(user, context);
policiesByContext.set(context, policies);
}
// @ts-expect-error - Fix this
if (context[contextFieldName] !== user$) {
if (context[contextFieldName] !== user) {
// @ts-expect-error - Fix this
extendContext({
[contextFieldName]: user$,
[contextFieldName]: user,
});

@@ -170,0 +237,0 @@ }

4

package.json
{
"name": "@envelop/generic-auth",
"version": "8.0.0-alpha-20240812113941-0c30c454",
"version": "8.0.0-alpha-20240812120620-e6a7b402",
"sideEffects": false,

@@ -10,3 +10,3 @@ "peerDependencies": {

"dependencies": {
"@envelop/extended-validation": "4.1.0-alpha-20240812113941-0c30c454",
"@envelop/extended-validation": "4.1.0-alpha-20240812120620-e6a7b402",
"@graphql-tools/utils": "^10.5.1",

@@ -13,0 +13,0 @@ "tslib": "^2.5.0"

@@ -16,2 +16,6 @@ import { ExecutionArgs, FieldNode, GraphQLError, GraphQLField, GraphQLInterfaceType, GraphQLObjectType } from 'graphql';

typeDirectives?: ReturnType<typeof getDirectiveExtensions>;
/** Scopes that type requires */
typeScopes?: string[][];
/** Policies that type requires */
typePolicies?: string[][];
/** The object field */

@@ -23,2 +27,10 @@ field: GraphQLField<any, any>;

fieldDirectives?: ReturnType<typeof getDirectiveExtensions>;
/** Scopes that field requires */
fieldScopes?: string[][];
/** Policies that field requires */
fieldPolicies?: string[][];
/** Extracted scopes from the user object */
userScopes: string[];
/** Policies for the user */
userPolicies: string[];
/** The args passed to the execution function (including operation context and variables) **/

@@ -32,2 +44,4 @@ executionArgs: ExecutionArgs;

export declare const SKIP_AUTH_DIRECTIVE_SDL = "\n directive @skipAuth on FIELD_DEFINITION\n";
export declare const REQUIRES_SCOPES_DIRECTIVE_SDL = "\n directive @requiresScopes(scopes: [[String!]!]!) on FIELD_DEFINITION\n";
export declare const POLICY_DIRECTIVE_SDL = "\n directive @policy(policies: [String!]!) on FIELD_DEFINITION\n";
export type GenericAuthPluginOptions<UserType extends {} = {}, ContextType = DefaultContext, CurrentUserKey extends string = 'currentUser'> = {

@@ -46,2 +60,24 @@ /**

contextFieldName?: CurrentUserKey;
/**
* Overrides the default directive name for marking a field that requires specific scopes.
*
* @default requiresScopes
*/
scopesDirectiveName?: 'requiresScopes';
/**
* Extracts the scopes from the user object.
*
* @default defaultExtractScopes
*/
extractScopes?(user: UserType): string[];
/**
* Overrides the default directive name for @policy directive
*
* @default policy
*/
policyDirectiveName?: string;
/**
* Extracts the policies for the user object.
*/
extractPolicies?(user: UserType, context: ContextType): PromiseOrValue<string[]>;
} & ({

@@ -102,4 +138,5 @@ /**

export declare function defaultProtectSingleValidateFn<UserType>(params: ValidateUserFnParams<UserType>): void | GraphQLError;
export declare function defaultExtractScopes<UserType>(user: UserType): string[];
export declare const useGenericAuth: <UserType extends {} = {}, ContextType extends Record<any, any> = DefaultContext, CurrentUserKey extends string = "currentUser">(options: GenericAuthPluginOptions<UserType, ContextType, CurrentUserKey>) => Plugin<{
validateUser: ValidateUserFn<UserType>;
} & Record<CurrentUserKey, UserType>>;

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