Search code examples
authenticationkeystonejs

KeystoneJS login via GraphQL mutation


I am trying to login to a Keystone 5 GraphQL API. I have setup the app so that I can login via the Admin Console, but I want to login from a Svelte application.

I keep finding references to the code below (I am new to GraphQL) but don't know how to use it.

mutation signin($identity: String, $secret: String) {
  authenticate: authenticateUserWithPassword(email: $identity, password: $secret) {
    item {
      id
    }
  }
}

If I post that query "as is" I get an authentication error, so I must be hitting the correct endpoint.

If I change the code to include my username and password

mutation signin("myusername", "mypassword") {
  authenticate: authenticateUserWithPassword(email: $identity, password: $secret) {
    item {
      id
    }
  }
}

I get a bad request error.

Can anyone tell me how I send username/password credentials correctly in order to log in.

The full code I am sending is this

import { onMount } from 'svelte';
  let users = [];
  onMount(() => {
    fetch("http://localhost:4000/admin/api", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      query: `mutation signin($identity: String, $secret: String) {
  authenticate: authenticateUserWithPassword(email: $identity, password: $secret) {
    item {
      id
    }
  }
}`
    })
  }).then(res => res.json())
    .then(data => {
      console.log(data)
    })
  })

Here is the response I get

{"errors":[{"message":"[passwordAuth:failure] Authentication failed","locations":[{"line":2,"column":3}],"path":["authenticate"],"extensions":{"code":"INTERNAL_SERVER_ERROR","exception":{"stacktrace":["Error: [passwordAuth:failure] Authentication failed","    at ListAuthProvider._authenticateMutation (/Users/simon/development/projects/keystone/meetings-api/node_modules/@keystonejs/keystone/lib/providers/listAuth.js:250:13)"]}},"uid":"ckwqtreql0016z9sl2s81af6w","name":"GraphQLError"}],"data":{"authenticate":null},"extensions":{"tracing":{"version":1,"startTime":"2021-12-03T20:13:44.762Z","endTime":"2021-12-03T20:13:44.926Z","duration":164684813,"execution":{"resolvers":[{"path":["authenticate"],"parentType":"Mutation","fieldName":"authenticateUserWithPassword","returnType":"authenticateUserOutput","startOffset":2469132,"duration":159500839}]}}}}


Solution

  • I found the answer eventually.

    You have to provide an extra object in your body called variables

    variables: {
      var1: "value1",
      var2: "value2"
    }
    

    Those variables will then replace the placehodlers in the query like $var1 or $var2

    Here is the full fetch code that works.

    fetch("http://localhost:4000/admin/api", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          query: `mutation signin($identity: String, $secret: String) {
      authenticate: authenticateUserWithPassword(email: $identity, password: $secret) {
        item {
          id
        }
      }
    }`,
          variables: {
            identity: "myusername",
            secret: "mypassword"
          }
        })
      }).then(res => res.json())
        .then(data => {
          console.log(data)
        })
    
    

    It's a shame that KeystoneJS don't provide any full code examples in their documentation. It would have saved me hours of searching.