Search code examples
aws-lambdaaws-api-gatewaygorillachalice

Authorization Error in API Gateway endpoints using lambda with Chalice code


Here is the scenario:

  • I had a Chalice app with two endpoints /getStream and /deleteStream.
  • I migrated them to Nextjs functions eliminating the need for a Chalice app.
  • So, I deleted the API Gateway but retained the Lambda function for backup.

enter image description here

import re
from urllib import request
from chalice import Chalice, Response
from chalicelib.streamEngine import StreamEngine
app = Chalice(app_name='mux-streaming')

print(app, "chalice app")

#  for testing purpose
@app.route('/', methods=['GET'], cors=True, authorizer=None)
def hello():

    print("hello")
        
    return "hello"


@app.route('/getStream', methods=['POST'], cors=True, authorizer=None)
def get_stream():
    request = app.current_request.json_body
    
    creatorID = request['creatorID']
    streamName = request['streamName']
    streamType = request['streamType']
        
        
    streamer = StreamEngine()
    return streamer.getStream(creatorID, streamName, streamType)
    

@app.route('/deleteStream', methods=['POST'], cors=True)
def delete_stream():
    request = app.current_request.json_body
    
    streamID = request['streamID']
    stream = StreamEngine()
    return stream.deleteStream(streamID)

  • Due to some reason, I want to migrate back to Chalice app but I don't have infra-as-code as it was done by another dev.
  • So, I added an API Gateway from AWS Console.

enter image description here

  • But the API Gateway throws authorization errors:

On GET https://invoke-url/prod:

{
  "message": "Authorization header requires 'Credential' parameter. Authorization header requires 'Signature' parameter. Authorization header requires 'SignedHeaders' parameter. Authorization header requires existence of either a 'X-Amz-Date' or a 'Date' header. Authorization=asdf"
}

which makes no sense as I don't have any authorization whatsoever.

On POST https://invoke-url/prod/getStream:

{
  "headers": {},
  "multiValueHeaders": {},
  "statusCode": 500,
  "body": "{\"Code\":\"InternalServerError\",\"Message\":\"Unknown request.\"}"
}

To make sure API Gateway isn't the imposter, I tried it with other lambdas and it just works fine. Any help will be appreciated. Thanks


Solution

  • I'm not super familiar with Chalice, but based on the information, I think there are a few things going on.

    When you deploy a Chalice app, it generates the infrastructure and API Gateway resources to match the Lambda annotations. Example taken from the Chalice docs:

    $ chalice deploy
    Creating deployment package.
    Creating IAM role: helloworld-dev
    Creating lambda function: helloworld-dev
    Creating Rest API
    Resources deployed:
      - Lambda ARN: arn:aws:lambda:us-west-2:12345:function:helloworld-dev
      - Rest API URL: https://abcd.execute-api.us-west-2.amazonaws.com/api/
    

    So when you brought up the API Gateway via ClickOps, it likely didn't match what the Chalice app would have brought up exactly – such as enabling the Lambda proxy response or JWT authorizers. A good example is the base invocation URL.

    On GET https://invoke-url/prod:

    {"message": "Authorization header requires 'Credential' parameter. Authorization header requires 'Signature' parameter. Authorization header requires 'SignedHeaders' parameter. Authorization header requires existence of either a 'X-Amz-Date' or a 'Date' header. Authorization=asdf"}
    

    (The comment noted that when the Authorization header isn't passed, it gives "Missing Authentication Token".)

    API Gateway returns the response "Auth header requires 'Credential' parameter ..." when an Authentication header is provided at all, even when auth is set to NONE on the resource. It's an AWS bug (which you can read more about here).

    The "Missing Authentication Token" response is when the API request is trying to access an APIGW resource that doesn't exist. You are running a GET command, but there is no GET resource listed on the APIGW console. Once that resource gets created and Authentication is set to NONE, you should be able to hit that.

    On POST https://invoke-url/prod/getStream:

    {  "headers": {},  "multiValueHeaders": {},  "statusCode": 500,  "body": "{\"Code\":\"InternalServerError\",\"Message\":\"Unknownrequest\"}"}```
    

    This looks like a runtime error in Lambda. Are there any logs available in CloudWatch that show a stack trace or error message?