aws-amplify / amplify-category-api

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development. This plugin provides functionality for the API category, allowing for the creation and management of GraphQL and REST based backends for your amplify project.
https://docs.amplify.aws/
Apache License 2.0
89 stars 77 forks source link

Custom Authorizer in GraphQL not being invoked #2128

Open amcdnl opened 11 months ago

amcdnl commented 11 months ago

How did you install the Amplify CLI?

npm

If applicable, what version of Node.js are you using?

18

Amplify CLI Version

12.8.2

What operating system are you using?

Mac

Did you make any manual changes to the cloud resources managed by Amplify? Please describe the changes made.

No

Describe the bug

The @custom authorization directive ( https://docs.amplify.aws/react/build-a-backend/graphqlapi/customize-authorization-rules/#custom-authorization-rule and https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html#aws-lambda-authorization ) does not seem to work. Its not even getting invoked when I trigger it from AWS Appsync Console even.

Expected behavior

It calls the custom auth lambda.

Reproduction steps

I created the following model:

type Billing
  @model
  @auth(rules: [
    {
      allow: custom
    }
  ]) {
  """
  The unique identifier for the billing.
  """
  id: ID!
}

I can confirm that after running the deploy command it updated my cli-inputs.json:

{
  "version": 1,
  "serviceConfiguration": {
    "apiName": "api",
    "serviceName": "AppSync",
    "defaultAuthType": {
      "mode": "OPENID_CONNECT",
      "openIDProviderName": "asdfasdf",
      "openIDIssuerURL": "https://app-asdfasdfasdf.us.frontegg.com/",
      "openIDClientID": "",
      "openIDAuthTTL": "0",
      "openIDIatTTL": "0"
    },
    "additionalAuthTypes": [
      {
        "mode": "API_KEY",
        "expirationTime": 365,
        "apiKeyExpirationDate": "2024-12-07T13:26:47.653Z",
        "keyDescription": "system"
      },
      {
        "mode": "AWS_LAMBDA",
        "lambdaFunction": "authorizer",
        "ttlSeconds": "0"
      }
    ],
    "conflictResolution": {}
  }
}

As you can see I have a 0 ttl and am using multiple auth providers with OIDC being the default here. When I try to execute this in the console I get an unauthorized error:

image

as you can see when I go to the logging portion I have 0 logs despite logging being turned on:

image

Interesting enough if I run the command to get the matrix I get the following:

api git:(main) ✗ amplify status api -acm Billing
🛑 Could not create a role from {"allow":"custom","provider":"function"}

which I haven't been able to find any information on and it does seem to deploy OK ( despite the fact it doens't work at all ). The only changes I've made to the lambda is to make it always return true like:

/**
 * @type {import('@types/aws-lambda').APIGatewayProxyHandler}
 */
exports.handler = async (event) => {
  console.log(`EVENT: ${JSON.stringify(event)}`);

  const {
    authorizationToken,
    requestContext: { apiId, accountId },
  } = event;

  const response = {
    isAuthorized: true, // authorizationToken === 'custom-authorized',
    resolverContext: {
      // eslint-disable-next-line spellcheck/spell-checker
      userid: 'user-id',
      info: 'contextual information A',
      more_info: 'contextual information B',
    },
    deniedFields: [
      // `arn:aws:appsync:${process.env.AWS_REGION}:${accountId}:apis/${apiId}/types/Event/fields/comments`,
      // `Mutation.createEvent`,
    ],
    ttlOverride: 0
  };

  console.log(`response >`, JSON.stringify(response, null, 2));

  return response;
};

I feel like either I'm missing something or this is not compatible with my setup. Maybe someone else who has implemented this can shed some light.

Project Identifier

b22263b845d6e507b22ea849f0297b89

Log output

N/A

Additional information

N/A

Before submitting, please confirm:

ykethan commented 11 months ago

Hey,👋 thanks for raising this! I'm going to transfer this over to our API repository for better assistance 🙂.

phani-srikar commented 11 months ago

This might be a side-effect and related to https://github.com/aws-amplify/amplify-category-api/issues/2060. This regression is fixed in https://github.com/aws-amplify/amplify-category-api/pull/2062 and pending release.

amcdnl commented 10 months ago

@phani-srikar - Awesome news - is there an ETA for release?

amcdnl commented 10 months ago

@phani-srikar - I upgraded to the latest version ( 12.9.0 ) after I saw @dpilch said it was released today however it still doesn't work. I'm get the same messages as above.

amcdnl commented 10 months ago

@dpilch @ykethan @phani-srikar - Is there an ETA on this? Its a major blocker for me at the moment.

AnilMaktala commented 10 months ago

Hey @amcdnl, We recognize the importance of this for you. We're actively working on it and will provide you with an update on the timeline as soon as possible.

sundersc commented 10 months ago

@amcdnl - Are you using a JWT token as authorizer token? In that case, AppSync considers it as Cognito auth mode and process the request incorrectly. Can you add a prefix (say 'Bearer' or something else) and give a try? You can remove this in lambda and extract the actual authorizer token.

Related issues: https://github.com/aws-amplify/amplify-cli/issues/9836 https://github.com/aws-amplify/amplify-cli/issues/9714

amcdnl commented 10 months ago

@sundersc - Yes, I also tried adding Bearer per some of the other tickets in the console and same result. I'm not using Cognito or IAM - its all JWT Tokens.

RoyalBis commented 9 months ago

I encountered a similar issue.

Adding Bearer + JWT seems to have the same problem. However adding Token + JWT seems to resolve this issue.

amcdnl commented 9 months ago

However adding Token + JWT seems to resolve this issue.

Can you expand on that?

RoyalBis commented 9 months ago

Certainly,

Using the following Graphql Request

This code will correctly hit my lambda authorizer with an authToken in the format of Token xyz...

let token = (await Auth.currentSession()).getIdToken().getJwtToken();

API.graphql<GraphQLQuery<ListItemsQuery>>(
   {
        query: queries.listItems,
        authToken: `Token ${token}`,
        authMode: GRAPHQL_AUTH_MODE.AWS_LAMBDA
    }).then((response) => {
        ...handleResponse
    });

This code will not hit my lambda authorizer even though the only change is Token xyz... -> Bearer xyz...

let token = (await Auth.currentSession()).getIdToken().getJwtToken();

API.graphql<GraphQLQuery<ListItemsQuery>>(
   {
        query: queries.listItems,
        authToken: `Bearer ${token}`,
        authMode: GRAPHQL_AUTH_MODE.AWS_LAMBDA
    }).then((response) => {
        ...handleResponse
    });
AvaniYorkie commented 8 months ago

Hi @amcdnl I'm facing the same issue. Were you able to figure out the solution? It's urgent for me. Thanks!

amcdnl commented 8 months ago

@AvaniYorkie - No, I ended up migrating off Amplify, too buggy.

espetro commented 3 months ago

Hey @dpilch @ykethan @phani-srikar , what's the status of this bug? Is there an ETA by any chance?

yubi00 commented 2 months ago

@dpilch @ykethan When I tried the same, I have found that using the cognito jwt token as an Authorization header in external platform like postman or apollo studio would always invoke the USERPOOL AUTH mode, allowing you to access graphql queries. but if the token is other than the valid jwt, would invoke lambda function with the auth type being AWS_LAMBDA. is there a way to invoke lambda for both of the case when cognito user pool mode is set up as a primary auth mode and lambda auth mode as additional auth mode ? we are looking to secure our graphql api when called from external platform such a way that our business logics are in the custom authorizer lambda function.