211

I am trying to call a Lambda Function through AWS API Gateway. When I mention Authentication type NONE it works fine but API become public and anyone with url can access my API. To make API call secure, I am using Authentication type AWS_IAM and also attached AmazonAPIGatewayInvokeFullAccess policy to my user but getting this error:

{ message: "Missing Authentication Token"}

I don't know what I am missing here.

codependent
  • 23,193
  • 31
  • 166
  • 308
Umer Waheed
  • 4,044
  • 7
  • 41
  • 62
  • I believe most if not all Answers here would also work for any other AWS Service (i.e: also DynamoDB) mapped behind a given API Gateway Resource endpoint. Assuming that's true, API Gateway is the operative interface here (not the AWS Service Resource). – cellepo Mar 25 '20 at 23:00
  • 9
    The error is as a result of hitting the wrong endpoint – Rexben Aug 11 '20 at 13:48
  • 5
    Or the right endpoint with the wrong method, GET vs. POST, etc. – RaisinBranCrunch Mar 10 '21 at 21:10
  • 1
    My issues was different lol, I forgot to deploy the API to staging, hence it didn't work for me xD – keidakida Sep 02 '22 at 23:21
  • It took me way too long to realize you always need to deploy after changes in api gateway, that's how I got this same error. – Pete Mar 06 '23 at 12:04
  • aws really needs to clarify that error message. – aerin Mar 19 '23 at 19:00
  • And you may just need to specify *additional* path. When using `ANY` method and `{proxy+}` resource, and deploying a stage with a stage name of `v1` for instance, you get given an invoke URL that goes all the way up to `https://.../v1`, but it *still* requires more path spec because your `ANY` method is on the proxy resource and it seems it can't be empty. But because you are using proxy for the resource, literally any path will work, so long as it's not empty, so just add some characters and it should go through: `https://../v1/something`. – NeilG Aug 18 '23 at 16:06

27 Answers27

377

I've lost some time for a silly reason:

When you create a stage, the link displayed does not contain the resource part of the URL:

API URL: https://1111.execute-api.us-east-1.amazonaws.com/dev

API + RESOURCE URL https://1111.execute-api.us-east-1.amazonaws.com/dev/get-list

The /get-list was missing

And of course, you need to check that the method configuration looks like this:

enter image description here

  • 59
    special kudos are required for admitting silly (but common) reasons for a problem. This got me as well. – Jeff Richards Oct 13 '17 at 15:59
  • Sorry, I didn't understand what you meant, If you want to check if a post request is setup to use authentication, you need to click on the POST option, under the resource you created, for example, you may have /my-post-call in your resources, and under it, you have OPTION and POST methods. Click on the POST , and then in method configuration, there you can see if authentication is required. But If you want to get the full URL to a post call, it works the same way as a get API URL + RESOURCE, for example, https://1111.execute-api.us-east-1.amazonaws.com/dev/my-pos-tcall – Carlos Alberto Schneider Feb 14 '18 at 11:13
  • 5
    A related, dumb thing that tripped me up: make sure your HTTP verb is correct. I was sending a GET instead of a POST by mistake. It seems you'll get this error on any route that doesn't match *exactly* in terms of both path and verb. – Josh1billion Mar 08 '19 at 20:23
  • FWIW, clicking on the Resource itself (in this case, GET) first in the Stages tree I believe should reveal the full URL for that resource directly. More details and an explanatory pic in my related Answer: https://stackoverflow.com/a/60858537/1357094 – cellepo Mar 25 '20 at 23:06
  • Thank you for this! Another issue I ran into was that I was trying to add my API key to "params" in postman instead of "Headers". I knew it was going to work because in the "KEY" column, I started typing "x-api" and it auto-populated the key name, then simply added the API key to the "VALUE" column. Thanks again! – Z41N Feb 17 '22 at 17:22
  • BTW there's no need to disable authentication, you can pass the api key as x-api-key header – OtaconKiko Mar 15 '22 at 11:30
  • I had made put request instead of POST that is why I was getting same error. – Santosh Dec 13 '22 at 09:47
57

I think you are directly trying to access API link, this won't work because API is secured using IAM role and you must provide AWS authentication i.e Access key and Secret key.

Use the Postman Chrome extension to test your API: http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-use-postman-to-call-api.html

saddam
  • 606
  • 5
  • 5
  • 1
    Hi Saddam, How AWS authentication can be done in SOAP ui. In POSTMAN, its very easy. Do we have similar way in SOAP UI? – Pankaj Sharma Nov 25 '19 at 14:36
  • 1
    Using Postman ? The problem is to call it "for real", not from Postman. > ou must provide AWS authentication i.e Access key and Secret key How? – Alex 75 Jun 27 '21 at 14:56
37

I just had the same issue and it seems it also shows this message if the resource cannot be found.

In my case I had updated the API, but forgotten to redeploy. The issue was resolved after deploying the updated API to my stage.

Nic
  • 12,220
  • 20
  • 77
  • 105
28

Make sure you are clicking on the specific Resource first in the Stages tree, as that will populate a URL with the full path to the resource (rather than just the root path): enter image description here

