awslabs / aws-mobile-appsync-sdk-js

JavaScript library files for Offline, Sync, Sigv4. includes support for React Native
Apache License 2.0
917 stars 265 forks source link

IncompleteSignatureException using IAM auth #702

Open Darbiol opened 2 years ago

Darbiol commented 2 years ago

Note: If your issue/feature-request/question is regarding the AWS AppSync service, please log it in the official AWS AppSync forum

Do you want to request a feature or report a bug? bug?

Which versions and which environment (browser, react-native, nodejs) / OS are affected by this issue? Did this work in previous versions? react

Issue: I'm setting up an unAuth request using AWS_IAM with AWSAppSyncClient and react-apollo but i'm getting this response.

{
  "errors" : [ {
    "errorType" : "IncompleteSignatureException",
    "message" : "'accept' is named as a SignedHeader, but it does not exist in the HTTP request."
  } ]
}

Packages used:

Setup:

import Auth from '@aws-amplify/auth'
import AWSAppSyncClient from 'aws-appsync'
import { AUTH_TYPE } from 'aws-appsync/lib'
import { API_URL } from './api-url'

export const getClient = async () => {
  return new AWSAppSyncClient({
    url: API_URL,
    region: process.env.aws_s3_region,
    auth: {
      type: AUTH_TYPE.AWS_IAM,
      credentials: () => Auth.currentCredentials(),
    },
    complexObjectsCredentials: () => Auth.currentCredentials(),
    disableOffline: true,
  })
}

where we call the setup:

async componentDidMount() {
    const apollo = await getClient()
    this.setState({
      client: apollo,
    })
    ...
}

render() {
    const { client } = this.state
    ...
    return (
      <ApolloProvider client={client}>
        <ApolloHookProvider client={client}>{childrenWithProps}</ApolloHookProvider>
      </ApolloProvider>
    )
 }

Where its being used:

const variables = {
    Id: '1234'
}
useEffect(() => {
    async function doThis() {
      try {
        const res = await client.query({
          query: GET_QUERY,
          variables,
          fetchPolicy: 'network-only',
        })
      } catch (error) {
        console.log('error', error)
      }
    }
    doThis()
  }, [userData]);

Note: I've already setup Appsync to accept unauth request, also setup the unauth Identity and added the @aws_iam directive to my appsync schema.

this is the request being sent

:authority: <Host>
:method: POST
:path: /graphql
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
authorization: AWS4-HMAC-SHA256 Credential=<AccessKeyId>/20220121/eu-central-1/appsync/aws4_request, SignedHeaders=accept;content-type;host;x-amz-date;x-amz-security-token, Signature=<Signature>
cache-control: no-cache
content-length: 374
content-type: application/json; charset=UTF-8
origin: http://localhost:3001
pragma: no-cache
referer: http://localhost:3001/
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
x-amz-date: 20220121T000606Z
x-amz-security-token: <session_token>
x-amz-user-agent: aws-amplify/2.0.7

from what i understand from the error it's sending adding accept as a signed header but accept is not included in the calculation of the signature? is there a way we can remove the accept from SignedHeaders in the authorization?

popperur commented 2 years ago

I had the same issue, got

'accept' is named as a SignedHeader, but it does not exist in the HTTP request.

It turned out I used the wrong URL for the connection. In my case, the good URL looked like

https://jr6rvrdasnehzdkg7dtraihflq.appsync-api.us-east-1.amazonaws.com/graphql