I did not set any authorization for the Websocket and it throws INVALID_API_KEY
.
Here's SAM template:
##############################################################
# API GATEWAY: BrokerAuthenticateSocketApi
##############################################################
BrokerAuthenticateSocketApi:
Type: AWS::ApiGatewayV2::Api
Properties:
Name: !Sub "${AWS::StackName}-BrokerAuthenticateSocketApi"
ProtocolType: WEBSOCKET
RouteSelectionExpression: "$request.body.action"
Tags:
'Joba:Product': !Ref Product
'Joba:Environment': !Ref Environment
ApiStage: # Why would we need this: https://medium.com/@TomKeeber/aws-api-gateways-c048cec63046
Type: AWS::ApiGatewayV2::Stage
Properties:
StageName: !Ref ApiStageName
AutoDeploy: true
ApiId: !Ref BrokerAuthenticateSocketApi
AccessLogSettings:
DestinationArn: !GetAtt ApiGatewayAccessLogGroup.Arn
Format: '{"requestTime":"$context.requestTime","requestId":"$context.requestId","routeKey":"$context.routeKey","status":$context.status,"responseLatency":$context.responseLatency,"integrationRequestId":"$context.integration.requestId","functionResponseStatus":"$context.integration.status","integrationLatency":"$context.integration.latency","integrationServiceStatus":"$context.integration.integrationStatus","ip":"$context.identity.sourceIp","userAgent":"$context.identity.userAgent","principalId":"$context.authorizer.principalId","validationErrorString":"$context.error.validationErrorString","integrationErrorMessage":"$context.integrationErrorMessage","errorMessage":"$context.error.message","errorResponseType":"$context.error.responseType"}'
Tags:
'Joba:Product': !Ref Product
'Joba:Environment': !Ref Environment
ApiAuthenticateRoute:
Type: AWS::ApiGatewayV2::Route
Properties:
ApiId: !Ref BrokerAuthenticateSocketApi
RouteKey: authenticate
AuthorizationType: NONE # TODO: change this for Auth0
OperationName: AuthenticateRoute
Target: !Join
- /
- - integrations
- !Ref ApiAuthenticateRouteIntegration
ApiAuthenticateRouteIntegration:
Type: AWS::ApiGatewayV2::Integration
Properties:
ApiId: !Ref BrokerAuthenticateSocketApi
IntegrationType: AWS
IntegrationMethod: POST
IntegrationUri: !Sub "arn:aws:apigateway:${AWS::Region}:states:action/StartExecution"
CredentialsArn: !Sub "${ApiIntegrationStateMachineExecutionRole.Arn}"
TemplateSelectionExpression: \$default
RequestTemplates: # see: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-mapping-template-reference.html
"$default" :
Fn::Sub: >
#set($statesInput='{"data": ' + $input.body + ',"webSocket": {"connectionId": "' + $context.connectionId + '", "domainName": "' + $context.domainName + '"}' + '}')
#set($statesInput=$util.escapeJavaScript($statesInput).replaceAll("\\'","'"))
{
"input": "$statesInput",
"stateMachineArn": "${DownloadBrokerageNotesStateMachine}"
}
ApiAuthenticateRouteResponse: # https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-route-response.html
Type: AWS::ApiGatewayV2::RouteResponse
Properties:
RouteId: !Ref ApiAuthenticateRoute
ApiId: !Ref BrokerAuthenticateSocketApi
RouteResponseKey: $default
ApiAuthenticateRouteIntegrationResponse:
Type: AWS::ApiGatewayV2::IntegrationResponse
Properties:
ApiId: !Ref BrokerAuthenticateSocketApi
IntegrationId: !Ref ApiAuthenticateRouteIntegration
IntegrationResponseKey: $default
ApiIntegrationStateMachineExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Action:
- "sts:AssumeRole"
Effect: Allow
Principal:
Service:
- !Sub apigateway.${AWS::Region}.amazonaws.com
Path: "/"
Policies:
- PolicyName: StateMachineExecutionAccess
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "states:StartExecution"
Resource: !Ref DownloadBrokerageNotesStateMachine
Tags:
- Key: 'Joba:Product'
Value: !Ref Product
- Key: 'Joba:Environment'
Value: !Ref Environment
ApiGatewayAccessLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Join [ "/", [ "joba", "apigateway", !Ref BrokerAuthenticateSocketApi, "access-logs"]]
Using Postman to test, it connects successfully to the websocket:
When I try to send a message (with action=authenticate
as configured in the SAM template), it returns Forbidden
The apigatway log shows INVALID_API_KEY
.
{
"requestTime":"28/Jan/2023:22:32:34 +0000",
"requestId":"feZUdEH2oAMFe9A=",
"routeKey":"-",
"status":403,
"responseLatency":-,
"integrationRequestId":"-",
"functionResponseStatus":"-",
"integrationLatency":"-",
"integrationServiceStatus":"-",
"userAgent":"-","principalId":"-",
"validationErrorString":"-",
"integrationErrorMessage":"-",
"errorMessage":"Forbidden",
"errorResponseType":"INVALID_API_KEY"
}
In no section of the SAM template, I specified Authorization. In fact, I specified AuthorizationType: NONE
in the AWS::ApiGatewayV2::Route
.
What's wrong with my configuration?
It was really hard to find the error, but I did. A rather silly mistake, but not fully understood why it has to be like this.