Custom lambda authorizer for websocket api not working

0

Hi,

I am trying to secure a websocket api using cognito. I created a lambda authorizer following the documentation and forums posts, and I deploy everything using AWS SAM CLI. My template looks like this (I ommited some stuff for clarity).

  AuthDependenciesLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: AuthDependenciesLayer
      ContentUri: auth_dependencies/
      CompatibleRuntimes:
        - python3.12

  AuthFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: !Sub '${AWS::StackName}-auth-fn'
      CodeUri: authorizer/
      Architectures:
        - x86_64
      Environment:
        Variables:
          COGNITO_USER_POOL_ID: !Ref 'CognitoUserPoolId'
          COGNITO_USER_POOL_CLIENT_ID: !Ref 'CognitoUserPoolClientId'
          COGNITO_REGION: !Ref 'AWS::Region'
      Layers:
        - !Ref AuthDependenciesLayer

  AuthPermission:
    Type: AWS::Lambda::Permission
    DependsOn:
      - AuthFunction
      - Api
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref AuthFunction
      Principal: apigateway.amazonaws.com

  Authorizer:
    Type: AWS::ApiGatewayV2::Authorizer
    Properties:
      Name: !Sub '${AWS::StackName}-authorizer'
      ApiId: !Ref Api
      AuthorizerType: REQUEST
      AuthorizerUri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${AuthFunction.Arn}/invocations'
      IdentitySource:
        - route.request.querystring.token

I also make sure my connection function uses the authorizer

      AuthorizationType: CUSTOM
      AuthorizerId: !Ref LambdaAuthorizer

On the console I can clearly see my authorizer being connected to the route. I also tested the lambda with a valid JWT, and it worked as expected. However whenever I try to connect to my websocket using wscat and the correct websocket url (wss://MY_API.execute-api.REGION.amazonaws.com/STAGE/) i can connect without giving a token. No cloudwatch logs are generated either.

Is there something I missed, something not written in the docs or is it a bug ?

I am on a time constraint so I would love the help. Alternatively I can implement the auth logic inside the connect lambda. Thanks a lot

1 Answer
0
  1. Authorizer not triggered on $connect route: For WebSocket APIs, the custom authorizer only runs on the $connect route. Make sure you have explicitly set the AuthorizationType and AuthorizerId on the $connect route. If it's missing or misconfigured, the authorizer won’t be triggered.

  2. route.request.querystring.token not passed in test: When using wscat to connect, you must include the token in the URL query string exactly as defined in IdentitySource. For example:

    wscat -c "wss://MY_API.execute-api.REGION.amazonaws.com/STAGE?token=eyJraWQiOi..."
    

    If the query param is missing or misnamed, the authorizer won't be called and the connection may be allowed.

  3. IAM permissions for InvokeFunction: You have the AWS::Lambda::Permission block set up, but double-check that !Ref AuthFunction is actually resolving to the correct function name and that it includes the full ARN (especially if you're referencing it from another region or stack).

  4. Check deployment and stage configuration: Sometimes changes don’t propagate unless you redeploy both the API and the stage. Try running:

    sam deploy --guided
    

    and ensure the deployment updates are actually applied to the correct stage.

  5. CloudWatch logging not showing anything: This suggests that the authorizer lambda isn't being invoked at all. Reconfirm the $connect route is configured with the authorizer and redeploy. Also, verify that logging is enabled for the WebSocket API stage.

  6. Fallback approach: If you're still running into a wall and are short on time, placing the token verification logic inside the $connect lambda function is a reasonable workaround. You can manually decode and validate the JWT there using a library like python-jose.

profile picture
answered a month ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions