rubyonjets/jets

Error when using Authenticators and CORS is enabled

Closed this issue · 2 comments

Checklist

  • Upgrade Jets: Are you using the latest version of Jets? This allows Jets to fix issues fast. There's a jets upgrade command that makes this a simple task. There's also an Upgrading Guide: http://rubyonjets.com/docs/upgrading/
  • Reproducibility: Are you reporting a bug others will be able to reproduce and not asking a question. If you're unsure or want to ask a question, do so on https://community.rubyonjets.com
  • Code sample: Have you put together a code sample to reproduce the issue and make it available? Code samples help speed up fixes dramatically. If it's an easily reproducible issue, then code samples are not needed. If you're unsure, please include a code sample.

My Environment

Software Version
Operating System OSX
Jets 2.3.15
Ruby 2.5.5

Expected Behaviour

I have declared authenticators for individual routes in routes.rb and have CORS enabled in application.rb. The CloudFormation generated for the corresponding API Gateway Methods should set the AuthorizationType and AuthenticatorId for the methods bound to routes with authenticators.

With CORS enabled an extra api gateway method get generated, with *Cors* in the name (e.g. PersonsPersonIdCorsApiMethod). This method should have both the AuthoriztaionType and AuthenticationId set.

If CORS is disabled everything is fine.

Current Behavior

Currently, when CORS is enabled the extra *Cors* api gateway methods set the AuthorizationType, but not the AuthenticationId. This result in a CloudFormation error during deployment stating that an Authenticator must be provided.

Step-by-step reproduction instructions

Code Sample

appication.rb

config.cors = true

routes.rb

get    'persons/:person_id', to: 'persons#show', authorizer: "client#cognito_authorizer"

Excerpt from the generated CloudFormation code, after doing a jet build. Notice that the first method has both AuthorizationType and AuthorizerId, but the second *Cors* method is missing the AuthorizerId.

 PersonsPersonIdShowGetApiMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      ResourceId: !Ref PersonsPersonIdApiResource
      RestApiId: !Ref RestApi
      HttpMethod: GET
      RequestParameters: {}
      AuthorizationType: COGNITO_USER_POOLS
      ApiKeyRequired: 'false'
      Integration:
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ShowLambdaFunction.Arn}/invocations
      MethodResponses: []
      AuthorizerId: !Ref ClientCognitoClientAuthorizerAuthorizer
  PersonsPersonIdCorsApiMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      ResourceId: !Ref PersonsPersonIdApiResource
      RestApiId: !Ref RestApi
      AuthorizationType: cognito_user_pools
      HttpMethod: OPTIONS
      MethodResponses:
      - StatusCode: '200'
        ResponseParameters:
          method.response.header.access-control-allow-origin: 'true'
          method.response.header.access-control-allow-credentials: 'true'
          method.response.header.access-control-allow-methods: 'true'
          method.response.header.access-control-allow-headers: 'true'
        ResponseModels: {}
      RequestParameters: {}
      Integration:
        Type: MOCK
        RequestTemplates:
          application/json: "{statusCode:200}"
        IntegrationResponses:
        - StatusCode: '200'
          ResponseParameters:
            method.response.header.access-control-allow-origin: "'*'"
            method.response.header.access-control-allow-credentials: "'true'"
            method.response.header.access-control-allow-methods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
            method.response.header.access-control-allow-headers: "'Content-Type,X-Amz-Date,Authorization,Auth,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'"
          ResponseTemplates:
            application/json: ''

Solution Suggestion

When generating the *Cors* api gateway methods (e.g. PersonsPersonIdCorsApiMethod), the AuthentiatorId should also be set.

Can confirm that i am facing the same issue.

https://github.com/tongueroo/jets/blob/7b4dd59527f70188d9d111ad330837dff16403b3/lib/jets/resource/api_gateway/cors.rb#L54

Apparently, the default cors_authorization_type config is nil, which then resolves to the route's authorization type. Managed to work around the issue by setting:
config.api.cors_authorization_type = "NONE"

pgib commented

@bolstycjw Thank you for this tip!