Hello: I've been following two tutorials in the AWS documentation:
creating the sample pet store API (https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-from-example.html)
...and creating an API key (https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-setup-api-key-with-console.html#api-gateway-usage-plan-create-apikey).
When I test the pet store get method with the provided URL, it returns:
Welcome to your Pet Store API You have successfully deployed your
first API. You are seeing this HTML page because the GET method to the
root resource of your API returns this content as a Mock integration.
The Pet Store API contains the /pets and /pets/{petId} resources. By
making a GET request to /pets you can retrieve a list of Pets in your
API. If you are looking for a specific pet, for example the pet with
ID 1, you can make a GET request to /pets/1.
You can use a REST client such as Postman to test the POST methods in
your API to create a new pet. Use the sample body below to send the
POST request:
{
"type" : "cat",
"price" : 123.11 }
Now I go to the API Gateway -> API -> Resources -> -> Method Request -> API Key Required and change it to "True" and redeploy.
When I go to the provided URL to test, now the page returns:
{"message":"Forbidden"}
Which makes sense... I told it API required = true, right?
So my question is, how do I pass the API key? So that I don't get the "forbidden" result? I didn't see that in the tutorial links I pasted above and haven't been able to find elsewhere.
You Create a Usage Plans
Attach this usage plan to your API and Stage
Create an API Key
Now invoke your API with header named x-api-key and value of it is the API Key created in step-3
Sample:
curl -i -H "x-api-key: Cd2YiWs8Fv8Lg6njI0wXf1iiNOE94XjM3EQe8567" -X GET https://7r9cvghbf4.execute-api.ap-northeast-2.amazonaws.com/dd/pets
Assuming you've followed all steps for creating the API key you can use this API key by specifying it in the x-api-key header within your request.
You distribute API keys to your customers and require them to pass the API key as the X-API-Key header of each incoming request.
More information for using API keys in API Gateway is available on: Choose an API key source - Amazon API Gateway
Related
I want to get my own Google Contacts so I read up on the People API documentation, on the "Authorize Request" section under the "Acquiring and using an API key" it says:
API keys: A request that does not provide an OAuth 2.0 token must send
an API key. The key identifies your project and provides API access,
quota, and reports.
The API supports several types of restrictions on API keys. If the API
key that you need doesn't already exist, then create an API key in the
Console by clicking Create credentials > API key. You can restrict the
key before using it in production by clicking Restrict key and
selecting one of the Restrictions.
So that seems easy enough, I went to the project page and created an unrestricted API Key, then I can create this request URL: https://people.googleapis.com/v1/people/me?key=API_KEY&personFields=names, with the API key just in the URL, as this statement suggest.
After you have an API key, your application can append the query parameter key=yourAPIKey to all request URLs.
But when I run the URL I posted before it returns this:
{
"error": {
"code": 401,
"message": "The request does not have valid authentication credentials.",
"status": "UNAUTHENTICATED"
}
}
What am I doing wrong? :(
Turns out the solution is pretty simple and I feel quite stupid, it isn't possible to access your own Google Contacts or any other private data using the API key, if you're trying to access any private data you should use OAuth 2.0 and not an API key (unlike for instance a public YouTube play-list where you CAN use an API key). Thanks to #Mateo Randwolf
So I am trying trying to execute a PutItem request from my AWS API Gateway. I am trying to do this by using the path /storeid/{username}/{password}. I have done the mapping as json and the test within the API works perfectly and I see my data show up in my DynamoDB table but when I deploy the API and try to invoke this request I receive the following response: {"message":"Missing Authentication Token"}. This request does not have any authorization or API key requirement. Why does the test work but not the url when invoked.
ps-yes I entered the correct url
Please help!
A few things to check
Verify that Authorization is set to None (i.e. not IAM) in your Method request settings.
Verify that you deployed your API changes to your stage. Using the console, click Actions -> Deploy API.
Once deployed the URL to use should be displayed when you select the Stage that you deployed to. Verify you are using the correct URL.
Also, side note, it is a really bad idea to be putting passwords in your URL path or query parameters. Consider doing sending the data in the request body as a POST and doing something like HTTPS and hashing to protect the password.
I have a working AWS API Gateway GET method. I want to secure it using an API key, so I've created an API key and usage plan, etc.
So previously when I wanted to call the GET method, I would just type a URL with the appropriate parameters into the browser and send it. However, now that we've introduced the API key into the mix, I'm not sure how to call it.
I'm aware of the command line GET and curl tools. Which of these 3 tools (browser, GET, CURL) can accomplish this task and what syntax do I need to use to make the request to the GET method passing the API key?
Mark B is right, I'm just copying because it's the right answer.
You must pass an HTTP header named x-api-key with the API Key as the value. One tool is cURL, another is Postman.
I have created an API Key and added it to my functions. I have then deployed the api and tested it but still get:
"message": "Forbidden"
How do I pass the api key with my JSON request as I have been using "x-api-key": "theKey"?
The x-api-key parameter is passed as a HTTP header parameter (i.e. it is not added to the JSON body). How you pass HTTP headers depend on the HTTP client you use.
For example, if you use curl and assuming that you POST the JSON payload, a request would look something like (where you replace [api-id] with the actual id and [region] with the AWS region of your API):
$ curl -X POST -H "x-api-key: theKey" -H "Content-Type: application/json" -d '{"key":"val"}' https://[api-id].execute-api.[region].amazonaws.com
I had to add an API Usage plan, and then link the plan to the API stage.
Seems like this is the only way to link the key to the API, not sure if this is a recent change on AWS.
If you set 'API Key Required' option to true, please check below.
you have to pass 'x-api-key' HTTP Header Parameter to API Gateway.
The API Key had to be created.
In addition, you need to check a Usage Plan for the API Key on API Gateway Console.
If you set 'API' key required to true, you need to pass the api key as header.
API Key is passed as header field 'x-api-key'. Even after adding this field in header, this issue may occur. In that case, please validate below points
Do you have a Usage Plan? if not need to create one.
Link you API with Usage Plan. For that add a stage, it will link your API
Do you have API Key? if not you need to create an API Key and enable it.
Add the Usage Plan which is linked with your API to this API Key. For that, add Usage Plan.
I hope you are not missing to link the API key with the API
I was able to get a successful response from Lambda using below configuration in Postman native app -
Under authorization tab (For some reason this didn't work when i passed the same parameters under header)
Key : x-api-key
Value : your-api-key-value
Add to : Header
I don't have enough reputation to set this as a comment, But I was finally able to find the document specifying that 'x-api-key' belongs in the header for API Gateway calls that come from outside clients (like postman, swagger, etc.) in the AWS Documentation.
The relevant part:
To use header-sourced API keys:
Create an API with desired API methods. And deploy the API to a
stage.
Create a new usage plan or choose an existing one. Add the deployed
API stage to the usage plan. Attach an API key to the usage plan or
choose an existing API key in the plan. Note the chosen API key
value.
Set up API methods to require an API key.
Redeploy the API to the same stage. If you deploy the API to a new
stage, make sure to update the usage plan to attach the new API
stage.
The client can now call the API methods while supplying the x-api-key
header with the chosen API key as the header value.
Choose an API key source
For Private API Gateways accessed through public DNS, we need to pass additional header of 'x-apigw-api-id' with the api id along with 'x-api-key' if configured.
curl -v https://{vpce-id}.execute-api.{region}.vpce.amazonaws.com/test -H 'x-apigw-api-id:{api-id}'
Its documented below,
https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-api-test-invoke-url.html#w20aac13c16c28c11
Here a good resource explaining different reasons why we could be getting a Forbidden. The two most important are the request URL and the x-api-key header:
https://{api_id}.execute-api.{region}.amazonaws.com/{stage_name}/{resource_name}
Missing stage name will give you 403 for ex. Maybe for security reasons the response is not revealing an issue with the stage name, and thus you get a generic Forbidden.
I faced the same problem today. I had already mapped the API key to the usage plan (which was linked to the api gateway stage). I was also passing the api key in header correctly.
When none of these solutions work, do remember to check if your API is linked to WAF policy with only a certain ip-addresses permitted. Apparently, my IP address had changed today. So, WAF was blocking me. That can be an additional reason to get {"message": "Forbidden"} error.
Pretty self explanatory title. I'm using API Gateway in AWS, requiring an API key to access a backend written in Django (not using lambda). I need to know how to access the API key used in the request to keep track of who did what at the app level.
You can use mapping templates and get the API Key from the $context variable, it’s the apiKey property inside the identity object: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#context-variable-reference
Create a mapping template for your requests and include the property in it. For example, if you wanted to include the entire request body + the API Key you would do this:
{
"body": $input.json('$'),
"apiKey": "$context.identity.apiKey"
}
Depending on how your backend application is built, you could send the API key to your application in a HTTP parameter (path, query string, or header) or in the request body. Please have a read through the docs on how to move data between the two systems.
Thanks,
Ryan
Here is how I finally made it work. At the top or bottom of the template, include this line.
#set($context.requestOverride.header.x-api-key = $context.identity.apiKey)
When your backend receives this request, the api key will be in the header x-api-key.
Here is a basic mapping template that just forwards the (json) body and the header.
$input.json("$")
#set($context.requestOverride.header.x-api-key = $context.identity.apiKey)
API Gateway uses the X-API-Key header, so I like for my backend to also use that. That way I can use the same testing commands with only the URL being different.