Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authentication/Authorization/Bussiness logic #11

Open
matuscongrady opened this issue Jun 22, 2017 · 4 comments
Open

Authentication/Authorization/Bussiness logic #11

matuscongrady opened this issue Jun 22, 2017 · 4 comments

Comments

@matuscongrady
Copy link

Hello,

I like how easy it is to get a working GraphQL backend-data service with this project.
I'd like to test this on a small production project, but before I do, I'd like to find a way to solve some common issues:

1. Authentication
I guess this could be implemented as an express (connect-type) authentication middleware, that would first read JWT, make a dgraph query for a user, and then put authenticated user to the graphql context.

2. Authorization
Let's say we have an authenticated user (and his role) in a graphql context. How would I restrict certain users from reading/manipulating data that should be restricted to them?
I know I can make my own mutations/queries with custom logic, but I would loose all the nice features of the auto-generated queries/mutations.

3. Bussiness logic
Let's say I wan't to send an email after creating a user (after performing a createUser mutation). Where would I put this "send email" logic?

I really have no clue how I would solve this. Maybe some kind to extend some of the auto-generated queries/mutations with custom "hooks"?

Thanks for any suggestion or answer!

@dpeek
Copy link
Owner

dpeek commented Jun 26, 2017

Hi @ugros,

These are all things that I want to tackle at some point, I don't have clearly defined solutions yet but I can at least give you an idea. It seems like the project could eventually become a kind of self hosted Graph.cool or Scaphold.io, so when in doubt I'm more than happy to follow in their very clever foot steps!

  1. Authentication
    We provide a built in type User type and provide a hook to map from a request (bearer token, cookie or other) to the id of the current User. I'd like a solution that easily portable as I'm also deploying to AWS/Lambda/API Gateway (https://github.com/dpeek/dgraphql-serverless)

  2. Authorization
    Graph.cool (and Facebook) use permission queries which seem like a flexible solution to authorization in general without having to define custom business logic for each use-case.

  3. Business Logic
    The basic idea here is to create a request pipeline for mutations that would allow the execution of code at various stages of a mutation (validation, pre-commit, post-commit). In a single DgraphQL server these could just be callbacks provided to the context. In something larger it would be great to delegate to external services (lambda, existing APIs, etc).

Unfortunately I can't tell you when any of this will get done – this isn't my day job! But know that I'm very open to suggestions, pull requests and discussion!

@matuscongrady
Copy link
Author

matuscongrady commented Jun 30, 2017

Hello, @dpeek, thanks for the answer!

We provide a built in type User type and provide a hook to map from a request (bearer token, cookie or other) to the id of the current User

I don't think I understand. Is this already implemented?

I currently don't have time to analyze the code, and make a reasonable pull request, so I'll atleast suggest a dgraphQL API I would like to see :)

Hook API:

import { mutationHook, resolverHook } from 'dgraphql'

mutationHook('<<MUTATION_NAME>>', ' << before / after >>' () => { action(); }
resolverHook('<<ENTITY_NAME>>', ' << before / after >>' () => { action(); }

Basically, schema/mutation would be still generated from schema string.
To modify behavior (add hooks), a simple JS API would be available.

Parameters for hooks:
Query/Mutation params supplied from the request,
GraphQL context
Result (only for 'after' hook)

Hook should return either:

  1. (possibly modified) result
  2. { error: 'Error text', ...additionalParams } (Basically, any object with 'error' or '_error' property would be interpreted as a GraphQL error, and it's message or 'error' value would be returned to the client as common graphQL error
  3. (only an idea) If hook returns a falsy value (undefined, null or false), common GraphQL error with error code 500 should be sent to the client

Currently, the schema (type string) is supplied to DgraphQL client.
I can imagine 2 possibilities how to register hooks into it:

import { createSchema, Client } from 'dgraphql'

const schema  = createSchema('<<SCHEMA_STRING>>')
schema.mutationHook(...params);
schema.resolverHook(...params);

const client = new Client({
  server: 'http://localhost:8080/query',
  schema: schema,
  debug: false
})

import { Client, mutationHook, resolverHook } from 'dgraphql'

const hook1 = mutationHook(...params);
const hook2 = resolverHook(...params);

const client = new Client({
  server: 'http://localhost:8080/query',
  schema: schema,
  hooks: [hook1, hook2, ...] // an array of 'hook' type objects
  debug: false
})

Other things (like parsing bearer token and autoinjecting current user to the context) seem like a lot of work, but hopefully hooks wouldn't be so much work for you and this would allow us to solve majority of the problems above (at least to some degree).

Anyway, thanks for the great work so far. I've analyzed a lot of graphQL projects/starter kits and this one is as close to what I'd ultimately want to work with as possible. ;)

@MichelDiz
Copy link

Could be a JWT verification between the mutations and the queries. And some API gateway take care of craft of create the tokens.

@nikolakanacki
Copy link

If we're talking about ACL in general, mentioning Graph.cool service, one has to look no further than their "permission queries". Those things are so powerful there is basically nothing you can't do with them. Would like to hear what others think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants