@envelop/generic-auth 7.0.0 → 8.0.0-alpha-20240806125641-9b9885ba

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,8 +4,8 @@ This plugin allows you to implement custom authentication flow by providing a cu
4
4
  based on the original HTTP request. The resolved user is injected into the GraphQL execution
5
5
  `context`, and you can use it in your resolvers to fetch the current user.
6
6
 
7
- > The plugin also comes with an optional `@auth` directive that can be added to your GraphQL schema
8
- > and helps you to protect your GraphQL schema in a declarative way.
7
+ > The plugin also comes with an optional `@authenticated` directive that can be added to your
8
+ > GraphQL schema and helps you to protect your GraphQL schema in a declarative way.
9
9
 
10
10
  There are several possible flows for using this plugin (see below for setup examples):
11
11
 
@@ -15,8 +15,8 @@ There are several possible flows for using this plugin (see below for setup exam
15
15
  - **Option #2 - Manual Validation**: the plugin will just resolve the user and injects it into the
16
16
  `context` without validating access to schema field.
17
17
  - **Option #3 - Granular field access by using schema field directives or field extensions**: Look
18
- for an `@auth` directive or `auth` extension field and automatically protect those specific
19
- GraphQL fields.
18
+ for an `@authenticated` directive or `authenticated` extension field and automatically protect
19
+ those specific GraphQL fields.
20
20
 
21
21
  ## Getting Started
22
22
 
@@ -70,7 +70,7 @@ const validateUser: ValidateUserFn<UserType> = params => {
70
70
  // This method is being triggered in different flows, based on the mode you chose to implement.
71
71
 
72
72
  // If you are using the `protect-auth-directive` mode, you'll also get 2 additional parameters: the resolver parameters as object and the DirectiveNode of the auth directive.
73
- // In `protect-auth-directive` mode, this function will always get called and you can use these parameters to check if the field has the `@auth` or `@skipAuth` directive
73
+ // In `protect-auth-directive` mode, this function will always get called and you can use these parameters to check if the field has the `@authenticated` or `@skipAuth` directive
74
74
 
75
75
  if (!user) {
76
76
  return new Error(`Unauthenticated!`)
@@ -175,7 +175,7 @@ type UserType = {
175
175
  const resolveUserFn: ResolveUserFn<UserType> = async context => {
176
176
  /* ... */
177
177
  }
178
- const validateUser: ValidateUserFn<UserType> = async params => {
178
+ const validateUser: ValidateUserFn<UserType> = params => {
179
179
  /* ... */
180
180
  }
181
181
 
@@ -198,7 +198,11 @@ Then, in your resolvers, you can execute the check method based on your needs:
198
198
  const resolvers = {
199
199
  Query: {
200
200
  me: async (root, args, context) => {
201
- await context.validateUser()
201
+ const validationError = context.validateUser()
202
+ if (validationError) {
203
+ throw validationError
204
+ }
205
+
202
206
  const currentUser = context.currentUser
203
207
 
204
208
  return currentUser
@@ -209,8 +213,8 @@ const resolvers = {
209
213
 
210
214
  #### Option #3 - `protect-granular`
211
215
 
212
- This mode is similar to option #2, but it uses the `@auth` SDL directive or `auth` field extension
213
- for protecting specific GraphQL fields.
216
+ This mode is similar to option #2, but it uses the `@authenticated` SDL directive or `auth` field
217
+ extension for protecting specific GraphQL fields.
214
218
 
215
219
  ```ts
216
220
  import { execute, parse, specifiedRules, subscribe, validate } from 'graphql'
@@ -243,15 +247,15 @@ const getEnveloped = envelop({
243
247
  ##### Protect a field using a field `directive`
244
248
 
245
249
  > By default, we assume that you have the GraphQL directive definition as part of your GraphQL
246
- > schema (`directive @auth on FIELD_DEFINITION`).
250
+ > schema (`directive @authenticated on FIELD_DEFINITION`).
247
251
 
248
- Then, in your GraphQL schema SDL, you can add `@auth` directive to your fields, and the
252
+ Then, in your GraphQL schema SDL, you can add `@authenticated` directive to your fields, and the
249
253
  `validateUser` will get called only while resolving that specific field:
250
254
 
251
255
  ```graphql
252
256
  type Query {
253
- me: User! @auth
254
- protectedField: String @auth
257
+ me: User! @authenticated
258
+ protectedField: String @authenticated
255
259
  # publicField: String
256
260
  }
257
261
  ```
@@ -273,7 +277,7 @@ const GraphQLQueryType = new GraphQLObjectType({
273
277
  type: GraphQLInt,
274
278
  resolve: () => 1,
275
279
  extensions: {
276
- auth: true
280
+ authenticated: true
277
281
  }
278
282
  }
279
283
  }
@@ -292,7 +296,7 @@ the `protect-all` and `protect-granular` mode:
292
296
  import { GraphQLError } from 'graphql'
293
297
  import { ValidateUserFn } from '@envelop/generic-auth'
294
298
 
295
- const validateUser: ValidateUserFn<UserType> = async ({ user }) => {
299
+ const validateUser: ValidateUserFn<UserType> = ({ user }) => {
296
300
  // Now you can use the 3rd parameter to implement custom logic for user validation, with access
297
301
  // to the resolver data and information.
298
302
 
@@ -304,8 +308,8 @@ const validateUser: ValidateUserFn<UserType> = async ({ user }) => {
304
308
 
305
309
  ##### With a custom directive with arguments
306
310
 
307
- It is possible to add custom parameters to your `@auth` directive. Here's an example for adding
308
- role-aware authentication:
311
+ It is possible to add custom parameters to your `@authenticated` directive. Here's an example for
312
+ adding role-aware authentication:
309
313
 
310
314
  ```graphql
311
315
  enum Role {
@@ -313,7 +317,7 @@ enum Role {
313
317
  MEMBER
314
318
  }
315
319
 
316
- directive @auth(role: Role!) on FIELD_DEFINITION
320
+ directive @authenticated(role: Role!) on FIELD_DEFINITION
317
321
  ```
318
322
 
319
323
  Then, you use the `directiveNode` parameter to check the arguments:
@@ -321,7 +325,7 @@ Then, you use the `directiveNode` parameter to check the arguments:
321
325
  ```ts
322
326
  import { ValidateUserFn } from '@envelop/generic-auth'
323
327
 
324
- const validateUser: ValidateUserFn<UserType> = async ({ user, fieldAuthDirectiveNode }) => {
328
+ const validateUser: ValidateUserFn<UserType> = ({ user, fieldAuthDirectiveNode }) => {
325
329
  // Now you can use the fieldAuthDirectiveNode parameter to implement custom logic for user validation, with access
326
330
  // to the resolver auth directive arguments.
327
331
 
@@ -367,7 +371,7 @@ const resolvers = {
367
371
  user: {
368
372
  me: (_, __, { currentUser }) => currentUser,
369
373
  extensions: {
370
- auth: {
374
+ authenticated: {
371
375
  role: 'USER'
372
376
  }
373
377
  }
@@ -385,11 +389,7 @@ validation.
385
389
  ```ts
386
390
  import { ValidateUserFn } from '@envelop/generic-auth'
387
391
 
388
- const validateUser: ValidateUserFn<UserType> = async ({
389
- user,
390
- executionArgs,
391
- fieldAuthExtension
392
- }) => {
392
+ const validateUser: ValidateUserFn<UserType> = ({ user, executionArgs, fieldAuthExtension }) => {
393
393
  if (!user) {
394
394
  return new Error(`Unauthenticated!`)
395
395
  }
@@ -397,7 +397,7 @@ const validateUser: ValidateUserFn<UserType> = async ({
397
397
  // You have access to the object define in the resolver tree, allowing to define any custom logic you want.
398
398
  const validate = fieldAuthExtension?.validate
399
399
  if (validate) {
400
- await validate({
400
+ return validate({
401
401
  user,
402
402
  variables: executionArgs.variableValues,
403
403
  context: executionArgs.contextValue
@@ -410,7 +410,7 @@ const resolvers = {
410
410
  user: {
411
411
  resolve: (_, { userId }) => getUser(userId),
412
412
  extensions: {
413
- auth: {
413
+ authenticated: {
414
414
  validate: ({ user, variables, context }) => {
415
415
  // We can now have access to the operation and variables to decide if the user can execute the query
416
416
  if (user.id !== variables.userId) {
package/cjs/index.js CHANGED
@@ -1,33 +1,43 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useGenericAuth = exports.defaultProtectSingleValidateFn = exports.defaultProtectAllValidateFn = exports.SKIP_AUTH_DIRECTIVE_SDL = exports.DIRECTIVE_SDL = exports.UnauthenticatedError = void 0;
3
+ exports.useGenericAuth = exports.defaultProtectSingleValidateFn = exports.defaultProtectAllValidateFn = exports.createUnauthenticatedError = exports.SKIP_AUTH_DIRECTIVE_SDL = exports.DIRECTIVE_SDL = void 0;
4
4
  const graphql_1 = require("graphql");
5
5
  const extended_validation_1 = require("@envelop/extended-validation");
6
6
  const utils_1 = require("@graphql-tools/utils");
7
- class UnauthenticatedError extends graphql_1.GraphQLError {
8
- }
9
- exports.UnauthenticatedError = UnauthenticatedError;
10
7
  exports.DIRECTIVE_SDL = `
11
- directive @auth on FIELD_DEFINITION
8
+ directive @authenticated on FIELD_DEFINITION
12
9
  `;
13
10
  exports.SKIP_AUTH_DIRECTIVE_SDL = `
14
11
  directive @skipAuth on FIELD_DEFINITION
15
12
  `;
13
+ function createUnauthenticatedError(params) {
14
+ return (0, utils_1.createGraphQLError)('Unauthorized field or type', {
15
+ nodes: params?.fieldNode ? [params.fieldNode] : undefined,
16
+ path: params?.path,
17
+ extensions: {
18
+ code: 'UNAUTHORIZED_FIELD_OR_TYPE',
19
+ http: {
20
+ status: params?.statusCode ?? 401,
21
+ },
22
+ },
23
+ });
24
+ }
25
+ exports.createUnauthenticatedError = createUnauthenticatedError;
16
26
  function defaultProtectAllValidateFn(params) {
17
27
  if (params.user == null && !params.fieldAuthDirectiveNode && !params.fieldAuthExtension) {
18
- const schemaCoordinate = `${params.objectType.name}.${params.fieldNode.name.value}`;
19
- return new UnauthenticatedError(`Accessing '${schemaCoordinate}' requires authentication.`, [
20
- params.fieldNode,
21
- ]);
28
+ return createUnauthenticatedError({
29
+ fieldNode: params.fieldNode,
30
+ path: params.path,
31
+ });
22
32
  }
23
33
  }
24
34
  exports.defaultProtectAllValidateFn = defaultProtectAllValidateFn;
25
35
  function defaultProtectSingleValidateFn(params) {
26
36
  if (params.user == null && (params.fieldAuthDirectiveNode || params.fieldAuthExtension)) {
27
- const schemaCoordinate = `${params.objectType.name}.${params.fieldNode.name.value}`;
28
- return new UnauthenticatedError(`Accessing '${schemaCoordinate}' requires authentication.`, [
29
- params.fieldNode,
30
- ]);
37
+ return createUnauthenticatedError({
38
+ fieldNode: params.fieldNode,
39
+ path: params.path,
40
+ });
31
41
  }
32
42
  }
33
43
  exports.defaultProtectSingleValidateFn = defaultProtectSingleValidateFn;
@@ -35,7 +45,7 @@ const useGenericAuth = (options) => {
35
45
  const contextFieldName = options.contextFieldName || 'currentUser';
36
46
  if (options.mode === 'protect-all' || options.mode === 'protect-granular') {
37
47
  const directiveOrExtensionFieldName = options.directiveOrExtensionFieldName ??
38
- (options.mode === 'protect-all' ? 'skipAuth' : 'auth');
48
+ (options.mode === 'protect-all' ? 'skipAuth' : 'authenticated');
39
49
  const validateUser = options.validateUser ??
40
50
  (options.mode === 'protect-all'
41
51
  ? defaultProtectAllValidateFn
@@ -46,51 +56,101 @@ const useGenericAuth = (options) => {
46
56
  fieldAuthDirectiveNode: input.astNode?.directives?.find(directive => directive.name.value === directiveOrExtensionFieldName),
47
57
  };
48
58
  };
59
+ const rejectUnauthenticated = 'rejectUnauthenticated' in options ? options.rejectUnauthenticated !== false : true;
49
60
  return {
50
61
  onPluginInit({ addPlugin }) {
51
62
  addPlugin((0, extended_validation_1.useExtendedValidation)({
63
+ rejectOnErrors: rejectUnauthenticated,
52
64
  rules: [
53
65
  function AuthorizationExtendedValidationRule(context, args) {
66
+ const operations = {};
67
+ const fragments = {};
68
+ for (const definition of args.document.definitions) {
69
+ if (definition.kind === 'OperationDefinition') {
70
+ operations[definition.name?.value ?? args.operationName ?? 'Anonymous'] =
71
+ definition;
72
+ }
73
+ else if (definition.kind === 'FragmentDefinition') {
74
+ fragments[definition.name.value] = definition;
75
+ }
76
+ }
54
77
  const user = args.contextValue[contextFieldName];
55
- const handleField = (fieldNode, objectType) => {
78
+ const handleField = ({ node: fieldNode, path, }, objectType) => {
56
79
  const field = objectType.getFields()[fieldNode.name.value];
57
80
  if (field == null) {
58
81
  // field is null/undefined if this is an introspection field
59
82
  return;
60
83
  }
61
84
  const { fieldAuthExtension, fieldAuthDirectiveNode } = extractAuthMeta(field);
62
- const error = validateUser({
85
+ const resolvePath = [];
86
+ let curr = args.document;
87
+ for (const pathItem of path) {
88
+ curr = curr[pathItem];
89
+ if (curr?.kind === 'Field') {
90
+ resolvePath.push(curr.name.value);
91
+ }
92
+ }
93
+ return validateUser({
63
94
  user,
64
95
  fieldNode,
65
96
  objectType,
66
97
  fieldAuthDirectiveNode,
67
98
  fieldAuthExtension,
68
99
  executionArgs: args,
100
+ field,
101
+ path: resolvePath,
69
102
  });
70
- if (error) {
71
- context.reportError(error);
72
- }
73
103
  };
74
104
  return {
75
- Field(node) {
105
+ Field(node, key, parent, path, ancestors) {
76
106
  if (!(0, utils_1.shouldIncludeNode)(args.variableValues, node)) {
77
107
  return;
78
108
  }
79
109
  const fieldType = (0, graphql_1.getNamedType)(context.getParentType());
80
110
  if ((0, graphql_1.isIntrospectionType)(fieldType)) {
81
- return false;
111
+ return node;
82
112
  }
83
113
  if ((0, graphql_1.isObjectType)(fieldType)) {
84
- handleField(node, fieldType);
114
+ const error = handleField({
115
+ node,
116
+ key,
117
+ parent,
118
+ path,
119
+ ancestors,
120
+ }, fieldType);
121
+ if (error) {
122
+ context.reportError(error);
123
+ return null;
124
+ }
85
125
  }
86
126
  else if ((0, graphql_1.isUnionType)(fieldType)) {
87
127
  for (const objectType of fieldType.getTypes()) {
88
- handleField(node, objectType);
128
+ const error = handleField({
129
+ node,
130
+ key,
131
+ parent,
132
+ path,
133
+ ancestors,
134
+ }, objectType);
135
+ if (error) {
136
+ context.reportError(error);
137
+ return null;
138
+ }
89
139
  }
90
140
  }
91
141
  else if ((0, graphql_1.isInterfaceType)(fieldType)) {
92
142
  for (const objectType of args.schema.getImplementations(fieldType).objects) {
93
- handleField(node, objectType);
143
+ const error = handleField({
144
+ node,
145
+ key,
146
+ parent,
147
+ path,
148
+ ancestors,
149
+ }, objectType);
150
+ if (error) {
151
+ context.reportError(error);
152
+ return null;
153
+ }
94
154
  }
95
155
  }
96
156
  return undefined;
package/esm/index.js CHANGED
@@ -1,35 +1,45 @@
1
- import { getNamedType, GraphQLError, isInterfaceType, isIntrospectionType, isObjectType, isUnionType, } from 'graphql';
1
+ import { getNamedType, isInterfaceType, isIntrospectionType, isObjectType, isUnionType, } from 'graphql';
2
2
  import { useExtendedValidation } from '@envelop/extended-validation';
3
- import { shouldIncludeNode } from '@graphql-tools/utils';
4
- export class UnauthenticatedError extends GraphQLError {
5
- }
3
+ import { createGraphQLError, shouldIncludeNode } from '@graphql-tools/utils';
6
4
  export const DIRECTIVE_SDL = /* GraphQL */ `
7
- directive @auth on FIELD_DEFINITION
5
+ directive @authenticated on FIELD_DEFINITION
8
6
  `;
9
7
  export const SKIP_AUTH_DIRECTIVE_SDL = /* GraphQL */ `
10
8
  directive @skipAuth on FIELD_DEFINITION
11
9
  `;
10
+ export function createUnauthenticatedError(params) {
11
+ return createGraphQLError('Unauthorized field or type', {
12
+ nodes: params?.fieldNode ? [params.fieldNode] : undefined,
13
+ path: params?.path,
14
+ extensions: {
15
+ code: 'UNAUTHORIZED_FIELD_OR_TYPE',
16
+ http: {
17
+ status: params?.statusCode ?? 401,
18
+ },
19
+ },
20
+ });
21
+ }
12
22
  export function defaultProtectAllValidateFn(params) {
13
23
  if (params.user == null && !params.fieldAuthDirectiveNode && !params.fieldAuthExtension) {
14
- const schemaCoordinate = `${params.objectType.name}.${params.fieldNode.name.value}`;
15
- return new UnauthenticatedError(`Accessing '${schemaCoordinate}' requires authentication.`, [
16
- params.fieldNode,
17
- ]);
24
+ return createUnauthenticatedError({
25
+ fieldNode: params.fieldNode,
26
+ path: params.path,
27
+ });
18
28
  }
19
29
  }
20
30
  export function defaultProtectSingleValidateFn(params) {
21
31
  if (params.user == null && (params.fieldAuthDirectiveNode || params.fieldAuthExtension)) {
22
- const schemaCoordinate = `${params.objectType.name}.${params.fieldNode.name.value}`;
23
- return new UnauthenticatedError(`Accessing '${schemaCoordinate}' requires authentication.`, [
24
- params.fieldNode,
25
- ]);
32
+ return createUnauthenticatedError({
33
+ fieldNode: params.fieldNode,
34
+ path: params.path,
35
+ });
26
36
  }
27
37
  }
28
38
  export const useGenericAuth = (options) => {
29
39
  const contextFieldName = options.contextFieldName || 'currentUser';
30
40
  if (options.mode === 'protect-all' || options.mode === 'protect-granular') {
31
41
  const directiveOrExtensionFieldName = options.directiveOrExtensionFieldName ??
32
- (options.mode === 'protect-all' ? 'skipAuth' : 'auth');
42
+ (options.mode === 'protect-all' ? 'skipAuth' : 'authenticated');
33
43
  const validateUser = options.validateUser ??
34
44
  (options.mode === 'protect-all'
35
45
  ? defaultProtectAllValidateFn
@@ -40,51 +50,101 @@ export const useGenericAuth = (options) => {
40
50
  fieldAuthDirectiveNode: input.astNode?.directives?.find(directive => directive.name.value === directiveOrExtensionFieldName),
41
51
  };
42
52
  };
53
+ const rejectUnauthenticated = 'rejectUnauthenticated' in options ? options.rejectUnauthenticated !== false : true;
43
54
  return {
44
55
  onPluginInit({ addPlugin }) {
45
56
  addPlugin(useExtendedValidation({
57
+ rejectOnErrors: rejectUnauthenticated,
46
58
  rules: [
47
59
  function AuthorizationExtendedValidationRule(context, args) {
60
+ const operations = {};
61
+ const fragments = {};
62
+ for (const definition of args.document.definitions) {
63
+ if (definition.kind === 'OperationDefinition') {
64
+ operations[definition.name?.value ?? args.operationName ?? 'Anonymous'] =
65
+ definition;
66
+ }
67
+ else if (definition.kind === 'FragmentDefinition') {
68
+ fragments[definition.name.value] = definition;
69
+ }
70
+ }
48
71
  const user = args.contextValue[contextFieldName];
49
- const handleField = (fieldNode, objectType) => {
72
+ const handleField = ({ node: fieldNode, path, }, objectType) => {
50
73
  const field = objectType.getFields()[fieldNode.name.value];
51
74
  if (field == null) {
52
75
  // field is null/undefined if this is an introspection field
53
76
  return;
54
77
  }
55
78
  const { fieldAuthExtension, fieldAuthDirectiveNode } = extractAuthMeta(field);
56
- const error = validateUser({
79
+ const resolvePath = [];
80
+ let curr = args.document;
81
+ for (const pathItem of path) {
82
+ curr = curr[pathItem];
83
+ if (curr?.kind === 'Field') {
84
+ resolvePath.push(curr.name.value);
85
+ }
86
+ }
87
+ return validateUser({
57
88
  user,
58
89
  fieldNode,
59
90
  objectType,
60
91
  fieldAuthDirectiveNode,
61
92
  fieldAuthExtension,
62
93
  executionArgs: args,
94
+ field,
95
+ path: resolvePath,
63
96
  });
64
- if (error) {
65
- context.reportError(error);
66
- }
67
97
  };
68
98
  return {
69
- Field(node) {
99
+ Field(node, key, parent, path, ancestors) {
70
100
  if (!shouldIncludeNode(args.variableValues, node)) {
71
101
  return;
72
102
  }
73
103
  const fieldType = getNamedType(context.getParentType());
74
104
  if (isIntrospectionType(fieldType)) {
75
- return false;
105
+ return node;
76
106
  }
77
107
  if (isObjectType(fieldType)) {
78
- handleField(node, fieldType);
108
+ const error = handleField({
109
+ node,
110
+ key,
111
+ parent,
112
+ path,
113
+ ancestors,
114
+ }, fieldType);
115
+ if (error) {
116
+ context.reportError(error);
117
+ return null;
118
+ }
79
119
  }
80
120
  else if (isUnionType(fieldType)) {
81
121
  for (const objectType of fieldType.getTypes()) {
82
- handleField(node, objectType);
122
+ const error = handleField({
123
+ node,
124
+ key,
125
+ parent,
126
+ path,
127
+ ancestors,
128
+ }, objectType);
129
+ if (error) {
130
+ context.reportError(error);
131
+ return null;
132
+ }
83
133
  }
84
134
  }
85
135
  else if (isInterfaceType(fieldType)) {
86
136
  for (const objectType of args.schema.getImplementations(fieldType).objects) {
87
- handleField(node, objectType);
137
+ const error = handleField({
138
+ node,
139
+ key,
140
+ parent,
141
+ path,
142
+ ancestors,
143
+ }, objectType);
144
+ if (error) {
145
+ context.reportError(error);
146
+ return null;
147
+ }
88
148
  }
89
149
  }
90
150
  return undefined;
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@envelop/generic-auth",
3
- "version": "7.0.0",
3
+ "version": "8.0.0-alpha-20240806125641-9b9885ba",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
6
  "@envelop/core": "^5.0.0",
7
7
  "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
8
8
  },
9
9
  "dependencies": {
10
- "@envelop/extended-validation": "^4.0.0",
10
+ "@envelop/extended-validation": "4.1.0-alpha-20240806125641-9b9885ba",
11
11
  "@graphql-tools/utils": "^10.0.6",
12
12
  "tslib": "^2.5.0"
13
13
  },
@@ -1,7 +1,5 @@
1
- import { DirectiveNode, ExecutionArgs, FieldNode, GraphQLError, GraphQLObjectType } from 'graphql';
1
+ import { DirectiveNode, ExecutionArgs, FieldNode, GraphQLError, GraphQLField, GraphQLObjectType } from 'graphql';
2
2
  import { DefaultContext, Maybe, Plugin, PromiseOrValue } from '@envelop/core';
3
- export declare class UnauthenticatedError extends GraphQLError {
4
- }
5
3
  export type ResolveUserFn<UserType, ContextType = DefaultContext> = (context: ContextType) => PromiseOrValue<Maybe<UserType>>;
6
4
  export type ValidateUserFnParams<UserType> = {
7
5
  /** The user object. */
@@ -10,15 +8,19 @@ export type ValidateUserFnParams<UserType> = {
10
8
  fieldNode: FieldNode;
11
9
  /** The object type which has the field that is being validated. */
12
10
  objectType: GraphQLObjectType;
11
+ /** The object field */
12
+ field: GraphQLField<any, any>;
13
13
  /** The directive node used for the authentication (If using an SDL flow). */
14
14
  fieldAuthDirectiveNode: DirectiveNode | undefined;
15
15
  /** The extensions used for authentication (If using an extension based flow). */
16
16
  fieldAuthExtension: unknown | undefined;
17
17
  /** The args passed to the execution function (including operation context and variables) **/
18
18
  executionArgs: ExecutionArgs;
19
+ /** Resolve path */
20
+ path: ReadonlyArray<string | number>;
19
21
  };
20
- export type ValidateUserFn<UserType> = (params: ValidateUserFnParams<UserType>) => void | UnauthenticatedError;
21
- export declare const DIRECTIVE_SDL = "\n directive @auth on FIELD_DEFINITION\n";
22
+ export type ValidateUserFn<UserType> = (params: ValidateUserFnParams<UserType>) => void | GraphQLError;
23
+ export declare const DIRECTIVE_SDL = "\n directive @authenticated on FIELD_DEFINITION\n";
22
24
  export declare const SKIP_AUTH_DIRECTIVE_SDL = "\n directive @skipAuth on FIELD_DEFINITION\n";
23
25
  export type GenericAuthPluginOptions<UserType extends {} = {}, ContextType = DefaultContext, CurrentUserKey extends string = 'currentUser'> = {
24
26
  /**
@@ -74,9 +76,20 @@ export type GenericAuthPluginOptions<UserType extends {} = {}, ContextType = Def
74
76
  * @default `defaultProtectSingleValidateFn`
75
77
  */
76
78
  validateUser?: ValidateUserFn<UserType>;
79
+ /**
80
+ * Reject on unauthenticated requests.
81
+ * @default true
82
+ */
83
+ rejectUnauthenticated?: boolean;
77
84
  });
78
- export declare function defaultProtectAllValidateFn<UserType>(params: ValidateUserFnParams<UserType>): void | UnauthenticatedError;
79
- export declare function defaultProtectSingleValidateFn<UserType>(params: ValidateUserFnParams<UserType>): void | UnauthenticatedError;
85
+ export declare function createUnauthenticatedError(params?: {
86
+ fieldNode?: FieldNode;
87
+ path?: ReadonlyArray<string | number>;
88
+ message?: string;
89
+ statusCode?: number;
90
+ }): GraphQLError;
91
+ export declare function defaultProtectAllValidateFn<UserType>(params: ValidateUserFnParams<UserType>): void | GraphQLError;
92
+ export declare function defaultProtectSingleValidateFn<UserType>(params: ValidateUserFnParams<UserType>): void | GraphQLError;
80
93
  export declare const useGenericAuth: <UserType extends {} = {}, ContextType extends Record<any, any> = DefaultContext, CurrentUserKey extends string = "currentUser">(options: GenericAuthPluginOptions<UserType, ContextType, CurrentUserKey>) => Plugin<{
81
94
  validateUser: ValidateUserFn<UserType>;
82
95
  } & Record<CurrentUserKey, UserType>>;
@@ -1,7 +1,5 @@
1
- import { DirectiveNode, ExecutionArgs, FieldNode, GraphQLError, GraphQLObjectType } from 'graphql';
1
+ import { DirectiveNode, ExecutionArgs, FieldNode, GraphQLError, GraphQLField, GraphQLObjectType } from 'graphql';
2
2
  import { DefaultContext, Maybe, Plugin, PromiseOrValue } from '@envelop/core';
3
- export declare class UnauthenticatedError extends GraphQLError {
4
- }
5
3
  export type ResolveUserFn<UserType, ContextType = DefaultContext> = (context: ContextType) => PromiseOrValue<Maybe<UserType>>;
6
4
  export type ValidateUserFnParams<UserType> = {
7
5
  /** The user object. */
@@ -10,15 +8,19 @@ export type ValidateUserFnParams<UserType> = {
10
8
  fieldNode: FieldNode;
11
9
  /** The object type which has the field that is being validated. */
12
10
  objectType: GraphQLObjectType;
11
+ /** The object field */
12
+ field: GraphQLField<any, any>;
13
13
  /** The directive node used for the authentication (If using an SDL flow). */
14
14
  fieldAuthDirectiveNode: DirectiveNode | undefined;
15
15
  /** The extensions used for authentication (If using an extension based flow). */
16
16
  fieldAuthExtension: unknown | undefined;
17
17
  /** The args passed to the execution function (including operation context and variables) **/
18
18
  executionArgs: ExecutionArgs;
19
+ /** Resolve path */
20
+ path: ReadonlyArray<string | number>;
19
21
  };
20
- export type ValidateUserFn<UserType> = (params: ValidateUserFnParams<UserType>) => void | UnauthenticatedError;
21
- export declare const DIRECTIVE_SDL = "\n directive @auth on FIELD_DEFINITION\n";
22
+ export type ValidateUserFn<UserType> = (params: ValidateUserFnParams<UserType>) => void | GraphQLError;
23
+ export declare const DIRECTIVE_SDL = "\n directive @authenticated on FIELD_DEFINITION\n";
22
24
  export declare const SKIP_AUTH_DIRECTIVE_SDL = "\n directive @skipAuth on FIELD_DEFINITION\n";
23
25
  export type GenericAuthPluginOptions<UserType extends {} = {}, ContextType = DefaultContext, CurrentUserKey extends string = 'currentUser'> = {
24
26
  /**
@@ -74,9 +76,20 @@ export type GenericAuthPluginOptions<UserType extends {} = {}, ContextType = Def
74
76
  * @default `defaultProtectSingleValidateFn`
75
77
  */
76
78
  validateUser?: ValidateUserFn<UserType>;
79
+ /**
80
+ * Reject on unauthenticated requests.
81
+ * @default true
82
+ */
83
+ rejectUnauthenticated?: boolean;
77
84
  });
78
- export declare function defaultProtectAllValidateFn<UserType>(params: ValidateUserFnParams<UserType>): void | UnauthenticatedError;
79
- export declare function defaultProtectSingleValidateFn<UserType>(params: ValidateUserFnParams<UserType>): void | UnauthenticatedError;
85
+ export declare function createUnauthenticatedError(params?: {
86
+ fieldNode?: FieldNode;
87
+ path?: ReadonlyArray<string | number>;
88
+ message?: string;
89
+ statusCode?: number;
90
+ }): GraphQLError;
91
+ export declare function defaultProtectAllValidateFn<UserType>(params: ValidateUserFnParams<UserType>): void | GraphQLError;
92
+ export declare function defaultProtectSingleValidateFn<UserType>(params: ValidateUserFnParams<UserType>): void | GraphQLError;
80
93
  export declare const useGenericAuth: <UserType extends {} = {}, ContextType extends Record<any, any> = DefaultContext, CurrentUserKey extends string = "currentUser">(options: GenericAuthPluginOptions<UserType, ContextType, CurrentUserKey>) => Plugin<{
81
94
  validateUser: ValidateUserFn<UserType>;
82
95
  } & Record<CurrentUserKey, UserType>>;