#✅ - 403 error invoking API.post with authenticated user

15 messages · Page 1 of 1 (latest)

patent ore
#

I've created an AWS Amplify function with amplify add function resulting in the following basic configuration:

General information
- Name: MyFunction
- Runtime: python

Resource access permission
- Not configured

Scheduled recurring invocation
- Not configured

Lambda layers
- Not configured

Environment variables:
- Not configured

Secrets configuration
- Not configured

I then added a REST API using amplify add api that uses this function, and added a path with "create" and "read" access for authenticated users resulting in the following policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "execute-api:Invoke"
            ],
            "Resource": [
                "arn:aws:execute-api:us-west-2:...:.../staging/POST/added/path/*",
                "arn:aws:execute-api:us-west-2:...:.../staging/POST/added/path",
                "arn:aws:execute-api:us-west-2:...:.../staging/GET/added/path/*",
                "arn:aws:execute-api:us-west-2:...:.../staging/GET/added/path"
            ],
            "Effect": "Allow"
        }
    ]
}

But when I invoke the API from my app, with a logged in authenticated user (who has no trouble using my GraphQL API via DataStore) I get a 403 error.

I can't figure out what's happening here. What would cause a 403 error in this case? This is all pretty much out of the box from the Amplify CLI. What's wrong with the authentication I'm providing?


The code for the Lambda function (generated by the CLI, with no further edits) is:

def handler(event, context):
  return {
      'statusCode': 200,
      'headers': {
          'Access-Control-Allow-Headers': '*',
          'Access-Control-Allow-Origin': '*',
          'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
      },
      'body': json.dumps('Hello from your new Amplify Python lambda!')
  }

The invoking code (copied from the Amplify documentation) is:

import ... { API } from 'aws-amplify'

// ...

    const callLambdaFunction = async () => {
        try {

             console.log( (await Auth.currentSession())
                        .getIdToken()
                        .getJwtToken() )

            const response = await API.post( 'Chat', '/added/path', {
                body: { data },
                headers: {
                    Authorization: `Bearer ${ (await Auth.currentSession())
                        .getIdToken()
                        .getJwtToken() }`,
                },
            } )

            setResult( response )
        }
        catch ( error ) {
            console.log( error )
        }
    }

Some notes:

  1. Why do I even need to provide authentication? Doesn't the API.post already know about the currently authenticated user and append the necessary headers? DataStore does.
  2. What do "read", "create", etc. mean in the amplify api CLI? How do the relate to what the endpoint does or is, or who can access it. Is it a secret code for "GET", "POST", etc.?
  3. I've tried pasting the JWT I get from Auth.currentSession into Postman but get nonsense:
    {
        "message": "'eyJhbG...0HMs' not a valid key=value pair (missing equal-sign) in Authorization header: 'Bearer eyJhbG...0HMs'."
    }
    
    even if I just paste random text.
neat plank
#

Try getAccessToken() instead of getIdToken(). You can test the token with https://jwt.io. Others may have a better answer.

patent ore
neat plank
#

When I tested in my front-end, using getIdToken() was returning JTW that jwt.io didn't like (looked like the payload was an escaped json string instead of a decoded json object). Are you able to get a valid token and call the API using curl/wget or other rest tester?

patent ore
#

So far jwt.io likes all the tokens I've retrieved with every permutation of Auth.getSomething... that I can think of. And the results there look right: a Cognito user. Maybe the problem is (again!) the Amplify CLI: when I chose the option to restrict access to an authenticated user, what have I really set up? From the wording I expect the call to work with — well — and authenticated user, like DataStore but it feels like amplify update api does something else (and there's the mystery of what "read, create, ..." means in the context of a REST API.

neat plank
#

Not sure, but if you make changes you may test in a local env via amplify mock or amplify push to update cloud before things will pick up your changes. Looking forward to hearing what finally works. I can't find the project where I last played with Amplify REST from the front-end, so can't really help much more. Let us know what works out.

patent ore
#

It's all been mocked and pushed and tested in Gateway. It's all wired up as expected. It's just not authenticating as documented (no surprise there really).

patent ore
#

It turns out this doesn't work. It turns out to that (in contradiction to the documentation) to get an Amplify API working with Amplify (Cognito) Auth, you need to make modifications to the API Gateway outside of Amplify, by first creating a Cognito user pool authorizer in API Gateway console, and then adding the Cognito user pool authorizer to a method of the API, and then "redeploy" the API (whatever that means). None of which has anything do do with Amplify! (And who knows how it interacts with Amplify over time.) What am I missing?

neon granite
#

Any updates on this? #1019643921137139772 I am having a similar issue where I cannot get my REST API to authenticate my user. Do I really have to go out of amplify just to setup my rest api?

cobalt elm
#

Same here, seems to be a serious bug?

gloomy crest
#

@neon granite @cobalt elm see the comment above

neon granite
#

That's the solution I ended up using for this and it worked fine for cognito authentication

gloomy crest
#

Great glad it worked for you @neon granite

terse tuskBOT
#

✅ - 403 error invoking API.post with authenticated user