Skip to content

Commit f476a82

Browse files
committed
Added initial README.md content for public release ✏
1 parent cd4bc26 commit f476a82

File tree

2 files changed

+146
-1
lines changed

2 files changed

+146
-1
lines changed

README.md

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,148 @@
44
</p>
55

66
---
7+
8+
# Summary
9+
10+
`gql-auth-directives` is a set of schema directives that allows a granular approach to role-based access control with GraphQL.
11+
12+
## Features
13+
14+
- Directives for roles, permissions and authentication
15+
- Allows access control for queries, mutations
16+
- Allows access control for input types
17+
- Provided with default handlers using JWTs
18+
19+
# Getting Started
20+
21+
## Prerequisites
22+
23+
This package requires the user to use a server that supports [Apollo schema directives](https://www.apollographql.com/docs/graphql-tools/schema-directives/).
24+
25+
## Installing
26+
27+
Use npm
28+
29+
```
30+
$ npm install --save gql-auth-directives
31+
```
32+
33+
or yarn
34+
35+
```
36+
$ yarn add gql-auth-directives
37+
```
38+
39+
to install the package.
40+
41+
# Available directives
42+
43+
- `@hasRole(roles: ["ADMIN", "USER"])`
44+
> A user with either an admin or user role will be authorized
45+
- `@hasPermission(permissions: ["CREATE_USERS"])`
46+
- `@isAuthenticated`
47+
48+
# Setup
49+
50+
## Default handlers
51+
52+
To use the default handlers, the environment variable `JWT_SECRET` must be set. The variable will be used for verifying authorization headers and grab `roles`/`permissions` arrays in the token's payload.
53+
54+
We need to generate the auth directives and add it to the server configuration like so:
55+
56+
```javascript
57+
import { createAuthDirectives } from "gql-auth-directives";
58+
59+
const authDirectives = createAuthDirectives();
60+
61+
const server = new ApolloServer({
62+
typeDefs,
63+
resolvers,
64+
schemaDirectives: { ...authDirectives },
65+
context(ctx) {
66+
return { ...ctx }; // ⚠ Make sure to always pass the ctx from the server's context function
67+
},
68+
});
69+
```
70+
71+
## Override handlers
72+
73+
The library also allows using custom functions for the provided directives.
74+
75+
You could override the `hasPermission` handler like so:
76+
77+
```javascript
78+
import { createAuthDirectives } from "gql-auth-directives";
79+
80+
const authDirectives = createAuthDirectives({
81+
hasPermissionHandler: (ctx, permissions) => {
82+
const user = getUser(ctx);
83+
// Do something with the user and throw an error if the user's permissions doesn't match the permissions passed
84+
},
85+
});
86+
87+
const server = new ApolloServer({
88+
typeDefs,
89+
resolvers,
90+
schemaDirectives: { ...authDirectives },
91+
context(ctx) {
92+
return { ...ctx };
93+
},
94+
});
95+
```
96+
97+
## Schema declarations
98+
99+
We also need to add the directives declarations at the top of our GraphQL schema like so:
100+
101+
```graphql
102+
directive @isAuthenticated on FIELD | FIELD_DEFINITION | INPUT_FIELD_DEFINITION
103+
directive @hasPermission(permissions: [String!]!) on FIELD | FIELD_DEFINITION | INPUT_FIELD_DEFINITION
104+
directive @hasRole(roles: [String!]!) on FIELD | FIELD_DEFINITION | INPUT_FIELD_DEFINITION
105+
106+
[...]
107+
```
108+
109+
If you use something like `makeExecutableSchema` from [graphql-tools](https://github.com/apollographql/graphql-tools) that allows schema stitching you can also add the directives declarations like so:
110+
111+
```javascript
112+
import { createAuthDirectives, authTypeDefs } from "gql-auth-directives";
113+
import { makeExecutableSchema } from "graphql-tools";
114+
115+
const authDirectives = createAuthDirectives();
116+
117+
const schema = makeExecutableSchema({
118+
resolvers,
119+
typeDefs: [authTypeDefs, typeDefs],
120+
schemaDirectives: { ...authDirectives },
121+
});
122+
123+
const server = new ApolloServer({
124+
schema,
125+
context(ctx) {
126+
return { ...ctx };
127+
},
128+
});
129+
```
130+
131+
# Usage
132+
133+
We can now use our directives inside our GraphQL schema:
134+
135+
```graphql
136+
input CreatePostInput {
137+
name: String!
138+
description: String!
139+
published: Boolean @hasPermission(permissions: ["PUBLISH_POST"])
140+
}
141+
142+
type Mutation {
143+
createPost(data: CreatePostInput!): Post! @hasRole(roles: ["AUTHOR"])
144+
}
145+
146+
type Query {
147+
me: User! @isAuthenticated
148+
}
149+
```
150+
151+
> ℹ Notice that you can also use the directives for inputs. If an unauthorized user tries to fill the published field it will throw an error and never reach the resolver.

example/server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const authDirectives = createAuthDirectives({
1515
});
1616
const schema = makeExecutableSchema({
1717
resolvers,
18-
typeDefs: [typeDefs, authTypeDefs],
18+
typeDefs: [authTypeDefs, typeDefs],
1919
schemaDirectives: { ...authDirectives },
2020
});
2121

0 commit comments

Comments
 (0)