Slash Lambda Field addGraphQLResolvers not passing JWT

Continuing the discussion from Slash Lambda Fileds addGraphQLResolver missing args:

Overview

In a lambda function, we should be able to run graphql requests either queries or mutations. What we want to do next is to fetch from an API and update one field when we request another field. What we found out while doing this is that while we can do graphql queries and mutations, the JWT token is not being passed along. This results in problems because now we either have to include a hard coded token or remove the auth update rule to allow this to work from a lambda.

There may be another bug here with passing variables to the graphql query/mutation even if the variables are hard coded. I will test again on that point with a simpler example to confirm.
UPDATE: No this was not another bug. We resolved this part I believe.

Schema:

type Contact @auth(
  update: { rule: "{$ROLE: { eq: \"ADMIN\" } }" }
) {
  id: ID
  name: String @search(by: [hash])
  fromAPI: String
  syncAPI: String @lambda
}

# Dgraph.Authorization {"VerificationKey":"My_S3cr3t!","Header":"token","Namespace":"https://my.app.com/claims","Algo":"HS256"}

JWT:

{
  "https://my.app.com/claims": {
    "ROLE": "ADMIN"
  },
  "iat": 1605923890,
  "exp": 1767225600,
  "iss": "myapp",
  "sub": "john.doe"
}

signed:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwczovL215LmFwcC5jb20vY2xhaW1zIjp7IlJPTEUiOiJBRE1JTiJ9LCJpYXQiOjE2MDU5MjM4OTAsImV4cCI6MTc2NzIyNTYwMCwiaXNzIjoibXlhcHAiLCJzdWIiOiJqb2huLmRvZSJ9.A2kpBagmpmI62hYTG-doCk3fxFhSF3PH_qdSo8jdIJI

Add Data

mutation {
  addContact(input: [{
    name: "Qux"
  }]) {
    numUids
    contact {
      id
      name
      fromAPI
    }
  }
}

response:

{
  "data": {
    "addContact": {
      "numUids": 1,
      "contact": [
        {
          "id": "0x7",
          "name": "Qux",
          "fromAPI": null
        }
      ]
    }
  },
  "extensions": {
    "touched_uids": 7,
    "tracing": {
      "version": 1,
      "startTime": "2021-01-14T19:50:52.329356205Z",
      "endTime": "2021-01-14T19:50:52.334463966Z",
      "duration": 5107780,
      "execution": {
        "resolvers": [
          {
            "path": [
              "addContact"
            ],
            "parentType": "Mutation",
            "fieldName": "addContact",
            "returnType": "AddContactPayload",
            "startOffset": 101131,
            "duration": 4979254,
            "dgraph": [
              {
                "label": "mutation",
                "startOffset": 148307,
                "duration": 2474818
              },
              {
                "label": "query",
                "startOffset": 3679377,
                "duration": 1373014
              }
            ]
          }
        ]
      }
    }
  }
}

Update From Slash API Explorer:

passing in the JWT above as the header token

mutation {
  updateContact(input: {
    filter: {
      name:{eq:"Qux"}
    }
    set: {
      fromAPI: "quux"
    }
  }) {
    numUids
    contact {
      id
      name
      fromAPI
    }
  }
}

response:

{
  "data": {
    "updateContact": {
      "numUids": 1,
      "contact": [
        {
          "id": "0x7",
          "name": "Qux",
          "fromAPI": "quux"
        }
      ]
    }
  },
  "extensions": {
    "touched_uids": 9,
    "tracing": {
      "version": 1,
      "startTime": "2021-01-14T20:00:17.206785379Z",
      "endTime": "2021-01-14T20:00:17.211507046Z",
      "duration": 4721686,
      "execution": {
        "resolvers": [
          {
            "path": [
              "updateContact"
            ],
            "parentType": "Mutation",
            "fieldName": "updateContact",
            "returnType": "UpdateContactPayload",
            "startOffset": 96834,
            "duration": 4599594,
            "dgraph": [
              {
                "label": "mutation",
                "startOffset": 217826,
                "duration": 1988950
              },
              {
                "label": "query",
                "startOffset": 3456080,
                "duration": 1206784
              }
            ]
          }
        ]
      }
    }
  }
}

Lambda:

async function syncAPI({graphql}) {
  const response = await graphql(`
    mutation {
      updateContact(input: {
        filter: {
          name:{eq:"Qux"}
        }
        set: {
          fromAPI: "quuz"
        }
      }) {
        numUids
        contact {
          id
          name
          fromAPI
        }
      }
    }
  `);
  return JSON.stringify(response)
}

self.addGraphQLResolvers({
  "Contact.syncAPI": syncAPI
})

Query from Slash API Explorer

query MyQuery {
  queryContact(filter: {name: {eq: "Qux"}}) {
    id
    name
    syncAPI
  }
}

response:

{
  "data": {
    "queryContact": [
      {
        "id": "0x7",
        "name": "Qux",
        "syncAPI": "{\"data\":{\"updateContact\":{\"numUids\":0,\"contact\":[]}},\"extensions\":{\"touched_uids\":2,\"tracing\":{\"version\":1,\"startTime\":\"2021-01-14T20:06:21.767509161Z\",\"endTime\":\"2021-01-14T20:06:21.771172522Z\",\"duration\":3663351,\"execution\":{\"resolvers\":[{\"path\":[\"updateContact\"],\"parentType\":\"Mutation\",\"fieldName\":\"updateContact\",\"returnType\":\"UpdateContactPayload\",\"startOffset\":96515,\"duration\":3551855,\"dgraph\":[{\"label\":\"mutation\",\"startOffset\":131853,\"duration\":1378019},{\"label\":\"query\",\"startOffset\":2541768,\"duration\":1090889}]}]}}}}"
      }
    ]
  },
  "extensions": {
    "touched_uids": 4,
    "tracing": {
      "version": 1,
      "startTime": "2021-01-14T20:06:21.742527393Z",
      "endTime": "2021-01-14T20:06:21.77845642Z",
      "duration": 35929029,
      "execution": {
        "resolvers": [
          {
            "path": [
              "queryContact"
            ],
            "parentType": "Query",
            "fieldName": "queryContact",
            "returnType": "[Contact]",
            "startOffset": 99917,
            "duration": 35803282,
            "dgraph": [
              {
                "label": "query",
                "startOffset": 234199,
                "duration": 1638815
              }
            ]
          }
        ]
      }
    }
  }
}

Notice numUids returned 0. No Contact was updated.

This would only be possible if the JWT was not passed through the lambda script.

Umm… @abhimanyusinghgaur, that is not true in my test case here.

Update: If we change this to be a Lambda Mutation instead of a Lambda Field, then the JWT seems to pass through. We also need the JWT on Lambda Fields though too. Why? In a Lambda Mutation we have to then pass an id of the node, where the Lambda Field already has that id in the parent. So this requires us to do another round trip to the database from the lambda to get the info from the Contact that we will need to send to the API we are working with, hence why we wanted to call it from a field.