15

Facebook does not mention authentication for their GraphQL library.

Suppose I have a users table fetchable from GraphQL and I do not wish to disclose users information to anybody who demands it except the logged in user, at what level should I add the authentication layer ?

At the schema level by mutating a "logged-in" state ?

Or maybe by passing extra parameters to the graphql function that currently takes only query and schema ?

jonathancardoso
  • 9,319
  • 6
  • 49
  • 63
Lyes BEN
  • 940
  • 4
  • 13

5 Answers5

11

It's possible to add auth header with token to your GraphQL queries.

var token = localStorage.getItem('id_token');

Relay.injectNetworkLayer(
  new Relay.DefaultNetworkLayer('http://pathtohost/graphql', {
    headers: {
      Authorization: token
    }
  })
);
Tom Craft
  • 161
  • 4
3

This blog post https://medium.com/the-graphqlhub/graphql-and-authentication-b73aed34bbeb#.cpmrcqcyt describes 3 types of authentication with Relay.

1 - based on a token (https://stackoverflow.com/a/34843562/2628278) - This one scales better \o/

2 - based on rootValue (https://stackoverflow.com/a/36001558/2628278)

3 - based only in Relay and GraphQL

The problem with the first two approaches is that you need to use non-relay/graphql code to handle this.

The third approach is like this:

{
  viewer(token: String) {
    name
  }
}

pass the auth token to viewer, and let graphql handles it

you will need a mutation as well:

mutation {
  createToken(username: String!, password: String!) {
    token
    error
  }
}

that will return the token or an error. The token should be stored in a cookie or local storage on web, and on AsyncStorage on React Native

Sibelius Seraphini
  • 4,023
  • 7
  • 30
  • 52
1

Although it's really unclear in the documentation, in addition to schema and query (or requestString as it's called in the docs), you can also pass a rootValue. That value will be passed to every resolve function in your GraphQL schema, so it's where you want to put any authentication information that is paired with the request.

For example if you call graphql with:

graphql(schema, query, auth, variables)

In your resolve functions you'll have access to auth:

async user(auth, args) {
  return await db.users.find(auth, args.id)
}
jkettmann
  • 609
  • 6
  • 12
Ian Storm Taylor
  • 7,530
  • 10
  • 45
  • 69
1

Another option is to use a Relay Network Layer other than the Default one, such as nodkz/react-relay-network-layer.

This network layer support middlewares, and you can inject an authMiddleware to specify the Auth Token for each Relay request. You can also specify what to do if the server fails to authorize the request (i.e. send user to the login screen). See an example of how you can set it up:

import { RelayNetworkLayer, urlMiddleware, authMiddleware } from 'react-relay-network-layer';

const middlewares = [
  urlMiddleware({
    url: () => `${graphqlAPIHost}/dragon/v2/graph`
  }),
  authMiddleware({
    token: () => auth.accessToken(), // Here you retrieve the Auth Access Token
    tokenRefreshPromise: (req) => {
      loginActions.logout(); // Here you specify what to do if the server returns 401
      return req;
    }
  })
];
Relay.injectNetworkLayer(new RelayNetworkLayer(middlewares, { disableBatchQuery: true }));

This will send the auth token in the request headers. For more information visit the nodkz/react-relay-network-layer github page.

Jose R. Cruz
  • 889
  • 1
  • 9
  • 15
0

So, On the server side you can check this repo I've created showing how to handle login/logout using GraphQL mutations: https://github.com/shalkam/graphql-login

It's using passport.js for auth.

Shalkam
  • 593
  • 4
  • 10