graphql-auth-directive
v0.5.1
Published
GraphQL @auth directive that protects resources from unauthenticated and unauthorized access
Downloads
39
Maintainers
Readme
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
Installation
npm install graphql-auth-directive
# or
yarn add graphql-auth-directive
Usage
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.
Options
| 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. |
Custom Auth procedure
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> {
/* ... */
}
}
Integrations
TypeGraphQL
See typegraphql example for more information.
Why another GraphQL Auth Directive?
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:
Contributing
I would love to see your contribution :heart:
See CONTRIBUTING guidelines.
License
This project is licensed under the MIT License.
See LICENSE file for details.