AWS API Gateway: is it possible to include specific request body validation error in the response body? - amazon-web-services

I have an API Gateway POST endpoint that takes in a JSON request body. I have turned on the body request validator and added the request body model. However the error response I'm getting is only some generic message: "message": "Invalid request body" as defined in the Gateway responses. I'm wondering if it is possible to include the specific validation error in the response? In the logs it says specifically
Request body does not match model schema for content type application/json:
[object has missing required properties (["property1","property2",...])]
Is it possible to have something similar to this in the actual response? Thank you.

In Gateway response for error type BAD_REQUEST_BODY error status 400
set Application/json to {"message":$context.error.validationErrorString}
Ref
https://stackoverflow.com/a/48014686

AWS API Gateway will include more details only if the request payload format is valid, but parameters format is invalid:
{
"message": "Missing required request parameters: [p1]"
}
If the request payload is invalid, you will always receive the same message:
{
"message": "Invalid request body"
}
See the bottom of following page:
http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-request-validation-test.html
The only way you can get more details is through logs.
By the way, why do you want to send more details through your API, is it for development and debugging only? If yes, using logs is the way to go. You may have some log processing and storage solution to make your debugging easier (e.g. Splunk, Data Dog, Sumo Logic, etc.)
Otherwise, in general, returning too much of technical details in your API error messages is something to avoid.

Related

AWS API Gateway: Handle both invalid URL and validation errors

I have an API gateway set up with an OpenAPI specification and a proxy lambda integration. Request validation is enabled, and also an authorizer lambda.
Let's say I have endpoints GET /foo and POST /bar. The integrations to these endpoints work well, and the requests are validated and authenticated.
The problem is this:
In order to send back any validation errors when an invalid request is made, e.g. with a missing request body property, I have the following response mapping:
x-amazon-apigateway-gateway-responses:
BAD_REQUEST_BODY:
statusCode: 400
responseTemplates:
application/json: |
{"message": "Invalid request body: $context.error.validationErrorString"}
This also works well. However, if I try to call an endpoint that doesn't exist (e.g. GET /baz), I get a very weird default error message from API gateway. From the past I remember getting a HTTP 403 with something like "missing API key" for invalid URLs, which is weird since it should render a 404, but now I get the even stranger body:
{
"message": "'eyJhbGciOiJSUzI <rest of JWT ...>' not a valid key=value pair (missing equal-sign) in Authorization header: 'Bearer eyJhbGciOiJSUzI <...>"
}
In other words, the JWT I send as my bearer token is passed back in an error message, saying it's not a key=value pair.
Thing is, my authorizer lambda is only connected to the valid endpoints (obviously), so it's not being called. But why is the default built-in API gateway route handler parsing my bearer token and deciding it's not a key=value pair (!)? For an endpoint that doesn't exist? I don't have any {proxy+} endpoint at all.
If I try to map all 403 responses (MISSING_AUTHENTICATION_TOKEN, INVALID_SIGNATURE, etc) to custom error messages, as described here, I get no result, despite docs saying the default response for missing URLs is MISSING_AUTHENTICATION_TOKEN. However, if I also override DEFAULT_4XX, it works, I can return a HTTP 404 with a "Not found" message. The problem is that as soon as I override DEFAULT_4XX, it also overrides my BAD_REQUEST_BODY response so that my validation error messages are lost. Apparently DEFAULT_4XX is not matched last, it takes precedence over BAD_REQUEST_BODY!
How can I set up API gateway so that I at the same time can:
Return 404 NOT FOUND for invalid endpoints such as GET /baz
Return 400 with the $context.error.validationErrorString variable for requests that failed validation
I've found this question that described a similar problem, but surely it's not required to create a {proxy+} integration and/or a dedicated separate lambda only to return a 404 error, this must be possible to achieve by configuration!?
I used the openAPI mock proxy (no lambda) solutions documented here: not a valid key=value pair (missing equal-sign) in Authorization header
It is working very well.

Change response "not a valid key=value pair (missing equal-sign) in Authorization header" in AWS ApiGateway

I've read other similar posts with exact same error message, however my question is different.
I have an AWS ApiGateway in https://XXXXXXXX.execute-api.us-east-1.amazonaws.com/xxxx/users (from now I will call it as /users ).
I have implemented my ApiGateway to Lambda scripts with Cognito authorization, they work without problems, for example:
/users/me -> returns data of current logged user
The problem is when I call an unexistent route in ApiGateway, for example:
/users/mine123 -> it returns
{ "message":
"'my-cognito-user-id-token' not a
valid key=value pair (missing equal-sign) in Authorization header:
'Bearer my-cognito-user-id-token'." }
My question is... Is there a way to return a NotFound or BadRequest error when route in ApiGateway doesn't exist?
I think is possible implementing resource ANY, but, is there a "clean" way to do it without resource ANY?
Edit 1:
I tried Api Gateway response as well. I set a custom response, an status error code 404 for Resource Not Found but Api Gateway still returns 403 Forbidden.
Edit 2
I already have 4XX responses configured too:
And API Gateway always returns 403 error with this message (as expected for a generic 4XX error), however I think it doesn't make sense because is not a real Forbidden error it's a NotFound or BadRequest error.
For example,
A request to nonexistent route in Github API https://api.github.com/ROUTE_THAT_DOESNT_EXIST returns 404 NotFound.
A request to nonexistent route in StackExchange API https://api.stackexchange.com/ROUTE_THAT_DOESNT_EXIST returns 400 BadRequest.
None of them return 403 Forbidden.
Error message { "message": "token not a valid key=value pair Authorization header: 'Bearer token'. is thrown when "Resource path doesn't exist" with status 403 with a response header "x-amzn-ErrorType" = "IncompleteSignatureException"
A request with an "Authorization" header is sent to an API resource
path that doesn't exist.
We can customize response body in 'Gateway Response' section. There doesn't seem to specific Gateway Response like Unauthorized, Invalid Signature, etc for this scenario, Hence we need to configure Default 4XX
We can update status code and Response Templates. Unlike Integration Response on a successful request process, error gateway response template doesn't support full VTL template but only supports simple place holders.
Example configuration for application/json
{"message":"Invalid Resource","type": "$context.error.responseType","stage": "$context.stage"}
Will return
{
"message": "Invalid Resource",
"type": "DEFAULT_4XX",
"stage": "qa"
}
Not sure whether it is a cleaner way than your suggestion, however you can configure specific gateway response for the missing authentication token - https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-gateway-response-using-the-console.html
In the Gateway Responses pane, choose a response type. In this walkthrough, we use Missing Authentication Token (403) as an example.
You can change the API Gateway-generated Status Code to return a different status code that meets your API's requirements. In this example, the customization changes the status code from the default (403) to 404 because this error message occurs when a client calls an unsupported or invalid resource that can be thought of as not found.

Amazon Web Services: How to add test request body for Mime Type application/x-www-form-urlencoded in AWS API Gateway?

I have connected API Gateway to my Lambda function using Post Method execution. The request comes from Form and accordingly shown request data.
In AWS, I gone to Post Method and clicked Test and on bottom i have request body textarea and i tried adding Request body as standard userName=<>&password=<> template but it is not working. When tried using JSON or other format it simply says media type is not supported.
//Request Data
userName=deep&passWord=deep#1234
//Response
{
"message": "Unsupported Media Type"
}
I expect the output as call to Lambda function connected but now it is returning unsupported media type.
Add the header
'Content-Type': 'application/json'
to your request to let the consumer (backend) know in which format your request body is carried. And then you can put the body in JSON format and you should not 415 - Unsupported Media Type.

Api Gateway change default error response format?

When I send request with wrong x-api-key, I get default response as
{
"message": "Forbidden"
}
I can modify error response from lambda if it hits my lambda function. But in this case aws sends default error response.
I have different error format for my endpoint
{
type:"error",
"message":"...",
"status":"...",
"code":403,
...
}
Is there any way to change to above format?
There is a new feature within API gateway where you can define default responses for various errors.
Documention for this feature is over here:
API Gateway Responses

How to bypass header from request into header in response in AWS API Gateway?

I have API Gateway endpoint, which is actually mock endpoint.
What I am trying to do is to make API to take Origin header from request and return the same value in response as Access-Control-Allow-Origin header.
So far I've tried to do the following:
Got to "Method Request" and add "Origin" header to the list
In "Method Execution" I am trying to map Access-Control-Allow-Origin to method.request.header.Origin, but I am getting an error message
Invalid mapping expression specified: Validation Result: warnings : [], errors : [Invalid mapping expression specified: method.request.header.Origin]
Thanks!
integration.request and integration.response only prepare the input to and output from the integration response. Therefore the integration request only supports additional input from the method.request and the integration response only supports additional input from the method response definitions.
Mapping the method.request parameters to method.response is currently not supported but definitely a valid and useful use case. I'll add it to our backlog, but unfortunately cannot commit to a timeline for when we plan on delivering this feature enhancement.
As a workaround, you could pass the Origin header to your integration endpoint which simply mirrors the input and passes it back to API Gateway. This way you should be able to return the value of the Origin request header as an Access-Control-Allow-Origin response header.
Hope this helps,
Jurgen, API Gateway
It can be done by input.param and context.responseOvverride methods
In Integration Response add a Mapping Template for proper Content-Type with a body like this:
#set($origin = $input.params('origin'))
#set($context.responseOverride.header.Access-Control-Allow-Origin = $origin)
It should look like this:
Of course, it can also be added via Cloud Formation and x-amazon-apigateway-integration. Example part of yaml:
x-amazon-apigateway-integration:
responses:
default:
statusCode: "200"
responseTemplates:
application/json: |
#set($origin = $input.params('origin'))
#set($context.responseOverride.header.Access-Control-Allow-Origin = $origin)
Hope that helps.