GithubHelp home page GithubHelp logo

graphql-auth's Introduction

GraphQL Auth

πŸ”’ Authentication and authorization middleware for GraphQL.

graphql-auth is a very simple middleware that easily integrates with any GraphQL server that follows the GraphQL API for resolvers.

Getting Started

How It Works

graphql-auth exports a single function (middleware) withAuth. This function takes two parameters, the first is scope (if any) for authorization, and the second is the callback to call when auth checking is complete. Let's look at an example:

import withAuth from 'graphql-auth';

const resolvers = {
  Query: {
    users: withAuth(['users:view'], (root, args, context) => { ... }),
    ...
  }
}

The way this works is withAuth looks for a special auth property on the context of the resolver. It expects the auth property to have two properties of its own:

  1. isAuthenticated to tell if the user is logged in
  2. scope scope of the logged in user (optional)

This allows you to use any form of authentication already supported by common frameworks like express and hapi. Here is an example in Hapi.js:

import { graphqlHapi } from 'graphql-server-hapi';
import { makeExecutableSchema } from 'graphql-tools';

import typeDefs from './type-defs';
import resolvers from './resolvers';

const register = function(server, options, next) {
  const executableSchema = makeExecutableSchema({
    resolvers,
    typeDefs,
  });

  server.register(
    [
      {
        register: graphqlHapi,
        options: {
          path: '/graphql',
          graphqlOptions: request => ({
            pretty: true,
            schema: executableSchema,
            context: {
              auth: {
                isAuthenticated: request.auth.isAuthenticated,
                scope: request.auth.credentials
                  ? request.auth.credentials.scope
                  : null,
              },
            },
          }),
        },
      },
    ],
    error => {
      if (error) return next(error);
      next();
    }
  );
};

register.attributes = {
  name: 'graphql-api',
  version: '1.0.0',
};

export default register;

For more in depth examples take a look at the graphql-auth-examples repo.

Installation

yarn add graphql-auth

withAuth([scope,] callback)

Without scope:

import withAuth from 'graphql-auth';

const resolvers = {
  Query: {
    users: withAuth((root, args, context, info) => { ... }),
    ...
  }
}

With scope:

import withAuth from 'graphql-auth';

const resolvers = {
  Query: {
    users: withAuth(['users:view'], (root, args, context, info) => { ... }),
    ...
  }
}

With dynamic scope:

import withAuth from 'graphql-auth';

const resolvers = {
  Query: {
    users: withAuth(
      (root, args, context, info) => { /* return scope based on resolver args */ },
      (root, args, context, info) => { ... }),
    ...
  }
}

Contributors

Thanks goes to these wonderful people (emoji key):


artgibson

πŸ’»

HaNdTriX

πŸ’» πŸ“–

Pascal Birchler

πŸ’»

AndrΓ©as Hanss

πŸ’» πŸ“–

This project follows the all-contributors specification. Contributions of any kind welcome!

graphql-auth's People

Contributors

artgibson avatar handtrix avatar kkemple avatar screamz avatar swissspidy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphql-auth's Issues

No license specified

Hi!

I’d love to use this library, but there’s no license specified. Would you mind committing one?

Thanks!

Dynamic CB Not Firing When Hit By Differently Scoped User

Dev setup:

  • graphql-auth version: version "0.2.0"
  • node version: v6.11.1

I am using graphql-auth with:

  • hapi
  • express
  • koa
  • other:

What you did:

