@envelop/generic-auth 1.1.0-alpha-6952fd9.0 → 1.2.2-alpha-1e6c37b.0

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
@@ -72,7 +72,7 @@ Now, configure your plugin based on the mode you wish to use:
72
72
 
73
73
  #### Option #1 - `protect-all`
74
74
 
75
- This mode offers complete protection for the entire API. It protects your entire GraphQL schema by validating the user before executing the request.
75
+ This mode offers complete protection for the entire API. It protects your entire GraphQL schema by validating the user before executing the request. You can optionally skip auth validation for specific GraphQL fields by using the `@skipAuth` directive.
76
76
 
77
77
  To setup this mode, use the following config:
78
78
 
@@ -102,6 +102,22 @@ const getEnveloped = envelop({
102
102
  });
103
103
  ```
104
104
 
105
+ > By default, we assume that you have the GraphQL directive definition as part of your GraphQL schema (`directive @skipAuth on FIELD_DEFINITION`).
106
+
107
+ Then, in your GraphQL schema SDL, you can add `@skipAuth` directive to your fields, and the `validateUser` will not get called while resolving that specific field:
108
+
109
+ ```graphql
110
+ type Query {
111
+ me: User!
112
+ protectedField: String
113
+ publicField: String @skipAuth
114
+ }
115
+ ```
116
+
117
+ > You can apply that directive to any GraphQL `field` definition, not only to root fields.
118
+
119
+ > If you are using a different directive for authentication, you can pass `authDirectiveName` configuration to customize it.
120
+
105
121
  #### Option #2 - `resolve-only`
106
122
 
107
123
  This mode uses the plugin to inject the authenticated user into the `context`, and later you can verify it in your resolvers.
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { DefaultContext, Plugin } from '@envelop/types';
1
+ import { DefaultContext, Plugin } from '@envelop/core';
2
2
  import { DirectiveNode, GraphQLError, GraphQLResolveInfo } from 'graphql';
3
3
  export * from './utils';
4
4
  export declare class UnauthenticatedError extends GraphQLError {
@@ -11,6 +11,7 @@ export declare type ValidateUserFn<UserType, ContextType = DefaultContext> = (us
11
11
  info: GraphQLResolveInfo;
12
12
  }, directiveNode?: DirectiveNode) => void | Promise<void>;
13
13
  export declare const DIRECTIVE_SDL = "\n directive @auth on FIELD_DEFINITION\n";
14
+ export declare const SKIP_AUTH_DIRECTIVE_SDL = "\n directive @skipAuth on FIELD_DEFINITION\n";
14
15
  export declare type GenericAuthPluginOptions<UserType extends {} = {}, ContextType extends DefaultContext = DefaultContext> = {
15
16
  /**
16
17
  * Here you can implement any custom sync/async code, and use the context built so far in Envelop and the HTTP request
@@ -33,8 +34,14 @@ export declare type GenericAuthPluginOptions<UserType extends {} = {}, ContextTy
33
34
  /**
34
35
  * This mode offers complete protection for the entire API.
35
36
  * It protects your entire GraphQL schema, by validating the user before executing the request.
37
+ * You can skip the validation using `@skipAuth` directive on a specific field.
36
38
  */
37
39
  mode: 'protect-all';
40
+ /**
41
+ * Overrides the default directive name
42
+ * @default skipAuth
43
+ */
44
+ authDirectiveName?: 'skipAuth' | string;
38
45
  } | {
39
46
  /**
40
47
  * Just resolves the user and inject to authenticated user into the `context`.
package/index.js CHANGED
@@ -19,6 +19,9 @@ class UnauthenticatedError extends graphql.GraphQLError {
19
19
  const DIRECTIVE_SDL = /* GraphQL */ `
20
20
  directive @auth on FIELD_DEFINITION
