I'm trying to configure API Gateway in AWS to receive webhooks from the Adyen platform.
I used API gateway integration with an S3 bucket and created an API, using the following link
https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html
The authentication is "none" in my configuration, however i'm observing error related to authorization.
Since i'm new to APIs, I couldn't understand this.
The webhook is an HTTP post method
{
"live": "false",
"notificationItems": [
{
"NotificationRequestItem": {
"amount": {
"currency": "EUR",
"value": 0
},
"eventCode": "REPORT_AVAILABLE",
"eventDate": "2022-11-22T15:19:37+01:00",
"merchantAccountCode": "COM",
"merchantReference": "testMerchantRef1",
"pspReference": "1OW4XY4YXEFDLM0F",
"reason": "will contain the URL to the report",
"success": "true"
}
}
]
}
The response I received is
{"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=Basic amFnYTYxOTBAZ21haWwuY29tOndJTERGSVJFQDEyMw=="}
Amazon API Gateway Configuration
enter image description here
According to the official documentation the particular error you are receiving indicates that you are trying to invoke a non-existing resource. In particular, the root cause is
A request with an "Authorization" header is sent to an API resource
path that doesn't exist.
Are you sure that you have published your API properly?
Related
I have set up API Gateway using HTTP API which is configured to a private application load balancer using a VPC link.
I have a route using this integration and I can request my route and I get a successful response from my API.
The problem comes though when I now want to protect this route.
I chose a simple lambda authoriser and set up a basic example I have seen in many tuts being:
exports.handler = async(event, context) => {
let response = {
"isAuthorized": false,
"context": {
"AuthInfo": "defaultdeny"
}
};
if (event.headers.authorization === "Bearer secretToken") {
response = {
"isAuthorized": true,
"context": {
"AuthInfo": "Customer1"
}
};
}
return response;
};
When I attach my authoriser I just get:
{
"statusCode": 401,
"error": "Unauthorized",
"message": "Invalid token."
}
this response does not seem to be coming from the authoriser as in cloud watch I can see the authoriser is returning true.
I am not sure if because I am accessing a private resource using an integration with a VPC link if there is something else I need to do, or what I am missing.
I am struggling to find any documentation on authorisers in such a scenario.
Any help most appreciated.
Authoriser settings
My Api was Strapi CMS, with Strapi if you pass an authorization header to the endpoint even a public one (as I was) then its own authentication kicks in.
So as the header was passed from the lambda authoriser to Strapi, Strapis auth kicked in. Many thanks to #stijndepestel
Is it possible to delete the message in the response?
{
"message": "PERMISSION_DENIED: The API targeted by this request is invalid for the given API key.",
"code": 403
}
I prefer not to expose information to users. In this particular case a 403 http error would be enough.
Is it possible to access response headers in API Gateway Access Logs? I am wanting to log a Header in my response Changes for Audit Logging Purposes, so I display a message for each Action as to what effect that Action.
My Current Log Format looks like:
{
"path": "$context.path",
"requestTime": "$context.requestTime",
"username": "$context.authorizer.username",
"email": "$context.authorizer.email"
"requestId": "$context.requestId",
"status": "$context.status",
"httpMethod": "$context.httpMethod",
"ip": "$context.identity.sourceIp",
"changes": "$$$TODO$$$"
}
In $$$TODO$$$ I have tried all sorts of expressions, to no avail, I imagine this might not be possible in the Custom Access Logging and that is my problem and I just don't know it, and I'll be forced to process the more verbose logs. Currently I am sending only these fields to an Elasticsearch cluster which is working nicely, but I'm worried with this new requirement I will have to change to the normal API gateway logs, and then do more filtering and processing with potentially a custom Lambda function.
UPDATE: I just noticed in the CloudWatch logs, that the content type has somehow mutated from application/json to text/plain. Here is what the WebHost string looks like now:
[Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting POST https://snip.execute-api.us-west-2.amazonaws.com/Stage/api/Clinician text/plain
This is what it looked like when the call was working:
[Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting POST https://snip.execute-api.us-west-2.amazonaws.com/Stage/api/Clinician application/json
And yet, the header in Postman sets Content-Type: application/json
So why is the content type changing?
Beginning of original post:
I'm developing an API Gateway Lambda Function using Visual Studio 2017 "Serverless Application with Test" blueprint which is a .NET CORE solution. We are using Cognito User Pools for authentication. I am using Postman to test my first function. I'm passing a valid ID Token for a User in a Cognito User Pool. The request passes authentication but responds with a 415 Unsupported Media Type.
Before I started passing an ID Token, I was using AWS_IAM authorizer. At that time, the body (content-type: application/json) would map to the POST parameter successfully. But now that I am using the Cognito User Pool authorizer, I get a 415 Unsupported Media Type when calling POST. The POST method signature is:
[HttpPost]
public APIGatewayProxyResponse Post([FromBody]Clinician user)
The sample data I am sending in the body is:
{
"Id": "",
"Username": "6punk",
"Title": "Punker",
"FirstName": "Six",
"MIddleName": "",
"LastName": "Punk",
"Suffix": "",
"PreferredFirstName": "",
"PreferredLastName": "",
"Email": "bogus#email.com",
"Phone": "+18015551206",
"UserSub": "",
"ClinicianTypeId": "1",
"EhrId": ""
}
As already mentioned, when authenticating as an IAM user or when testing via the Method Test pane in the API Gateway Console, the JSON maps perfectly to the Clinician class.
I have CORS enabled.
For the ANY method, I have the Integration Request type set to LAMBDA_PROXY.
Any ideas what is causing the 415 Unsupported Media Type when testing my POST method from Postman with an ID Token from a Cognito User?
As it turns out, it was a bug in Postman. Even though I had specified the Content-type as application/json, it was passing the content type as text/plain. I deleted the Content-Type header and then recreated it and things started working. I had had Postman up for several days. I don't know for certain why it started passing text/plain. All I know is that when I deleted and recreated the Content-Type header as application/json, only then did things start working again.
According to the AWS docs, models in API Gateway support JSON Schema syntax, however, they export as Swagger OpenAPI specs, where Swagger specification does not fully support many valid JSON Schema structures.
I would like my API Gateway model to have a set of optional text fields, e.g., message, but when defined as
{
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
and with body validation enabled, it rejects this model when message is an empty string, or missing. It does that even though message is not included in the list of required fields
"required": [
"message"
],
Digging around, I found that to allow empty/null string values, one must add a null type to the list of property types, e.g.:
{
"type": ["null", "string"]
}
This, however, still does not work with API Gateway, nor it properly exports as a Swagger spec YAML.
Is there any way to solve this with API Gateway and Swagger?
As mentioned by Helen, Swagger does not support multiple types nor null as a type. The will probably prevent your first approach from working with swagger import/export.
However, the internal API Gateway model support does use JSON Schema and may work even though import/export doesn't. I suggest you try entering your model via the API Gateway console or via the API Gateway CLI.