I have an endpoint that is using the dynamic scope cb to change the scoped based on the params.

	Mutation: {
		sendMessage: withAuth(
			(obj, { input }, context) => {
				console.log('params input: ', input)
				return input.A ? ["scope:A"] : ["scope:B"];
			}, 
			async (
				obj,
				{ input },
				context
			) => {...code}

I log in to my app as User A with scope A
I hit the above mutation
I see the console log
I receive the correct result
I log out
I log in to my app as User B with scope B
I hit the above mutation
I do not see a console log
I get a permission denied error
I terminate the server process
I start the server process
(I am still logged in with B from the previous session)
I hit the above mutation
I see the console log
I receive the correct result
I log out (with User B)
I log in to my app as User A with scope A
I hit the above mutation
I do not see a console log
I get a permission denied error

What happened:

In my context creation function, the one that puts auth on the context, I can see that the correct scopes are being applied. However, I believe the error has something to do with the dynamic cb being cached or not executed again (because I do not see the console log)

AuthorizationError: Permission Denied!
    at AuthorizationError (/Users/test/workspace/petigree/code/node_modules/graphql-auth/index.js:11:5)
    at /Users/test/workspace/petigree/code/node_modules/graphql-auth/index.js:51:14
    at next (native)
    at step (/Users/test/workspace/petigree/code/node_modules/babel-runtime/helpers/asyncToGenerator.js:17:30)
    at /Users/test/workspace/petigree/code/node_modules/babel-runtime/helpers/asyncToGenerator.js:35:14
    at Promise.F (/Users/test/workspace/petigree/code/node_modules/core-js/library/modules/_export.js:35:28)
    at /Users/test/workspace/petigree/code/node_modules/babel-runtime/helpers/asyncToGenerator.js:14:12
    at /Users/test/workspace/petigree/code/node_modules/graphql-auth/index.js:35:3
    at /Users/test/workspace/petigree/code/node_modules/graphql-tools/src/schemaGenerator.ts:536:22
    at resolveFieldValueOrError (/Users/test/workspace/petigree/code/node_modules/graphql/execution/execute.js:498:12)
    at resolveField (/Users/test/workspace/petigree/code/node_modules/graphql/execution/execute.js:462:16)
    at /Users/test/workspace/petigree/code/node_modules/graphql/execution/execute.js:284:20
    at process._tickCallback (internal/process/next_tick.js:109:7)

library is distributed in raw JS State and generates error

This library is distrbuted in uncompiled state and generates the following error when used:

node_modules/graphql-auth/index.js:1
(function (exports, require, module, __filename, __dirname) { export class ContextError extends Error {
                                                              ^^^^^^

SyntaxError: Unexpected token export
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:139:10)
    at Module._compile (module.js:617:28)

Presumably this can be resolved by implementing

[`@babel/preset-env`, {
    modules: true,
    node: 'current'
}]

But it's generally not recommended to distribute libraries this way.

Error: Cannot find module - fastify-gql

Hi,

I am trying out graphql-auth in a project, though I am getting the following error message after I implement withAuth in a resolver.

[ERROR] 12:26:15 Error: Cannot find module 'babel-runtime/core-js/promise'
Require stack:
- /app/node_modules/graphql-auth/build/index.js
...

I am using fastify-gql in a typescript project, I dont use Babel here.

Any idea on why this is happening?

Thanks!

Support wildcards

Judging by the code, you need to explicitly specify all scopes. But e.g. admins usually have access to all scopes. Would be nice if you could specify shortcuts like that

const scopes = {
    ADMIN: ['*'],
    EDITOR: [
        'user:*',
        'todo:*'
    ],
    ENDUSER: [
        'user:view:self',
        'user:update:self',
        'user:create',
        'todo:*'
    ]
}

withAuth without scope not working

Im trying to integrate this package into an existing graphql express server.

users: withAuth((root, args, context) => { ... }),

gives me an error:

error { TypeError: Cannot read property 'length' of null
    at /.../node_modules/graphql-auth/index.js:42:8
   ...

If I call

users: withAuth([], (root, args, context) => { ... }),

It works ok.

Missing argument for resolver

Dev setup:

  • graphql-auth version: 0.1.2
  • node version: 8.7.0
  • mongoose version: 4.12.1

I am using graphql-auth with:

  • hapi
  • express
  • koa
  • other:

What you did:

I set up a small API with express and mongoose for storage. When running a GraphQL query, I only want to fetch the fields from the database that are actually queried. I rely on the fourth argument passed to a resolver (info) to do this.

See graphql/graphql-js#799 for the arguments a resolver receives.

What happened:

Since withAuth() doesn't pass on the fourth argument to the callback, I cannot do access it (it's undefined).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.