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
81 stars 71 forks source link

Authorization rules not being respected? #2645

Open naedx opened 1 week ago

naedx commented 1 week ago

Environment information

System:
  OS: macOS 14.5
  CPU: arm64 Apple
  Shell: /bin/zsh
Binaries:
  Node: 20.9.0 - /usr/local/bin/node
  Yarn: 1.22.22 - ~/.npm-global/bin/yarn
  npm: 10.8.0 - ~/.npm-global/bin/npm
  pnpm: 9.1.2 - ~/.npm-global/bin/pnpm
NPM Packages:
  @aws-amplify/backend: 1.0.3
  @aws-amplify/backend-cli: 1.0.4
  aws-amplify: 6.3.7
  aws-cdk: 2.146.0
  aws-cdk-lib: 2.146.0
  typescript: 5.4.5
AWS environment variables:
  AWS_STS_REGIONAL_ENDPOINTS = regional
  AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1
  AWS_SDK_LOAD_CONFIG = 1
No CDK environment variables

Data packages

my_amplify_app@1.0.0 /xxx/my_amplify_app
├─┬ @aws-amplify/backend-cli@1.0.4
│ └─┬ @aws-amplify/schema-generator@1.0.0
│   └── @aws-amplify/graphql-schema-generator@0.8.6
└─┬ @aws-amplify/backend@1.0.3
  └─┬ @aws-amplify/backend-data@1.0.2
    └── @aws-amplify/data-construct@1.8.5

Description

I have a project created based on the quick start guide for Flutter. I have configured the Todo model to allow read only if the user is authenticated with userPools. However, in the web console I am able to successfully execute a create mutation with 'AWS Identity and Access Management' selected as the authorization provider.

Schema:

```typescript import { type ClientSchema, a, defineData } from "@aws-amplify/backend"; const schema = a.schema({ Todo: a .model({ content: a.string(), isDone: a.boolean(), }) .authorization(allow => [allow.authenticated('userPools').to(['read'])]), }) export type Schema = ClientSchema; export const data = defineData({ name: 'amplifyQuickStartData', schema, authorizationModes: { defaultAuthorizationMode: 'iam', }, }); ```
AnilMaktala commented 1 week ago

Hi @naedx, thanks for raising this. We are working on reproducing this issue. Will you be able to share the schema?

naedx commented 1 week ago

Hi @AnilMaktala ! Thanks for taking a look at this. The schema is in the details in the original post.

naedx commented 1 week ago

If I understand that vtl resolver that is created MutationcreateTodoauth0FunctionEdit it appears that once authorization is being done by IAM every operation is authorized?


## [Start] Authorization Steps. **
$util.qr($ctx.stash.put("hasAuth", true))
#set( $inputFields = $util.parseJson($util.toJson($ctx.args.input.keySet())) )
#set( $isAuthorized = false )
#set( $allowedFields = [] )
#if( $util.authType() == "IAM Authorization" )                        # <<<<<<<<<<<<<<<<<< here
  #if( $util.authType() == "IAM Authorization" && $util.isNull($ctx.identity.cognitoIdentityPoolId) && $util.isNull($ctx.identity.cognitoIdentityId) )                           # <<<<<<<<<<<<<<<<<< here
    $util.qr($ctx.stash.put("hasAuth", true))
    #set( $isAuthorized = true )                                                  # <<<<<<<<<<<<<<<<<< here
  #else
$util.unauthorized()
  #end
#end
#if( $util.authType() == "User Pool Authorization" )

#end
#if( !$isAuthorized && $allowedFields.isEmpty() )
$util.unauthorized()
#end
#if( !$isAuthorized )
  #set( $deniedFields = $util.list.copyAndRemoveAll($inputFields, $allowedFields) )
  #if( $deniedFields.size() > 0 )
    $util.error("Unauthorized on ${deniedFields}", "Unauthorized")
  #end
#end
$util.toJson({"version":"2018-05-29","payload":{}})
## [End] Authorization Steps. **
phani-srikar commented 4 days ago

Hi @naedx, you have 2 auth modes set on your API - IAM (enabled by default) and Cognito User Pools (based on your Auth rule). The expected behavior with your setup and schema is:

I've tested the scenario with a sample app and observed that:

Given this context,

it appears that once authorization is being done by IAM every operation is authorized?

Every operation is not authorized by default and the permissions depend on the policy you attach to that IAM role.

Can you double check and if possible share the policies attached to your IAM test role? When testing from the AppSync console, the IAM role will be the one you used to sign in to the AppSync console.