On this page

@envelop/generic-auth

Changelog for @envelop/generic-auth: every release with its changes and the pull requests behind them.

12.0.0

Major Changes

  • #4574 79b0e8b Thanks @egoodwinx! - ### Breaking Changes

    • Node: minimum supported version is now Node 22. Node 18 and 20 are no longer supported. Future releases will only support Node >=22.
    • GraphQL: minimum supported version is now GraphQL 16. GraphQL 14 and 15 are no longer supported.
    • Request body parsing: Yoga now limits request bodies to 25,000,000 bytes by default. Enforcing this limit streams the body through a byte counter, making POST body parsing asynchronous even for an in-memory body. As a result, yoga.fetch() can return a Promise where it previously returned a synchronous Response, even when all resolvers and plugins are synchronous.

    Migration

    • If you’re on Node 18/20, upgrade to Node 22 or later before upgrading this package.
    • If you’re on graphql 14/15, upgrade to graphql 16 or 17 first.
    • Await yoga.fetch() and response body parsing instead of relying on synchronous results. Set maxRequestBodySize: false in createYoga to disable the body-size limit and preserve synchronous parsing for in-memory bodies, but only if you enforce an appropriate request-body limit elsewhere.
  • #4623 be89d05 Thanks @ardatan! - ### Dependencies

    • Bump @graphql-tools/utils to ^13.1.1, @graphql-tools/schema to ^11.0.0, and @graphql-tools/executor to ^4.1.2.

    Incremental delivery

    Yoga maps the GraphQL HTTP Accept header through INCREMENTAL_DELIVERY_SPECS from @graphql-tools/utils onto executor incrementalSpec. multipart/mixed;incrementalSpec=v0.2 runs the v0.2 payload format and echoes that spec on Content-Type. multipart/mixed;deferSpec=20220824 or bare multipart/mixed stays on v0.1. An unsupported incremental spec yields 406.

    A later incremental spec is a graphql-tools table row plus an executor publisher. Yoga, Hive Gateway, and HTTP executors pick it up by bumping @graphql-tools/utils / @graphql-tools/executor.

    Breaking Changes

    • createGraphQLError is removed. Use new GraphQLError(message, options) from graphql. To attach Yoga’s experimental schema coordinate, use withSchemaCoordinate(error, coordinate) and read with getSchemaCoordinate from @graphql-tools/utils.
    • mapMaybePromise is removed (was exported from Yoga / @envelop/core). Use handleMaybePromise from @whatwg-node/promise-helpers.
    • Yoga no longer re-exports helpers that already live upstream:
      • getSchemaCoordinate -> @graphql-tools/utils
      • mergeSchemas -> @graphql-tools/schema
      • DisposableSymbols -> @whatwg-node/server
      • mapAsyncIterator / isPromise / fakePromise / handleMaybePromise / MaybePromise -> @whatwg-node/promise-helpers
    • @envelop/core utils no longer re-exports mapAsyncIterator or isPromise. Import from @whatwg-node/promise-helpers.
    • Use asGetArgumentValuesVariables / coerceGetVariableValuesResult from @graphql-tools/utils for GraphQL 16/17 VariableValues compatibility.

    Migration

    import { GraphQLError } from 'graphql'
    import { withSchemaCoordinate } from 'graphql-yoga'
    import { mergeSchemas } from '@graphql-tools/schema'
    import { getSchemaCoordinate } from '@graphql-tools/utils'
    import { handleMaybePromise, isPromise, type MaybePromise } from '@whatwg-node/promise-helpers'
    import { DisposableSymbols } from '@whatwg-node/server'
    
    throw withSchemaCoordinate(new GraphQLError('not found'), 'Query.user')