For other causes, see http://www.awslessons.com/2017/aws-api-gateway-missing-authentication-token/

cellepo
  • 4,001
  • 2
  • 38
  • 57
14

Looks like (as of April 2019) AWS API Gateway throws this exception for a variety of reasons - mostly when you are hitting an endpoint that API Gateway is not able to reach, either because it is not deployed, or also in cases where that particular HTTP method is not supported.

I wish the gateway sends more appropriate error codes like HTTP 405 Method not supported or HTTP 404 not found, instead of a generic HTTP 403 Forbidden.

TechiRik
  • 1,893
  • 6
  • 27
  • 37
  • most recent list of 403 Response headers/messages/root-causes:: https://repost.aws/knowledge-center/api-gateway-troubleshoot-403-forbidden – Marc Tamsky Jun 08 '23 at 21:02
11

In my case I missed adding '/' forward slash at the end of api.
Such a silly mistake.

https://le9dq5l9.execute-api.eu-west-1.amazonaws.com/v1/putdoctorinfo/

vijayraj34
  • 2,135
  • 26
  • 27
  • backslash is `\ `. refers to its slashing direction, not "at the back of url". `/` is forward slash – Diego Nov 17 '22 at 15:29
  • Upvoted. I spent an embarrassing amount of time on this. Deploying via terraform. Works fine from Postman but from React it was returning `MissingAuthenticationTokenException`. All it was is that URL needs to end with `/` in React using axios... – jgnovak-dev Apr 26 '23 at 23:17
9

