serverless: API Gateway WebSocket aws_iam authorizer does not work
This is a Bug Report
Description
-
What went wrong? Specifying authorizer: aws_iam in a websocket event causes deployment to fail
-
What did you expect should have happened? The deployment should have created an APi Gateway websocket with the AWS_AMI authorizer type.
-
What was the config you used?
functions:
# Client connections and disconnections from API Gateway WS
connectionManager:
handler: src/connection.handler
events:
- websocket:
route: $connect
authorizer: aws_iam
- websocket:
route: $disconnect
- What stacktrace or error message from your provider did you see?
The CloudFormation template is invalid: Template error: instance of Fn::GetAtt references undefined resource AwsUnderscoreiamLambdaFunction
It appears to be treating aws_iam as an unknown custom authorizer Lambda function instead of treating it as a special case as in http events.
Similar or dependent issues:
Additional Data
-
Serverless Framework Version you’re using: Serverless Version 1.42.3
-
Operating System: CentOS7
-
Stack Trace:
-
Provider Error messages:
About this issue
- Original URL
- State: open
- Created 5 years ago
- Reactions: 2
- Comments: 16
Friendly FYI for anyone waiting on this to be baked into the code, you can achieve the same effect with some overrides in your serverless.yml resources. I believe the websocket $connect route is always named “SconnectWebsocketsRoute” in the cloudformation, so you can do this in your serverless.yml:
And achieve the equivalent result to the desired
authorizer: aws_iamon the function event websocket $connect route.Some related FYIs:
Authfromaws-amplify, you’d then callAuth.currentCredentials()to get a promise that will return credentials object, thenAuth.essentialCredentials(credentials)to get an object with a set of temporary credentials. Then you’d take your wss:// URL as a string, build an access info object from the temporary credentials and a service info object, and use them with Signer.signUrl, e.g.Signer.signUrl(wssUrl, accessInfo, serviceInfo), to get your signed wss:// URL for use with the WebSockets library of your choice (and can test this URL withwscat -cif desired). YMMV.arn:aws:iam::*:user/*due to an undocumented bug (despite the documentation strongly implying you can do this). I ended up raising an AWS support case to find this out. No timeline for a fix was provided by AWS support.@rudijs, does AWS_IAM authorization work in your case? In my case I see the AWS_IAM in the websocket settings (API Gateway console) but still able to call lambda method without any authorization information. I expect to get 403 in case of the call without auth header.
@DmitryOstapuk The way it works for me is:
This is an example of what I currently have (I’m using typescript and adding in saving the connectionId to dynamodb)
If you try to connect to that using the wss:// endpoint you’ll get a 403 - that’s how it works out of the box.
Then in the front end, the app needs to sign in, I’m using Cognito and Amplify in a React app.
After auth is done, create a signed wss:// endpoint and the websocket client can connect OK.
What I’ve done is experimental so far, just tinkering around with it.
Hope that helps.
I have not got it working yet, but the first weird behavior I see, after editing my API and deploying it as shown above, I am still able to access the WebSocket API without any restriction. To solve this, I needed to manually
Deploythe API again manually from the AWS GUI console, which is totally weird and does not make sense (and therefore it took me 2 days to figure out why I am able to access the API with no 403 error).@rudijs It was very strange thing for me. websocket in AWS console was configured with the AWS_IAM, but
wscat -c "wss://********.execute-api.us-east-2.amazonaws.com/devworked without any signature. But when I created a right signature and repeat wscat with it the previous request without signature start working as expected with 403 error.