Let's say I have an AWS API Gateway. I have a resource in said gateway that requires the use of a gateway API Key. I would like my server to know which of my various keys are being used to authenticate (just for logging; there's no access control happening based on this).
How do I include the name of the gateway API Key in the request that is being sent to the server?
Firstly, you mentioned logging which keys are used for authentication. API GW API Keys are intended to be used with usage plans, not authentication/authorization (link).
For user authentication and authorization, don't use API keys. Use an IAM role, a Lambda authorizer, or an Amazon Cognito user pool.
I think it is because of this reason, AWS does not forward the key further to the backend. Furthermore, if you have used one of the authorizers like Lambda or Cognito, your backend will have a way to log the authenticated identity.
If you really want to log the API keys though, I think you can use a mapping template to explicitly tell API GW to forward the x-api-key header.
API keys attached to an API gateway have to be unique. From the docs:
API key values must be unique. If you try to create two API keys with different names and the same value, API Gateway considers them to be the same API key.
The is no such header to specify the name of the key. You can create your own custom header where you would add this information, but nothing would guarantee that the correct name is sent with a given API key. You would probably want to implement a call using the AWS SDK from your server to retrieve the name of the API key.
In case you are using a Lambda authorizer function, you can fetch the name of the API key in this function and forward it as a header to the backend server.
Related
I have an aws api gateway api that was using a api key to authenticate requests. It was tied to a usage plan and it was working. Later we needed a new api key name and value. I removed the old api key from usage plan and added the new api key to usage plan. Re-deployed the stage. Now when using the new api key name and value in the header the requests always return as 403 forbidden. Not sure what is wrong. Everything looks right.
The header for an API key must be x-api-key, without this the API will return a 403 when API key authentication is enabled for the stage.
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.
The name of the key does not need to share this, in fact you can use it to describe the application/user who will be using this API key with your integration.
To call your API you would use the below where $key is the API key value.
curl -H "x-api-key: $key" https://xxxxxx.execute-api.us-west-2.amazonaws.com/get-token
You can find out more information about this in the Choose an API key source documentation.
In AWS API Gateway,
- We can set up a resource to reqiure API Key for access.
- We can also set up another resource to require Authorization (e.g. JWT token, handled via a lambda function or AWS Cognito).
The question: can we configure a resource to be accessible in either of the above two situations? Currently, if we enable "API Key Required" and "Authorization" simultaneously, the request needs both the API Key and the Authorization. We were hoping for it to pass with only one of the two.
Hack/workaround: Create two copies of the same resource, and authorize each separately, one with API Key and the other one with an authorizer.
Let authorizer generate/map the API key for you
You have a Lambda authorizer return the API key as part of
the authorization response. For more information on the authorization
response, see Output from an Amazon API Gateway Lambda authorizer.
Pros:
Single end-point
API key is more for usage plan than authorization. Keep it that way.
Cons:
Authorizer will run on each request. Which cost money
Authentication, Identification, Authorization are intertwined concepts. As I got more educated on Auth, here is my answer:
API Keys are used for project/application identification and authorization
JWT are used for user authentication and authorization.
API Key is on project/application scope and JWT is on user scope. In other words, API Key only identifies the application, not the user of the application.
Accordingly, it makes sense not to authorize the same endpoint with both JWT and API Key as it would reduce the governance granularity for users and applications. But, if you have a usecase that requires that type of authorization, the suggested workaround could work.
I want to use the AWS API Gateway to Authorize using API Key.
However, my need is that every time some client use the API key to make request using x-api-key header, I want to see that it is for which account Id in my system.
For example: My system having userID-1 and I have created API key in API Gateway that is APIKey-1 now I want to map it in API Gateway. So,every time request comes to the downstream service I can see the API key as well as account ID.
So, from request I can identified that APIKey-1 is mapped to UserId-1 and so on.
Appreciate your help.
If any alternative, please let us know.
Thanks,
Keyur
ApiKeys is not recommended way to authorizer users. You should try using one of API gateway supported authorization solutions.
Why can't you push this mapping ( apikey to user ) to your backend ?
I want to use api-keys for authorization and grouping users for accesing the api's in API Gateway. The requests will be sent from web-page using javascript calls.
Is there any way to encrypt the api-keys?
Lets say I am able to encrypt it, will it be beneficial at all? Because someone can still see the encrypted api-keys and use it, and it will still work, because anyhow i will be decrypting it somewhere.
Is there any better way?
You cannot protect your API keys for authorization when your API calls are initiated from the client (i.e., JavaScript). As you said, there will be no point of encrypting them as well. You'll need to have an authorization provider that can return the API key as part of the response.
API Gateway allows you to have custom authorizer for your API. See Output from an Amazon API Gateway Custom Authorizer.
I'd like to add a default throttled API key for unauthenticated requests to prevent abuse.
How would I do this in API Gateway?
EDIT
To make it clearer what I need, how do I transform a request in API Gateway? Is this possible?
I would say using Cognito is the best way of authorizing API gateway.
If you want a default API key then you can go for custom API gateway authorizer. Please have a look on official documentation for the same here
You need to store the API Key in the Server Side of your application and shouldn't expose it to the Client Side (Although API Key is not considered as a security token, it can be used by malicious party to call your API).
There are couple of options you have based on the nature of your application consuming the API.
If it is a single page web application where front-end is hosted in S3, you can use AWS CloudFront to store the API Key in headers and forward it to the API Gateway, while also serving the frontend through the same CloudFront distribution. This will also remove the cross origin resource sharing problem between your web application and API Gateway.
If you have a web server, you can store the API Key at Web Server and use to proxy request to the API Gateway while setting the API Key header value.
Note: Don't use API Key for authentication which is not recommended.
This is how I would solve it.
Create Usage Plan with the throttle, burst and max limit on the request allowed.
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/APIGateway.html#createUsagePlan-property
API Key:
Create API Key (createApiKey) and associate it (createUsagePlanKey) with Usage Plan already defined. That will allow the limit defined for the requests received.
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/APIGateway.html#createApiKey-property
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/APIGateway.html#createUsagePlanKey-property
Have a separate lambda to monitor the Generated API-Keys and cleanup once it is expired, so you will not flood API-Gateway with unused keys.
If you take it to CloudFront, you can create Self Signed URL, that will be valid for a given period of time. After that time limit URL will be invalid. This is to keep yourself time-limited for the user, so within the given timelimit, what resource they can access.
One more usecase, we worked on, you can authenticate the user only on certain urls with custom Authorizer. Any other urls that get invokes, will return unauthorized without any additional code.
Hope it helps.