aws / aws-appsync-community

The AWS AppSync community
https://aws.amazon.com/appsync
Apache License 2.0
506 stars 32 forks source link

AppSync returns Unauthorized when using Lambda Authorizer #214

Open danitornow opened 2 years ago

danitornow commented 2 years ago

When utilizing the AWS Lambda Authorizer for AppSync as a secondary option, unable to get any request to come back as authorized. As part of testing, set the Authorizer to return true in every circumstance, but it was still returning an ‘Not Authorized’ error in AppSync. It appears that this is an issue with AppSync and it's Lambda Authorizer. I am able to confirm it calls the Lambda, and the response is hardcoded to be true, but it still fails in the AWS AppSync console saying it is unauthorized. We are able to perform our queries with the API Key in the Console but it fails and says ‘Unauthorized’ with the AWS Lambda Authorizer for the same query.

We are deploying AppSync via CloudFormation, utilizing Serverless Framework and the AppSync plugin.

The return from the Lambda was hardcoded (for testing) to this:

{
  "isAuthorized": true,
  "resolverContext": {}
}

The error message in AppSync:

  "data": {
    "getEvent": null
  },
  "errors": [
    {
      "path": [
        "getEvent"
      ],
      "data": null,
      "errorType": "Unauthorized",
      "errorInfo": null,
      "locations": [
        {
          "line": 2,
          "column": 3,
          "sourceName": null
        }
      ],
      "message": "Not Authorized to access getEvent on type Query"
    }
  ]
}

Made sure to include resolverContext due to this thread about Amplify issues with AppSync. GitHub thread about Amplify issue with AppSync Lambda Auth: https://github.com/aws-amplify/amplify-cli/issues/10047

Testing with an empty resolverContext and non-empty resolverContext produced the same results.

Lambda Code, Typescript compiled to Node 14:

Object.defineProperty(exports, "__esModule", { value: true });
exports.handler = void 0;

async function handler(lambdaEvent) {

    console.log('Received event context: {}', JSON.stringify(lambdaEvent.requestContext));
    return {
        isAuthorized: true,
        resolverContext: {}
    };
}
exports.handler = handler;
//# sourceMappingURL=authenticate.js.map

Example of Context coming from AppSync invocation:

    "apiId": "zpaawy2f7rbqdpupeik44az6wm",
    "accountId": "$$$$$$$$$$$",
    "requestId": "596b0f97-a6eb-47e0-bf98-f6659fc27df0",
    "queryString": "query MyQuery {\n  getEvent(id: \"2193\") {\n    location {\n      name\n    }\n    name\n    start_time\n    end_time\n  }\n}\n",
    "operationName": "MyQuery",
    "variables": {}
}
gabrieleCutowl commented 2 years ago

I'm experiencing the exact same behaviour also from aws console, using lambda response with isAuthorized fixed to true.

toha87 commented 2 years ago

Having the same issue, getting Not Authorized when returning isAuthorized: true.

fomson commented 2 years ago

Same here.

sivivan commented 2 years ago

Same here

sivivan commented 2 years ago

Having done a bit more investigation it appears that this issue is only present when having multiple authorizers, i.e. Lambda Authorisation as a secondary authorization option (with API key being the first). If I were to test Lambda authorization on its own then the same lambda function works just fine.

I have tried swapping the order, i.e. using lambda as default and api key as a secondary and now API key throws the same error.

fomson commented 2 years ago

@sivivan, could you please elaborate a bit more? :)

By any chance, is this comment relevant to what you are suggesting? :)

sivivan commented 2 years ago

@fomson basically it appears that Appsync only has issues if two or more auth mechanisms are configured. You can use either Lambda or API key just fine when just one of them is configured. The moment you add a second one the second auth method that you have added will throw an error of "Not Authorized to access on type Query".

fomson commented 2 years ago

@snvishna, what do you mean by "Lambda" auth mechanism?

In Transformer v1, in my GraphQL [AppSync], I have set up two authorisation modes: IAM (default) and Amazon Cognito User Pool.

As Lambdas are supposedly "private", in my GraphQL schema, on my Type(s), one of the @auth rules I have is {allow: private, provider: iam, operations: [create, update, delete, read]}. I think this means that anything that has "authed IAM role" [incl. my Lambda] will be able to do all those "operations" on the Type [incl. Amplify-generated resolvers]. I did give my Lambda access to my API/GraphQL [and Type(s)] in amplify MY_FUNCTION update...

So, do you suggest that in Transformer v2, if I had only one authorisation mode [either IAM or User Pool], things would work?

sivivan commented 2 years ago

@fomson apologies I am not familiar what Transformer v2 is.

I am just using the AWS Appsync (without using Amplify) directly.

But, yes, this is what I suggest is the root cause. Try testing with just one authorisation mode and see if things work.

For me the problem occurs when I have two modes added, i.e. API_KEY and Lambda auth modes.

In your case it might be due to IAM and User Pool being the two modes.

fomson commented 2 years ago

@sivivan I see. My apologies too for bringing confusion with Amplify [just noticed that this thread has nothing to with Amplify]

Either way, it does seem that there is something wrong with authorisation. Up until very recently, both IAM and User Pool worked well for me. It would not make sense to only allow one way to authorise as depending on the type of user, different operations could be permitted...

I will keep this thread in mind if a solution occurs for [my] Amplify-linked AppSync issues :)

NourDT commented 2 years ago

For anyone running into the same issue, I had this error and managed to resolve it - Query was explicitly defined, and i had to add the @aws_lambda directive to it, in addition to adding the same directive to the type itself. Once i added both, the request seemed to work fine.

Screenshot 2022-07-07 at 4 12 36 PM Screenshot 2022-07-07 at 4 13 41 PM
JandenMa commented 2 years ago

same here when we upgraded aws-cdk to v2

jbreuil commented 1 year ago

Having done a bit more investigation it appears that this issue is only present when having multiple authorizers, i.e. Lambda Authorisation as a secondary authorization option (with API key being the first). If I were to test Lambda authorization on its own then the same lambda function works just fine.

I have tried swapping the order, i.e. using lambda as default and api key as a secondary and now API key throws the same error.

This sums up the problem. I can also reproduce it with the query client of appsync, if you set an api key as secondary authentication providers, even if you select it in the query client setting any queries will throw Unauthorized

nits1991 commented 8 months ago

I am facing the same issue when my default mode is API_KEY and OIDC as additional mode. I keep getting unauthorized.

As soon as i make OIDC as deafult with the same configuration, it starts working.

Can please someone confirm if the same behavior happening with aws_lambda as additional mode happens with OIDC as additional mode

espetro commented 2 months ago

bump 👍 any news on whether this is solved or not?