awslabs / aws-mobile-appsync-sdk-js

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

Refused to set unsafe header "host" with IAM auth link #763

Open borgoat opened 5 months ago

borgoat commented 5 months ago

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

I think this is a bug. The only other reference I could find is here: https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/263#issuecomment-461280846

What is the current behavior?

We are using the IAM auth link. The logs are filled with error: Refused to set unsafe header "host". The signature per se works (after all, the "overridden header" is the correct host to begin with, so there's nothing to override), but the mess in the logs causes some troubles with our error tracking.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem.

Our Apollo client is configured as follows:

  const region = 'eu-west-1';
  const url = 'https://gql.mvp-275214716993.yeekatee.com';

  const cognitoAuthLink = createAuthLink({
    url,
    region,
    auth: {
      type: AUTH_TYPE.AMAZON_COGNITO_USER_POOLS,
      jwtToken: async () =>
        (await Auth.currentSession()).getAccessToken().getJwtToken(),
    },
  });

  const iamAuthLink = createAuthLink({
    url,
    region,
    auth: {
      type: AUTH_TYPE.AWS_IAM,
      credentials: () => Auth.currentCredentials(),
    },
  });

  const httpLink = ngHttpLink.create({ uri: url });

  const isAuthenticated$ = () =>
    fromPromise(
      Auth.currentUserPoolUser()
        .then(() => true)
        .catch(() => false),
    );

  const splitAuthLink = new ApolloLink((operation, forward) =>
    isAuthenticated$().flatMap((isAuthenticated) =>
      (isAuthenticated ? cognitoAuthLink : iamAuthLink).request(
        operation,
        forward,
      ),
    ),
  );

  const link = ApolloLink.from([splitAuthLink, httpLink]);

The url is our custom domain on AppSync.^1

What is the expected behavior?

No errors. Maybe we are using this incorrectly and I'm missing something.. I can't quite understand how this could work with Host being a forbidden header.^2

I think the problem is coming from here: https://github.com/awslabs/aws-mobile-appsync-sdk-js/blob/8502a78a5826c39ffaa16881462438392b276cea/packages/aws-appsync-auth-link/src/signer/signer.ts#L235

Since the same request object is created to compute the IAM signature, and then replaced into the Apollo operation context: https://github.com/awslabs/aws-mobile-appsync-sdk-js/blob/82cb58ee5256a0689ec45576b2fae1b83a0bff03/packages/aws-appsync-auth-link/src/auth-link.ts#L103

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

We also use the Cognito auth link - that one does not present any issue.

dependencies:
@apollo/client 3.8.9
apollo-angular 6.0.0
└── @apollo/client 3.8.9 peer
aws-appsync-auth-link 3.0.7
└── @apollo/client 3.8.9 peer

The same error is there on Safari 17.2.1 and Chrome 120, both on macOS 14.2.1