Minor Changes

  • #4625 51701f4 Thanks @User! - Fix partial authorization responses incorrectly forcing HTTP 401 when using mode: 'protect-granular' with rejectUnauthenticated: false

    Default authorization errors no longer include extensions.http in this mode. Unauthorized fields are still returned as null with an UNAUTHORIZED_FIELD_OR_TYPE error, while permitted fields continue to execute. The HTTP server determines the response status normally, allowing partial GraphQL responses to return HTTP 200 instead of 401.

    For example, configure the plugin to resolve an already verified JWT payload and allow partial responses:

    useGenericAuth({
      mode: 'protect-granular',
      resolveUserFn: context => context.jwt?.payload,
      rejectUnauthenticated: false
    })

    Given this schema:

    directive @requiresScopes(scopes: [[String!]!]!) on OBJECT | FIELD_DEFINITION
    
    type Query {
     @requiresScopes(scopes: [["read:profile"]])
    }
    
    type User {
      name: String
      email: String @requiresScopes(scopes: [["read:email"]])
    }

    A user whose JWT payload contains scope: 'read:profile', but not read:email, can request:

    {
      user {
        name
        email
      }
    }

    The response contains the permitted data and the field-level authorization error, without an HTTP status override:

    {
      "data": {
        "user": {
          "name": "Jane",
          "email": null
        }
      },
      "errors": [
        {
          "message": "Unauthorized field or type",
          "locations": [{ "line": 4, "column": 5 }],
          "path": ["user", "email"],
          "extensions": {
            "code": "UNAUTHORIZED_FIELD_OR_TYPE"
          }
        }
      ]
    }

    Whole-operation rejection remains unchanged: setting rejectUnauthenticated: true, or omitting it, still rejects unauthorized operations with HTTP 401. Explicit HTTP statuses returned by a custom validateUser function are also preserved, even when rejectUnauthenticated: false.

Patch Changes

11.2.3

Patch Changes

11.2.2

Patch Changes

11.2.1

Patch Changes

  • #4577 7bff35c Thanks @egoodwinx! - Add homepage and bugs.url to package.json files

  • Updated dependencies [7bff35c]:

    • @envelop/extended-validation@7.2.1
    • @envelop/core@5.6.1

11.2.0

Minor Changes

  • #4545 94ebe5b Thanks @egoodwinx! - Update to support graphql-js 17

    Bump package versions, fix expected typing, and update compatability with subscribe.

Patch Changes

  • Updated dependencies [94ebe5b]:
    • @envelop/extended-validation@7.2.0
    • @envelop/core@5.6.0

11.1.1

Patch Changes

  • Updated dependencies [0bfde27]:
    • @envelop/core@5.5.1
    • @envelop/extended-validation@7.1.1

11.1.0

Patch Changes

11.0.0

Patch Changes

  • Updated dependencies [0434fbd]:
    • @envelop/core@5.4.0
    • @envelop/extended-validation@7.0.0

10.0.1

Patch Changes

  • #2742 62a8915 Thanks @enisdenjo! - Remove empty and unused nodes from redacted query after validation

  • Updated dependencies [62a8915]:

    • @envelop/extended-validation@6.1.0

10.0.0

Patch Changes

  • Updated dependencies [3ebaa3b]:
    • @envelop/core@5.3.0
    • @envelop/extended-validation@6.0.0

9.1.3

Patch Changes

  • Updated dependencies [914f9ed, 914f9ed]:
    • @envelop/core@5.2.3
    • @envelop/extended-validation@5.1.3

9.1.2

Patch Changes

  • Updated dependencies [26137e7, 26137e7]:
    • @envelop/core@5.2.2
    • @envelop/extended-validation@5.1.2

9.1.1

Patch Changes

9.1.0

Patch Changes

  • Updated dependencies [a107c89, a107c89]:
    • @envelop/core@5.2.0
    • @envelop/extended-validation@5.1.0

9.0.1

Patch Changes

  • Updated dependencies [5b6a166]:
    • @envelop/core@5.1.1
    • @envelop/extended-validation@5.0.1

9.0.0

Patch Changes

  • Updated dependencies [9bd1b20]:
    • @envelop/core@5.1.0
    • @envelop/extended-validation@5.0.0

8.0.1

