GraphQL @auth directive that protects resources from unauthenticated and unauthorized access
npm install graphql-auth-directive






GraphQL @auth directive that protects resources from unauthenticated and unauthorized access.
Inspired by TypeGraphQL and GraphQL Tools.
:warning: Under development
:wave: Any help is appreciated
``console`
npm install graphql-auth-directiveor
yarn add graphql-auth-directive
> Note: See examples directory
1. Add @auth directive to GraphQL schema:
> Note: on OBJECT | FIELD | FIELD_DEFINITION
`graphql
type Example @auth {
unprotected: String!
adminProtected: String! @auth(roles: [ADMIN])
}
type Query {
unprotected: String!
protected: String! @auth
adminRoleProtected: String! @auth(roles: [ADMIN])
adminOrModeratorRolesProtected: String! @auth(roles: [ADMIN, MODERATOR])
viewPermissionProtected: String! @auth(permissions: [VIEW])
viewOrEditPermissionsProtected: String! @auth(permissions: [VIEW, EDIT])
roleAndPermissionProtected: String! @auth(roles: [ADMIN], permissions: [VIEW])
# ...
}
type Mutation {
# Same as Query
}
type Subscription {
# Same as Query
}
`
1. Build auth directive and create GraphQL schema:
`ts
import { buildAuthDirective, defaultAuthFn } from 'graphql-auth-directive';
import { makeExecutableSchema } from '@graphql-tools/schema';
import { ApolloServer } from 'apollo-server';
import { typeDefs } from './typeDefs';
import { resolvers } from './resolvers';
// Build auth directive
const authDirective = buildAuthDirective({
auth: defaultAuthFn // Auth procedure (default or custom)
// ... More options
});
// Build schema
let schema = makeExecutableSchema({
typeDefs: [authDirective.typeDefs, typeDefs], // TypeDefs
resolvers // Resolvers
});
schema = authDirective.transformer(schema); // Transform schema
// Build and start server
const server = new ApolloServer({
schema,
context: () => {
/ ... /
}
});
server
.listen()
.then((serverInfo) => console.info(Server started at ${serverInfo.url}));`
> Warning: defaultAuthFn requires a context of the following type:
`ts`
{
user?: {
roles: string[] | number[];
permissions: string[] | number[];
};
/ ... /
}
If defaultAuthFn does not match your configuration or you want more control, you can fully customize the auth procedure. See Custom Auth procedure for more information.
| Name | Type | Default Value | Description |
| --------------------- | ---------------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name | string | auth | Directive name. |auth
| | Auth | | Auth function (AuthFn) or class (AuthFnClass). |authMode
| | 'ERROR' \| 'NULL' | ERROR | Auth mode if access is not granted. ERROR throws an error. NULL returns null. |roles
| | { enumName?: string, default?: TRole \| TRole[] } | { enumName: undefined, default: undefined } | Roles configuration. enumName is the enum name for roles array type, default is String. default is the default value, default to []. |permissions
| | { enumName?: string, default?: TPermission \| TPermission[] } | { enumName: undefined, default: undefined } | Permissions configuration. enumName is the enum name for permissions array type, default is String. default is the default value, default to []. |authenticationError
| | ClassTypeEmptyConstructor | AuthenticationError | Authentication error class. An error class must extends Error. |authorizationError
| | ClassTypeEmptyConstructor | AuthorizationError | Authorization error class. An error class must extends Error. |container
| | ContainerType | IOCContainer | Dependency injection container. |
> Warning: auth must return boolean or Promise, where true indicates that access has been granted and false that is denied
You can fully customize the auth procedure by providing a function or class when building the directive.
`ts
import { buildAuthDirective } from 'graphql-auth-directive';
import { myAuth } from './myAuth';
// Build auth directive
const authDirective = buildAuthDirective({
auth: myAuth // Custom auth procedure
});
`
`ts
import type { AuthFn } from 'graphql-auth-directive';
import type { Context } from './Context'; // Your context type
import type { Roles, Permissions } from './User'; // Your roles and permissions enum
export const myAuthFn: AuthFn
{ context: { user } }, // Context
{ roles, permissions } // @auth(roles: [...], permissions: [...])
) : boolean | Promise
/ ... /
};
`
> Note: Class based auth can leverage Dependency Injection (DI) mechanism. To enable DI mechanism register your OCI Container when building the directive: buildAuthDirective({ ..., container: MyContainer });
`ts
import type { AuthFnClass } from 'graphql-auth-directive';
import type { Context } from './Context'; // Your context type
import type { Roles, Permissions } from './User'; // Your roles and permissions enum
export class MyAuthFnClass implements AuthFnClass
public auth(
{ context: { user } }, // Context
{ roles, permissions } // @auth(roles: [...], permissions: [...])
): boolean | Promise
/ ... /
}
}
``
See typegraphql example for more information.
Similar libraries are unmaintained and use an old (and deprecated) version of graphql-tools.
Moreover this library tries to be as most modular as possible, giving the user the ability to configure the directive as much as possible.
Similar libraries:
1. graphql-auth-user-directives
I would love to see your contribution :heart:
See CONTRIBUTING guidelines.
This project is licensed under the MIT License. \
See LICENSE file for details.