I try all the above, if you did all steps in the above answers, and you not solve the problem, then:

  1. on the left menu, hit the "Resources"
  2. in the right to "Resources", hit the api method that you want to test, like "POST/GET etc)
  3. hit the "ACTION" list (it's above to the API method in step 2
  4. select "DEPLOY API" (please do it, even you already deploy yours api)
  5. in "deployment stage" select "prod" or what ever you write in yours previous deploy (it will override yours previous deploy
  6. hit deploy

I thing that because of, when I create the "METHOD REQUEST" (see step 2 how to go to this menu) , in "Authorization" I select "AWS_IAM" after testing api, in aws test option, I try it in "postman" then I understand the in "METHOD REQUEST" , in "Authorization", I should select "none"

I change it to none, but I thing the AWS, need to deploy it again, as I explain

Yoni Ayalon
  • 437
  • 6
  • 3
  • I had the same problem and this solved it, thanks. My issue was actually a bit different than the one mentioned, my problem is that I have an authentication type as NONE, but the request to API gateway does not work. I solve it by (1) not providing any authorization in postman, (2) deploy the api, since I never click the deploy button. – Iching Chang Apr 16 '21 at 11:47
8

Found this in the docs:

If the AWS_IAM authorization were used, you would sign the request using the Signature Version 4 protocols.

Signing request with Signature Version 4


You can also generate an SDK for your API.

How to generate an SDK for an API in API Gateway

Once you've generated the SDK for the platform of your choice, step 6 mentions that if you're using AWS credentials, the request to the API will be signed:

  1. To initialize the API Gateway-generated SDK with AWS credentials, use code similar to the following. If you use AWS credentials, all requests to the API will be signed. This means you must set the appropriate CORS Accept headers for each request:

    var apigClient = apigClientFactory.newClient({
      accessKey: 'ACCESS_KEY',
      secretKey: 'SECRET_KEY',
    });
    
theJasonHall
  • 126
  • 2
  • 5
8

Make sure you create Resource and then create method inside it. That was the issue for me. Thanks

enter image description here

AbidCharlotte49er
  • 914
  • 1
  • 8
  • 11
4

If you enable AWS_IAM authentication you must sign your request with AWS credentials using AWS Signature Version 4.

Note: signing into the AWS console does not automatically sign your browser's requests to your API.

Bob Kinney
  • 8,870
  • 1
  • 27
  • 35
4

sometimes this message shown when you are calling a wrong api

check your api endpoint

HeshamSalama
  • 148
  • 4
4

In my case it was quite a stupid thing. I've get used that new entities are created using POST and it was failing with "Missing Authentication Token". I've missed that for some reason it was defined as PUT which is working fine.

sarh
  • 6,371
  • 4
  • 25
  • 29
2

This error mostly come when you call wrong api end point. Check your api end point that you are calling and verify this on api gateway.

Rizwan Saleem
  • 904
  • 11
  • 28
2

If you are using an API with endpoint of type PRIVATE, be sure of:

  1. You are invoking the API from within your AWS account (example: from an EC2 instance created in your account)

  2. Put necessary credential (access and secret keys) in the EC2 instance in route ~/.aws/credentials (this route is for linux instances) If IAM user use MFA aws_session_token value will be required too.

  3. Use vpce (vpc endpoint) based URL. Example: curl https://vpce-0c0471b7test-jkznizi5.execute-api.us-east-1.vpce.amazonaws.com/dev/api/v1/status

  4. Your EC2 instance have a security group than allow outbound traffic to another security group owned by the vpce like: EC2 instance sg

  5. Your vpce security group allow inbound traffic from another security group (previous sg from ec2 instance) owned by the EC2 instance like: vpce sg

See: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-apis.html

Jorge López
  • 1,649
  • 1
  • 10
  • 7
2

I had the same problem which I solved the following way:

GET Method test

https://54wtstq8d2.execute-api.ap-southeast-2.amazonaws.com/dev/echo/hello
Authorization tab -> 
•   select type(AWS signature)
•   Add AccessKey and SecretKey
Violeta
  • 700
  • 7
  • 16
2

You must be using Invoke Url to trigger Lambda Function from your browser or POSTMAN... Instead, use the API end point which will be listed in:

select yourLambdaFuntion >> Configuration >> Triggers.

There you can see API end point.

attached image

RiveN
  • 2,595
  • 11
  • 13
  • 26
2

I had same issue today because I was using GET instead of POST. Fixed the issues by changing method to POST in postman.

iamabhaykmr
  • 1,803
  • 3
  • 24
  • 49
1

For the record, if you wouldn't be using credentials, this error also shows when you are setting the request validator in your POST/PUT method to "validate body, query string parameters and HEADERS", or the other option "validate query string parameters and HEADERS"....in that case it will look for the credentials on the header and reject the request. To sum it up, if you don't intend to send credentials and want to keep it open you should not set that option in request validator(set it to either NONE or to validate body)

John
  • 1,711
  • 2
  • 29
  • 42
1

I had the same issue, and fixed it by removing the /dev/ and just put: https://1111.execute-api.us-east-1.amazonaws.com/get-list

MOnir
  • 29
  • 3
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 16 '22 at 08:18
0

First of all, check whether the API you created in the lamda function is registered with your AWS project or not. For that, go to the API gateway in your AWS console. If it is not registered, register it. This is the main cause of this issue.

You can even see in your aws.export.js file, that there are paths corresponding to your API ['/items'].

Your API must be present there, otherwise it will not append the security token to requests. Just register it in your project cloud-logic in your console for this.

If it's there, then use the above mentioned solution
http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-use-postman-to-call-api.html

Philipp Maurer
  • 2,480
  • 6
  • 18
  • 25
Geetanshu Gulati
  • 692
  • 8
  • 13
0

To contribute:

I had a similar error because my return response did not contain the 'body' like this:

return { 'statusCode': 200, 'body': "must contain the body tag if you replace it won't work" }

Andre
  • 598
  • 1
  • 7
  • 18
0

If you set up an IAM role for your server that has the AmazonAPIGatewayInvokeFullAccess permission, you still need to pass headers on each request. You can do this in python with the aws-requests-auth library like so:

import requests
from aws_requests_auth.boto_utils import BotoAWSRequestsAuth
auth = BotoAWSRequestsAuth(
    aws_host="API_ID.execute-api.us-east-1.amazonaws.com",
    aws_region="us-east-1",
    aws_service="execute-api"
)
response = requests.get("https://API_ID.execute-api.us-east-1.amazonaws.com/STAGE/RESOURCE", auth=auth)
Zags
  • 37,389
  • 14
  • 105
  • 140
0

Well for anyone still having the problem and I really feel very dumb after realizing this, but I passed in the url of /items the default one while adding API. But I kept calling the endpoint with /api. Special thanks to Carlos Alberto Schneider, as I realized my problem after reading your post.

Grokify
  • 15,092
  • 6
  • 60
  • 81
Jarrett
  • 486
  • 7
  • 13
0

According to my experience, please check the following steps:

  1. On API gateway side, make sure you add the correct path and publish the resource at the stage you want. For some url pattern like path parameter(/user/{user_id}) need more attention to have a check.

  2. Make sure you configure the correct options method for this resource, because sometimes it is the CORS that cause this problem.

  3. On Lambda side, make sure you specify the correct handler name as the entrypoint.

  4. Please always check cloudwatch logs of your lambda that can help u identify the problems on your lambda side.

0

In my case I was trying to do an UPDATE type request but in my AWS SAM template I had a PATCH type request:

Resources:
  LambdaFunction:
    Type: AWS::Serverless::Function # More info about Function Resource:
    # https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: src/
      Handler: app.lambda_handler
      Runtime: python3.8
      MemorySize: 128
      Events:    
       UpdateItem:
           Type: Api
           Properties:
           Path: /my-endpoint
           Method: patch
Jesus Walker
  • 116
  • 10
0

Things to check:

1. In resources, check for Authorization and API Key if these are required.
2. Redeploy the API, new changes might not reflected.
3. Get the url from stages, directly by clicking on the actions like GET, POST, These will contain the full path urls.
0

I had the same issue even if my access was regional and not private, no authorization on my method neither API. It's turned out that I was calling the root endpoint "https://azerty.execute-api.eu-west-3.amazonaws.com/dev/", which in local return me a json but raised an error. Be sure to call a proper endpoint, such as "https://azerty.execute-api.eu-west-3.amazonaws.com/dev/hello"

spacycookie
  • 118
  • 2
  • 7