Patch Changes

  • #2347 8b7e657 Thanks @ardatan! - dependencies updates:

  • #2347 8b7e657 Thanks @ardatan! - Handle operations with `@include` and `@skip` correctly when they have default values in the operation definition

    {
        query: /* GraphQL */ `
          query MyQuery($include: Boolean = true) {
            field @include(if: $include)
          }
        `,
        variables: {}
    }

    should be considered same as

    {
        query: /* GraphQL */ `
          query MyQuery($include: Boolean!) {
            field @include(if: $include)
          }
        `,
        variables: {
            include: true
        }
    }

8.0.0

Major Changes

  • #2281 70d4d7a Thanks @UserType;! - Refactor Generic Auth plugin;

    • [BREAKING] - Now @auth directive is renamed to @authenticated. If you want to keep the old name you can configure the plugin to use the old name.
    useGenericAuth({
      // ...
      authDirectiveName: 'auth'
    })
    • [BREAKING] - Now directiveOrExtensionFieldName is renamed to authDirectiveName.
    useGenericAuth({
      // ...
    - directiveOrExtensionFieldName: 'auth',
    + authDirectiveName: 'auth',
    });
    • Now auth directives support OBJECT and INTERFACE locations, so you can use the auth directive on types as well.
    directive @authenticated on OBJECT | INTERFACE
    
    type User @authenticated {
      id: ID!
      name: String!
    }
    • validateUser function does not receive fieldAuthDirectiveNode and fieldAuthExtension anymore. Instead, it takes fieldAuthArgs which is an object that contains the arguments of the auth directive or extension. So you don’t need to parse the arguments manually anymore.
    const validateUser: ValidateUserFn = params => {
      if (!params.fieldAuthArgs.roles.includes('admin')) {
        return createUnauthorizedError(params)
      }
    }
    • validateUser’s objectType parameter is now renamed to parentType. And it takes the original composite type instead of the GraphQLObjectType instance. Now it can be GraphQLInterfaceType as well.
    • validateUser’s current parameters are now;
    export type ValidateUserFnParams<UserType> = {
      /** The user object. */
    
      /** The field node from the operation that is being validated. */
      fieldNode: FieldNode
      /** The parent type which has the field that is being validated. */
      parentType: GraphQLObjectType | GraphQLInterfaceType
      /** The auth directive arguments for the type */
      typeAuthArgs?: Record<string, any>
      /** The directives for the type */
      typeDirectives?: ReturnType<typeof getDirectiveExtensions>
      /** Scopes that type requires */
      typeScopes?: string[][]
      /** Policies that type requires */
      typePolicies?: string[][]
      /** The object field */
      field: GraphQLField<any, any>
      /** The auth directive arguments for the field */
      fieldAuthArgs?: Record<string, any>
      /** The directives for the field */
      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) **/
      executionArgs: ExecutionArgs
      /** Resolve path */
      path: ReadonlyArray<string | number>
    }
    • New directives for role-based auth are added @requiresScopes and @policy for more granular control over the auth logic.
    directive @requiresScopes(scopes: [String!]!) on OBJECT | INTERFACE | FIELD_DEFINITION
    
    directive @policy(policy: String!) on OBJECT | INTERFACE | FIELD_DEFINITION

    Check README for more information.

Patch Changes

7.0.0

Major Changes

Patch Changes

  • Updated dependencies [68e7a2a5]:
    • @envelop/extended-validation@4.0.0

6.1.1

Patch Changes

6.1.0

Minor Changes

Patch Changes

6.0.1

Patch Changes

  • Updated dependencies []:
    • @envelop/core@4.0.1
  • Updated dependencies []:
    • @envelop/extended-validation@3.0.1

6.0.0

Major Changes

Patch Changes

5.0.6

Patch Changes

5.0.5

Patch Changes

  • Updated dependencies [270249cf]:
    • @envelop/core@3.0.5
  • Updated dependencies []:
    • @envelop/extended-validation@2.0.5

5.0.4

Patch Changes

  • Updated dependencies []:
    • @envelop/core@3.0.4
  • Updated dependencies []:
    • @envelop/extended-validation@2.0.4

