Search code examples
restaws-amplify

Can't set Access-Control-Allow-Credentials header for REST API


I'm having the following issues:

  1. I need to allow CORS only on a specific domain
  2. I need to make sure that secure cookies are sent along with the cross-origin request.

API Gateway specifies '*' as the Access-Control-Allow-Origin header and I need to only allow "example.com".

I found that I can do this by adding the following in override.ts in the rest API resource folder:

import { AmplifyApiRestResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiRestResourceStackTemplate) {
  // Change the default CORS response header Access-Control-Allow-Origin from "'*'" to the API's domain
  resources.restApi.body.paths['/v1'].options['x-amazon-apigateway-integration'].responses.default.responseParameters['method.response.header.Access-Control-Allow-Origin'] = { 
    'Fn::Sub': "'https://www.example.com'" 
  };
}

This seems unreasonably hacky, but whatever.

But I can't seem to solve for the Access-Control-Allow-Credentials header... This doesn't work:

import { AmplifyApiRestResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiRestResourceStackTemplate) {

  // Change the default CORS response header Access-Control-Allow-Origin from "'*'" to the API's domain
  resources.restApi.body.paths['/v1'].options['x-amazon-apigateway-integration'].responses.default.responseParameters['method.response.header.Access-Control-Allow-Origin'] = { 
    'Fn::Sub': "'https://www.example.com'" 
  };

  // ADDING THIS ...

  resources.restApi.body.paths['/v1'].options['x-amazon-apigateway-integration'].responses.default.responseParameters['method.response.header.Access-Control-Allow-Credentials'] = "true";

}

I get multiple errors, but it's basically complaining with this error for each of my REST endpoints:

Unable to put integration response on 'OPTIONS' for resource at path '/oauth/hubspot': Invalid mapping expression specified: Validation Result: warnings : [], errors : [Invalid mapping expression specified: true]

I get similar errors if I try any of the following:

// with quotes inside quotes
  resources.restApi.body.paths['/v1'].options['x-amazon-apigateway-integration'].responses.default.responseParameters['method.response.header.Access-Control-Allow-Credentials'] = "'true'";
// this structure
  resources.restApi.body.paths['/v1'].options['x-amazon-apigateway-integration'].responses.default.responseParameters['method.response.header.Access-Control-Allow-Credentials'] = { 
    'Fn::Sub': "'true'" 
  };

The thing is, I could easily do all this myself if Amplify would just let me override how I handle the OPTIONS request, and send it to my lambda function....


Solution

  • VICTORY!

    I'd still be interested in any suggested approaches, but this worked for me:

    // This file is used to override the REST API resources configuration
    import { AmplifyApiRestResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';
    
    export function override(resources: AmplifyApiRestResourceStackTemplate) {
      delete resources.restApi.body.paths['/v1'].options;
      delete resources.restApi.body.paths['/v1/{proxy+}'].options;
    }
    

    Basically, it's me telling Amplify to get out of the way and let me handle the OPTIONS request myself. So this leaves the "ANY" method on the endpoint so that the OPTIONS request flows through to the LAMBDA that's already configured. I already had the code in there to handle OPTIONS requests, so... It. Just. Worked.