GraphQL @auth
directive that protects resources from unauthenticated and unauthorized access.
Inspired by TypeGraphQL and GraphQL Tools.
👋 Any help is appreciated
npm install graphql-auth-directive
# or
yarn add graphql-auth-directive
Note: See examples directory
-
Add
@auth
directive to GraphQL schema:Note:
on OBJECT | FIELD | FIELD_DEFINITION
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 }
-
Build
auth
directive and createGraphQL
schema: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:{ user?: { roles: string[] | number[]; permissions: string[] | number[]; }; /* ... */ }
If
defaultAuthFn
does not match your configuration or you want more control, you can fully customize theauth
procedure. See Custom Auth procedure for more information.
Name | Type | Default Value | Description |
---|---|---|---|
name |
string |
auth |
Directive name. |
auth |
Auth<TContext, TRole, TPermission> |
Auth function (AuthFn<TContext, TRole, TPermission> ) or class (AuthFnClass<TContext, TRole, TPermission> ). |
|
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<Error> |
AuthenticationError |
Authentication error class. An error class must extends Error . |
authorizationError |
ClassTypeEmptyConstructor<Error> |
AuthorizationError |
Authorization error class. An error class must extends Error . |
container |
ContainerType |
IOCContainer |
Dependency injection container. |
Warning:
auth
must returnboolean
orPromise<boolean>
, wheretrue
indicates that access has been granted andfalse
that is denied
You can fully customize the auth procedure by providing a function or class when building the directive.
import { buildAuthDirective } from 'graphql-auth-directive';
import { myAuth } from './myAuth';
// Build auth directive
const authDirective = buildAuthDirective({
auth: myAuth // Custom auth procedure
});
AuthFn
function
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, Roles, Permissions> = (
{ context: { user } }, // Context
{ roles, permissions } // @auth(roles: [...], permissions: [...])
) : boolean | Promise<boolean> => {
/* ... */
};
AuthFnClass
class
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 });
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<Context, UserRoles, Permissions> {
public auth(
{ context: { user } }, // Context
{ roles, permissions } // @auth(roles: [...], permissions: [...])
): boolean | Promise<boolean> {
/* ... */
}
}
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:
I would love to see your contribution ❤️
See CONTRIBUTING guidelines.
This project is licensed under the MIT License.
See LICENSE file for details.