5.0.3

Patch Changes

  • Updated dependencies [6b48ef96]:
    • @envelop/core@3.0.3
  • Updated dependencies []:
    • @envelop/extended-validation@2.0.3

5.0.2

Patch Changes

  • Updated dependencies [22f5ccfb]:
    • @envelop/core@3.0.2
  • Updated dependencies []:
    • @envelop/extended-validation@2.0.2

5.0.0

Major Changes

Patch Changes

  • Updated dependencies []:
    • @envelop/extended-validation@2.0.0

4.6.0

Minor Changes

  • give access to execute args in validateUser function.

    This is useful in conjunction with the fieldAuthExtension parameter to achieve custom per field validation:

    import { ValidateUserFn } from '@envelop/generic-auth'
    
    const validateUser: ValidateUserFn<UserType> = async ({ user, executionArgs, fieldAuthExtension }) => {
      if (!user) {
        throw new Error(`Unauthenticated!`)
      }
    
      // You have access to the object define in the resolver tree, allowing to define any custom logic you want.
      const validate = fieldAuthExtension?.validate
      if (validate) {
        await validate({ user, variables: executionArgs.variableValues, context: executionArgs.contextValue })
      }
    }
    
    const resolvers = {
      Query: {
    
          resolve: (_, { userId }) => getUser(userId),
          extensions: {
            auth: {
              validate: ({ user, variables, context }) => {
                // We can now have access to the operation and variables to decide if the user can execute the query
                if (user.id !== variables.userId) {
                  throw new Error(`Unauthorized`)
                }
              }
            }
          }
        }
      }
    }

4.5.0

Minor Changes

  • #1499 1f7af02b Thanks @viniciuspalma! - Adding tslib to package dependencies

    Projects that currently are using yarn Berry with PnP or any strict dependency resolver, that requires that all dependencies are specified on package.json otherwise it would endue in an error if not treated correct

    Since https://www.typescriptlang.org/tsconfig#importHelpers is currently being used, tslib should be exported as a dependency to external runners get the proper import.

    Change on each package:

    // package.json
    {
      "dependencies": {
        "tslib": "^2.4.0"
      }
    }
  • Updated dependencies [1f7af02b, ae7bc9a3]:

    • @envelop/core@2.6.0

Patch Changes

  • Updated dependencies [1f7af02b]:
    • @envelop/extended-validation@1.9.0

4.4.0

Minor Changes

Patch Changes

  • Updated dependencies []:
    • @envelop/extended-validation@1.8.0

4.3.2

Patch Changes

  • 071f946: Fix CommonJS TypeScript resolution with moduleResolution node16 or nodenext
  • Updated dependencies [071f946]
    • @envelop/core@2.4.2
  • Updated dependencies [071f946]
    • @envelop/extended-validation@1.7.2

4.3.1

Patch Changes

  • Updated dependencies [787d28a2]
    • @envelop/core@2.4.1
    • @envelop/extended-validation@1.7.1

4.3.0

Minor Changes

  • 8bb2738: Support TypeScript module resolution.
  • Updated dependencies [8bb2738]
    • @envelop/core@2.4.0

Patch Changes

  • Updated dependencies [8bb2738]
    • @envelop/extended-validation@1.7.0

4.2.4

Patch Changes

  • ddd0e4f: useGenericAuth’s ContextType generic used to accept the types that has an index signature which makes it impossible to use it with “fixed types”. Now it defaults to DefaultContext without extending it so any kind of type can be used as ContextType.

    Also useGenericAuth now takes a third generic which is the name of the field name that contains the user data in the context. It can be also inferred from contextFieldName of the plugin options.

4.2.3

Patch Changes

  • fbf6155: update package.json repository links to point to the new home
  • Updated dependencies [fbf6155]
    • @envelop/core@2.3.3
  • Updated dependencies [fbf6155]
    • @envelop/extended-validation@1.6.3

4.2.2

