Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/graphql-community/graphql-directive-auth
GraphQL directive for handling auth
https://github.com/graphql-community/graphql-directive-auth
auth authentication authorization graphql graphql-directive graphql-server
Last synced: about 1 month ago
JSON representation
GraphQL directive for handling auth
- Host: GitHub
- URL: https://github.com/graphql-community/graphql-directive-auth
- Owner: graphql-community
- License: mit
- Created: 2018-07-26T16:49:18.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2023-01-06T01:41:55.000Z (almost 2 years ago)
- Last Synced: 2024-09-28T21:42:06.492Z (about 2 months ago)
- Topics: auth, authentication, authorization, graphql, graphql-directive, graphql-server
- Language: TypeScript
- Homepage:
- Size: 3.18 MB
- Stars: 136
- Watchers: 10
- Forks: 12
- Open Issues: 23
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# graphql-directive-auth
[![Version][version-badge]][package]
[![downloads][downloads-badge]][npmtrends]
[![PRs Welcome][prs-badge]][prs]
[![MIT License][license-badge]][build]# Introduction
The `graphql-directive-auth` was created to help with common authentication tasks that is faced in almost every API.
# Table of Contents
- [graphql-directive-auth](#graphql-directive-auth)
- [Introduction](#introduction)
- [Table of Contents](#table-of-contents)
- [Installation](#installation)
- [Usage](#usage)
- [Default](#default)
- [What `default` means, and what I **need to do**?](#what-default-means-and-what-i-need-to-do)
- [Example:](#example)
- [Custom behaviour of authentication functions](#custom-behaviour-of-authentication-functions)
- [Custom check role function](#custom-check-role-function)
- [How to create your own function](#how-to-create-your-own-function)
- [Directive Parameters](#directive-parameters)
- [Contributing](#contributing)
- [LICENSE](#license)# Installation
```
yarn add graphql-directive-auth
```# Usage
We are able to use directives in two different way:
## Default
To use the default directive behaviour, you need to set `APP_SECRET` environment variable, and that's all.
### What `default` means, and what do I **need to do**?
- `@isAuthenticated` - Just after you set environment variables, you need to have a valid JWT token and send it by `Authorization` in the HTTP headers. That's all, the directive will check your token and throw an error if the token is invalid or expired.
- `@hasRole` - Checks roles of an authenticated user. To use it correctly, inside your JWT token you should have the `role` property with the correct role. If the user role doesn't match with the provided role, then directive will throw an error.> `@hasRole` before checking role is doing authentication to get roles from JWT token.
### Example:
```js
import { AuthDirective } from 'graphql-directive-auth';
// or
const AuthDirective = require('graphql-directive-auth').AuthDirective;// set environment variable, but in better way ;)
process.env.APP_SECRET = 'your_secret_key';const schema = makeExecutableSchema({
typeDefs,
resolvers,
schemaDirectives: {
// to use @hasRole and @isAuthenticated directives
...AuthDirective(),
// custom name for @isAuthenticated
auth: AuthDirective().isAuthenticated,
// custom name for @hasRole
role: AuthDirective().hasRole,
},
});
```## Custom behaviour of authentication functions
If you need custom Authentication you can pass your authentication function to the main `AuthDirective` functions. Your authentication function should return an object which will be available via `context.auth`.
Authentication function signature:
```js
context => {
// your logic here// you should return an object
// this object will be passed inside your resolver
// it is available inside context via auth property
return {
user: {
id: 'your_user_id',
},
};
};
```usage:
```js
import { AuthDirective } from 'graphql-directive-auth';
// or
const AuthDirectives = require('graphql-directive-auth').AuthDirective;const customAuth = AuthDirectives({
authenticateFunc: authenticateCustomFunc,
checkRoleFunc: checkRoleCustomFunc
});const schema = makeExecutableSchema({
typeDefs,
resolvers,
schemaDirectives: {
// to use @hasRole and @isAuthenticated directives
...customAuth,
// custom name for @isAuthenticated
auth: customAuth().isAuthenticated,
// custom name for @hasRole
role: customAuth().hasRole,
},
```resolver:
```js
export default {
Query: {
me() (root, args, ctx){
const userId = ctx.auth.user.id; // your_user_id
},
},
};
```## Custom check role function
Same as with the authenticate function, you can add your own logic to checking roles. Here is an example of implementation:
```js
import { AuthenticationError } from 'apollo-server';
import jwt from 'jsonwebtoken';
import { jwtSecret } from '../config';export default (ctx, value) => {
const authorization =
ctx.request && ctx.request.headers && ctx.request.headers.authorization;if (!authorization) {
throw new AuthenticationError('Unauthorized access!');
}const token = authorization.replace('Bearer ', '');
const decodedToken = jwt.verify(token, jwtSecret);
const mandatoryRoles = value.split(',').map((s) => s.trim());
if (decodedToken && decodedToken.user && decodedToken.user.roles) {
const { roles } = decodedToken.user;
const rolesIntersection = roles.filter((role) =>
mandatoryRoles.includes(role),
);if (rolesIntersection.length === 0) {
throw new AuthenticationError('Invalid role!');
}return rolesIntersection;
}throw new AuthenticationError('Invalid token!');
};
```### How to create your own function
- Function accepts two parameters, one is the context and the second is the value from the directive
- To reject an access to the particular field, you need to throw an Error that will be caught by the directive and returned if required.
- Function doesn't need to return anything special# Directive Parameters
- '@isAuthenticated' - checks if user is authenticated
- '@hasRole(role: "user, admin")' - checks if user is authenticated and has the specified roles> if you use [`graphql-import`](https://github.com/prismagraphql/graphql-import) then you need to add this definition on top of the schema:
```graphql
directive @isAuthenticated on FIELD | FIELD_DEFINITION
directive @hasRole(role: String) on FIELD | FIELD_DEFINITION
```## Contributing
I would love to see your contribution. ❤️
For local development (and testing), all you have to do is to run `yarn` and then `yarn dev`. This will start the Apollo server and you are ready to contribute :tada:
Run yarn test (try `--watch` flag) for unit tests (we are using Jest)
# LICENSE
The MIT License (MIT) 2018 - Luke Czyszczonik -
[npm]: https://www.npmjs.com/
[node]: https://nodejs.org
[build-badge]: https://img.shields.io/travis/graphql-community/graphql-directive-auth.svg?style=flat-square
[build]: https://travis-ci.org/graphql-community/graphql-directive-auth
[coverage-badge]: https://img.shields.io/codecov/c/github/graphql-community/graphql-directive-auth.svg?style=flat-square
[coverage]: https://codecov.io/github/graphql-community/graphql-directive-auth
[version-badge]: https://img.shields.io/npm/v/graphql-directive-auth.svg?style=flat-square
[package]: https://www.npmjs.com/package/graphql-directive-auth
[downloads-badge]: https://img.shields.io/npm/dm/graphql-directive-auth.svg?style=flat-square
[npmtrends]: http://www.npmtrends.com/graphql-directive-auth
[license-badge]: https://img.shields.io/npm/l/graphql-directive-auth.svg?style=flat-square
[license]: https://github.com/graphql-community/graphql-directive-auth/blob/master/LICENSE
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
[prs]: http://makeapullrequest.com
[donate-badge]: https://img.shields.io/badge/$-support-green.svg?style=flat-square
[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
[coc]: https://github.com/graphql-community/graphql-directive-auth/blob/master/CODE_OF_CONDUCT.md