JWT Doesn't seem to be passed into Lambda graphql() query for lambda mutations

I am aware that dgraph-lambda supposedly passes the JWT through into the graphql() calls. This doesn’t seem to be happening for me, and I can’t find in the dgraph-lambda source code where it passes through the JWT.

Here’s my situation:

  • I’ve tried this on Lambda Mutations, Queries and Fields. None of them seem to work
  • I’m able to run queries in API Explorer, Postman, HTTP Requests with @auth rules just fine by passing a JWT with the auth header I set in the schema.
  • When I try to run the same GraphQL query within a lambda (still passing in the exact same JWT) the return value from the query is exactly what I expect it to be if there is no JWT passed in (an empty array)
  • I have verified that the query runs just fine inside the lambda if I remove the @auth rule and also runs just fine using DQL (which I don’t want to use because I want to use auth.

Does anyone have any insight into what might be happening, or could you even point me toward where in the dgraph-lambda library the JWT is actually attached to the event?

It’s an extremely simple query I’m testing it on, and as I said it works just fine outside of a lambda:

async function myLambdaThatDoesntWork ({ graphql }) {
  const gqlQuery = `
    query {
      queryGroup {
        groupCode
      }
    }
  `
  const results = await graphql(gqlQuery)
  const allGroupCodes = results?.data?.queryGroup?.map(g => g.groupCode)

  console.log('allGroupCodes: ', allGroupCodes)
  // output with no auth rule (or doing it with dql): [code1, code2, ...]
  // output WITH auth rule: []
  
  return allGroupCodes
}

self.addGraphQLResolvers({
  "Mutation.myLambdaThatDoesntWork": myLambdaThatDoesntWork,
});
1 Like

https://github.com/dgraph-io/dgraph-lambda/search?q=header&type=

1 Like

I appreciate the reply. Sorry, I must not have been clear. I can see where it’s passing the authHeader in to the graphql function, but I’m not seeing where the authHeader is being attached to the event in the first place (because that’s what is being passed into the function).

Does anyone have a working example of a Lambda Mutation they could share? I wonder if there’s some sort of enforcement of a specific auth header that must be used (‘X-Auth-Token’, etc).

I hope to shed a bit more light on this because I have the same question.

From what I can tell (I’m not fluent in Go):

  1. as part of parsing the Dgraph GraphQL directives on input schema, customAndLambdaMappings will convert that @lambda to a @custom directive at the appropriate /graphql-worker (or whatever configured) endpoint.
  2. as part of resolving a @custom http request, rewriteAndExecute will build a POST body for said endpoint using GetBodyForLambda. Here we see that the authHeader property gets set just as I’d expect, pulling the key from the parsed Dgraph.Authorization.

So, I’m sure I skipped a few steps, but it sure seems like Dgraph is in fact sending along authHeader appropriately as part of the POST body. (I didn’t go down the auth rabbit hole, so I suppose it’s possible parsing isn’t working.)

In Dgraph Lambda, pretty quickly it seems there’s an issue.

  1. scriptToExpress does what it says it’s going to do: convert a file into an express app.
  2. To do so, it compiles the script for execution in a Node VM context and passes data in via listening and triggering events via evaluateScript. evaluateScript returns a function that accepts an event object, which should include an authHeader property, among other things. It plucks off authHeader from the event and drops it into graphql.
  3. To convert the POST body from Dgraph into an event object, bodyToEvent does some quick mapping of JSON-parsed body data into a JS object. It does not add any authHeader.

As far as I can tell, this is the only means for getting data from the original POST to /graphql-worker into the lambda. This means the event object will never have a JWT attached.

Are we missing something? How is evaluateScript ever going to pass in an authHeader that is anything other than undefined? Please be gentle, I don’t know what I’m doing :sweat_smile:

2 Likes

I just posted a question which is somewhat related to this.

So are the lambda queries and mutations run without any auth ?

Although my question was different that I wanted to run the mutation within Lambda not with the same auth that is passed.

cc @gja

Couple of things

  1. We were not correctly passing authHeaders to lambdas. This has been fixed as of 48 hours ago. Please update your lambda script to see these changes. Yes, the bug is exactly what @chrisshaw mentioned’ bodyToEvent wasn’t passing the authHeader. I wish i’d seen this discuss post before implementing the fix, it would have made debugging this much easier.

  2. graphql will automatically pass along the authHeader, so the security context is the same. However, you can override the security context by passing in the authHeaders explicitly. Before the above bug was fixed, this behaved as an unauthenticated request, so you would not have gotten back any data.

  3. dql does not honour @auth headers, and thus a dql query can bypass auth rules written for GrapQL. Please consider this while writing your dql queries. (ACLs offers a way to potentially lock down dql queries as well, but GraphQL clients would also need to log in for ACLs to work)

1 Like