21
21
  `;
22
+ const SKIP_AUTH_DIRECTIVE_SDL = /* GraphQL */ `
23
+ directive @skipAuth on FIELD_DEFINITION
24
+ `;
22
25
  function defaultValidateFn(user, contextType) {
23
26
  if (!user) {
24
27
  throw new UnauthenticatedError('Unauthenticated!');
@@ -31,11 +34,21 @@ const useGenericAuth = (options) => {
31
34
  return {
32
35
  async onContextBuilding({ context, extendContext }) {
33
36
  const user = await options.resolveUserFn(context);
34
- await validateUser(user, context);
35
37
  extendContext({
36
38
  [fieldName]: user,
39
+ validateUser,
37
40
  });
38
41
  },
42
+ onExecute() {
43
+ return {
44
+ async onResolverCalled({ args, root, context, info }) {
45
+ const authDirectiveNode = getDirective(info, options.authDirectiveName || 'skipAuth');
46
+ if (authDirectiveNode)
47
+ return;
48
+ await context.validateUser(context[fieldName], context);
49
+ },
50
+ };
51
+ },
39
52
  };
40
53
  }
41
54
  else if (options.mode === 'resolve-only') {
@@ -79,6 +92,7 @@ const useGenericAuth = (options) => {
79
92
  };
80
93
 
81
94
  exports.DIRECTIVE_SDL = DIRECTIVE_SDL;
95
+ exports.SKIP_AUTH_DIRECTIVE_SDL = SKIP_AUTH_DIRECTIVE_SDL;
82
96
  exports.UnauthenticatedError = UnauthenticatedError;
83
97
  exports.defaultValidateFn = defaultValidateFn;
84
98
  exports.getDirective = getDirective;
package/index.mjs CHANGED
@@ -15,6 +15,9 @@ class UnauthenticatedError extends GraphQLError {
15
15
  const DIRECTIVE_SDL = /* GraphQL */ `
16
16
  directive @auth on FIELD_DEFINITION
17
17
  `;
18
+ const SKIP_AUTH_DIRECTIVE_SDL = /* GraphQL */ `
19
+ directive @skipAuth on FIELD_DEFINITION
20
+ `;
18
21
  function defaultValidateFn(user, contextType) {
19
22
  if (!user) {
20
23
  throw new UnauthenticatedError('Unauthenticated!');
@@ -27,11 +30,21 @@ const useGenericAuth = (options) => {
27
30
  return {
28
31
  async onContextBuilding({ context, extendContext }) {
29
32
  const user = await options.resolveUserFn(context);
30
- await validateUser(user, context);
31
33
  extendContext({
32
34
  [fieldName]: user,
35
+ validateUser,
33
36
  });
34
37
  },
38
+ onExecute() {
39
+ return {
40
+ async onResolverCalled({ args, root, context, info }) {
41
+ const authDirectiveNode = getDirective(info, options.authDirectiveName || 'skipAuth');
42
+ if (authDirectiveNode)
43
+ return;
44
+ await context.validateUser(context[fieldName], context);
45
+ },
46
+ };
47
+ },
35
48
  };
36
49
  }
37
50
  else if (options.mode === 'resolve-only') {
@@ -74,4 +87,4 @@ const useGenericAuth = (options) => {
74
87
  return {};
75
88
  };
76
89
 
77
- export { DIRECTIVE_SDL, UnauthenticatedError, defaultValidateFn, getDirective, useGenericAuth };
90
+ export { DIRECTIVE_SDL, SKIP_AUTH_DIRECTIVE_SDL, UnauthenticatedError, defaultValidateFn, getDirective, useGenericAuth };
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@envelop/generic-auth",
3
- "version": "1.1.0-alpha-6952fd9.0",
3
+ "version": "1.2.2-alpha-1e6c37b.0",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
+ "@envelop/core": "1.6.6-alpha-1e6c37b.0",
6
7
  "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
7
8
  },
8
9
  "repository": {
@@ -26,6 +27,7 @@
26
27
  "./*": {
27
28
  "require": "./*.js",
28
29
  "import": "./*.mjs"
29
- }
30
+ },
31
+ "./package.json": "./package.json"
30
32
  }
31
33
  }