graphql-request icon indicating copy to clipboard operation
graphql-request copied to clipboard

Add `requestFormatter` option to allow for signed request support for AWS AppSync / API Gateway

Open DavidWells opened this issue 5 years ago • 3 comments

AWS API gateway & Appsync require each request to be signed via aws sig v4. This signing can't happen up front because the request body (aka query) must be also be included as part of the signing.

TLDR; This PR adds a generic requestFormatter option to allow me manipulation of the request, in this case signing the request, before it is sent.

Example usage:

import { GraphQLClient } from 'graphql-request'

// Async or sync function to get current AWS Cognito creds for request signing
const getCreds = async function() {
  return {
    accessKeyId: '123',
    secretAccessKey: '456',
    sessionToken: '789',
  }
}

// Client with requestFormatter to manipulate payload right before fetch is called
const client = new GraphQLClient(ctx.url, {
  /* Custom function for signing request */
  requestFormatter: async function (payload) {
    /* Get current user creds for API call */
    const credentials = await getCreds()
  
    const { accessKeyId, secretAccessKey, sessionToken } = credentials
    if (!accessKeyId || !secretAccessKey) {
      throw new Error('Not authenticated')
    }
  
      /* Sign the request with aws4 */
    const signedRequest = aws4.sign(payload, {
      accessKeyId,
      secretAccessKey,
      sessionToken
    })
    /* Return request signed request */
    return signedRequest
  }
})

// Now each request is properly signed 
await client.request(`{ me { id } }`)

I've added tests along with this PR. Note: the aws4 is only used in the test as a dev dependency. Happy to remove it as a dev dep if ya'll want a different testing setup.

DavidWells avatar Sep 29 '20 04:09 DavidWells

It's possible that is could also be solved by custom fetch proposed here: https://github.com/prisma-labs/graphql-request/pull/212

I'd prefer to provide a simple function instead of patching & providing my own fetch though 😃

DavidWells avatar Sep 29 '20 17:09 DavidWells

@DavidWells you mentioned the use a custom fetch. It looks like aws4fetch might be perfect for this.

ctrlplusb avatar Jul 02 '21 13:07 ctrlplusb

Also across the same topic, is there any update on this PR?

ls-jingbo-jin avatar Aug 30 '22 07:08 ls-jingbo-jin