Patch Changes

  • Updated dependencies [07d029b]
    • @envelop/core@2.3.2
    • @envelop/extended-validation@1.6.2

4.2.1

Patch Changes

  • Updated dependencies [d5c2c9a]
    • @envelop/core@2.3.1
    • @envelop/extended-validation@1.6.1

4.2.0

Minor Changes

  • Updated dependencies [af23408]
    • @envelop/core@2.3.0

Patch Changes

  • @envelop/extended-validation@1.6.0

4.1.0

Minor Changes

  • Updated dependencies [ada7fb0]
  • Updated dependencies [d5115b4]
  • Updated dependencies [d5115b4]
    • @envelop/core@2.2.0

Patch Changes

  • @envelop/extended-validation@1.5.0

4.0.1

Patch Changes

  • Updated dependencies [01c8dd6]
    • @envelop/extended-validation@1.4.1

4.0.0

Major Changes

  • 7f78839: Use the extended validation phase instead of resolver wrapping for applying authentication rules.

    onResolverCalled results in wrapping all resolvers in the schema and can be a severe performance bottle-neck.

    Now the authorization rules are applied statically before running any execution logic, which results in the WHOLE operation being rejected as soon as a field in the selection set does not have sufficient permissions.

    The mode protect-auth-directive has been renamed to protect-granular.

    The authDirectiveName option got renamed to directiveOrExtensionFieldName.

    Authorization rules for the protect-all and protect-granular, can be applied via field extensions:

    // schema.ts
    import { GraphQLInt, GraphQLObjectType } from 'graphql'
    
    const GraphQLQueryType = new GraphQLObjectType({
      name: 'Query',
      fields: {
        foo: {
          type: GraphQLInt,
          resolve: () => 1,
          extensions: {
            skipAuth: true
            // or auth: true for mode "protect-granular".
          }
        }
      }
    })

    The validateUser function is no longer attached to the context object passed to the resolvers. You can add your own validateUser function to the context using useExtendContext.

    const getEnveloped = envelop({
      plugins: [
        useSchema(schema),
        useGenericAuth(options),
        useExtendContext(() => ({ validateUser }))
      ]
    })

Minor Changes

  • Updated dependencies [78b3db2]
  • Updated dependencies [f5eb436]
    • @envelop/core@2.1.0

Patch Changes

  • Updated dependencies [78b3db2]
  • Updated dependencies [8030244]
    • @envelop/extended-validation@1.4.0

3.0.0

Patch Changes

  • Updated dependencies [4106e08]
  • Updated dependencies [aac65ef]
  • Updated dependencies [4106e08]
    • @envelop/core@2.0.0

2.0.0

Patch Changes

  • Updated dependencies [d9cfb7c]
    • @envelop/core@1.7.0

1.2.1

Patch Changes

  • b1a0331: Properly list @envelop/core as a peerDependency in plugins.

    This resolves issues where the bundled envelop plugins published to npm had logic inlined from the @envelop/core package, causing instanceof check of EnvelopError to fail.

  • Updated dependencies [b1a0331]

    • @envelop/core@1.6.1

1.2.0

Minor Changes

  • 090cae4: GraphQL v16 support

1.1.0

Minor Changes

  • 04120de: add support for GraphQL.js 16

Patch Changes

  • 9f63dac: Add skipAuth directive to protect-all auth option

1.0.1

Patch Changes

  • 546db6c: Fix issue with inaccessible directiveNode

1.0.1

Patch Changes

  • Fix issue with inaccessible directiveNode

1.0.0

Major Changes

  • 40bc444: v1 major release for envelop packages

0.2.0

Minor Changes

  • 83b2b92: Extend plugin errors from GraphQLError.

0.1.1

Patch Changes

  • 28ad742: Improve TypeScript types

0.1.0

Minor Changes

  • eb6f53b: ESM Support for all plugins and envelop core

0.0.2

Patch Changes

  • 5fc65a4: Improved type-safety for internal context

0.0.1

Patch Changes

  • 55a13bd: NEW PLUGIN!