3

So, and after setting the Delete permissions of my Graphcool Comments schema to Authenticated (See image), I'm receiving the above mentioned error (See image) when attempting to delete a post comment.

A user receives a token after signing in as follows:

const Login = React.createClass({
  
  signinUser: function(emailID, passwordID) {

    const email = emailID;
    const password = passwordID;

    this.props.client.mutate({
      mutation: signinUser_Mutation,
      variables: {
        email,
        password,
      },
      options: {
        cachePolicy: 'offline-critical', 
        fetchPolicy: 'cache-first',
      },
    })
    .then(this.updateStateLoginDetails)
    .catch(this.handleSubmitError);
  },

  updateStateLoginDetails: function({data}) {
    localForage.setItem('graphcoolToken', data.signinUser.token);
  },

  handleSubmitError: function(err) {
    console.error(err.message);
  },

  handleSubmit: function(e) {
    e.preventDefault();
    this.signinUser(this.refs.email.value, this.refs.password.value);
    this.refs.loginForm.reset();
    this.refs.email.focus();
  },
  render: function() {

    return (
      <div className="comments">

        <form onSubmit={this.handleSubmit} ref="loginForm" className="comment-form">
          <input type="text" ref="email" placeholder="email"/>
          <input type="text" ref="password" placeholder="password"/>
          <input type="submit" hidden/>
        </form>
      </div>
    );
  }
});

Login.propTypes = {
  client: React.PropTypes.instanceOf(ApolloClient).isRequired,
}
const LoginWithApollo = withApollo(Login);

export default LoginWithApollo;

and the authorisation header is then set in my ApolloClient.js as follows:

const logErrors = {
  applyAfterware({ response }, next) {
    if (!response.ok) {
      response.clone().text().then((bodyText) => {
        console.log('...', `Network Error: ${response.status} (${response.statusText}) - ${bodyText}`);
        next();
      });
    } else {
      response.clone().json().then(({ errors }) => {
        if (errors) {
          console.log('...', 'GraphQL Errors:', errors.map(e => e.message));
        }
        next();
      });
    }
  },
};

// Create WebSocket client
const wsClient = new SubscriptionClient(SubscriptionClient_URL, {
  reconnect: true,
  connectionParams: {
    Authorization: Best way to read in graphcoolToken here?
  }
});

const networkInterface = createNetworkInterface({ 
  uri: networkInterface_URL,
  opts: {
    credentials: 'include',
  }
});

networkInterface.use([{
  async applyMiddleware(req, next) {
    if (!req.options.headers) {
      req.options.headers = {};  // Create the header object if needed.
    }
    
    // get the authentication token from local storage if it exists
    localForage.getItem('graphcoolToken', function (err, value) {
      req.options.headers.Authorization = value ? `Bearer ${value}` : null;

      // This is where next should have been placed
      next();
    });
  
    // next was incorrectly placed here
    next()
  },
}]);

if (process.env.NODE_ENV !== 'production') {
  networkInterface.useAfter([logErrors]);
}

// Extend the network interface with the WebSocket
const networkInterfaceWithSubscriptions = addGraphQLSubscriptions(
  networkInterface,
  wsClient
);

const client = new ApolloClient({
  networkInterface: networkInterfaceWithSubscriptions,
  dataIdFromObject: (o) => o.id,
  addTypeName: true,
  shouldBatch: true,
});

export default client;

The mutation to remove a comment is:

export const Remove_Comment_MutationOLD = gql`
  mutation removeComment ($id: ID!, $cid: ID!) {
    removeFromPostsOnComments (postsPostsId: $id, commentsCommentsId: $cid) {
      postsPosts {
        __typename
        id
        comments {
          __typename
          id
          text
          user
          deleted
          posts {
            __typename
            id
          }
        }
      }
    }

    deleteComments(id: $cid) {
      id
    }
  }
`;

So my question is, after setting the req.options.headers.authorization header, what is the best way to set Authorization in connectionParams, as mentioned in the following article: https://www.graph.cool/forum/t/authentication-issues-with-subscriptions/45/2

enter image description here

enter image description here

enter image description here

TheoG
  • 1,498
  • 4
  • 30
  • 54
  • Those are two different, unrelated questions. The Authorization connection parameter is not used for mutations or queries, only for subscriptions. Can you please inspect the authorization header of the request that corresponds to the mutation with the permission error? Does it contain a valid token for a registered user? – marktani May 28 '17 at 13:40
  • @marktani Yes, and as can be seen by the image I have attached to my original question, the request does indeed contain a valid graphcool_auth_token header. – TheoG May 28 '17 at 16:11
  • The request does not contain a header called `Authorization`. This is needed to authenticate a request. Why do you use the `async` keyword for the middleware? Maybe that's the problem. Here's more information about the middleware: http://dev.apollodata.com/core/network.html#networkInterfaceMiddleware – marktani May 28 '17 at 17:06
  • Here's another example as well: https://github.com/graphcool-examples/react-graphql/blob/master/authentication-with-auth0-and-apollo/src/index.js#L13-L25 – marktani May 28 '17 at 17:07
  • @marktani Turns out my placement of next() was incorrect. It should have been inside ``` localForage.getItem('graphcoolToken', function (err, value) { next() })```, and not outside of it, as I have now shown in my question. Thanks – TheoG May 28 '17 at 18:33

0 Answers0