Skip to content

Unable to use "iam" authorization for custom mutations in v6.2 #13339

@gpavlov2016

Description

@gpavlov2016

Before opening, please confirm:

JavaScript Framework

Next.js

Amplify APIs

GraphQL API

Amplify Version

v6

Amplify Categories

No response

Backend

Amplify Gen 2 (Preview)

Environment information

# Put output below this line
System:
    OS: Windows 11 10.0.22631
    CPU: (20) x64 13th Gen Intel(R) Core(TM) i9-13900H
    Memory: 2.44 GB / 31.68 GB
  Binaries:
    Node: 18.19.1 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 10.2.4 - C:\Program Files\nodejs\npm.CMD
    pnpm: 8.15.4 - ~\AppData\Local\pnpm\pnpm.EXE
  Browsers:
    Edge: Chromium (123.0.2420.97)
    Internet Explorer: 11.0.22621.3527
  npmPackages:
    %name%:  0.1.0
    @ampproject/toolbox-optimizer:  undefined ()
    @aws-amplify/backend: ^1.0.0 => 1.0.0
    @aws-amplify/backend-cli: ^1.0.1 => 1.0.1
    @aws-amplify/ui-react: ^6.1.9 => 6.1.9
    @aws-amplify/ui-react-internal:  undefined ()
    @aws-sdk/s3-presigned-post: ^3.568.0 => 3.568.0
    @babel/core:  undefined ()
    @babel/runtime:  7.22.5
    @edge-runtime/cookies:  4.1.1
    @edge-runtime/ponyfill:  2.4.2
    @edge-runtime/primitives:  4.1.0
    @hapi/accept:  undefined ()
    @heroicons/react: ^2.1.3 => 2.1.3
    @mswjs/interceptors:  undefined ()
    @napi-rs/triples:  undefined ()
    @next/font:  undefined ()
    @opentelemetry/api:  undefined ()
    @types/node: ^20.12.8 => 20.12.8
    @types/react: ^18.3.1 => 18.3.1
    @types/react-dom: ^18.3.0 => 18.3.0
    @vercel/nft:  undefined ()
    @vercel/og:  0.6.2
    acorn:  undefined ()
    amphtml-validator:  undefined ()
    anser:  undefined ()
    arg:  undefined ()
    assert:  undefined ()
    async-retry:  undefined ()
    async-sema:  undefined ()
    autoprefixer: ^10.4.19 => 10.4.19
    aws-amplify: ^6.2.0 => 6.2.0
    aws-amplify/adapter-core:  undefined ()
    aws-amplify/analytics:  undefined ()
    aws-amplify/analytics/kinesis:  undefined ()
    aws-amplify/analytics/kinesis-firehose:  undefined ()
    aws-amplify/analytics/personalize:  undefined ()
    aws-amplify/analytics/pinpoint:  undefined ()
    aws-amplify/api:  undefined ()
    aws-amplify/api/server:  undefined ()
    aws-amplify/auth:  undefined ()
    aws-amplify/auth/cognito:  undefined ()
    aws-amplify/auth/cognito/server:  undefined ()
    aws-amplify/auth/enable-oauth-listener:  undefined ()
    aws-amplify/auth/server:  undefined ()
    aws-amplify/data:  undefined ()
    aws-amplify/data/server:  undefined ()
    aws-amplify/datastore:  undefined ()
    aws-amplify/in-app-messaging:  undefined ()
    aws-amplify/in-app-messaging/pinpoint:  undefined ()
    aws-amplify/push-notifications:  undefined ()
    aws-amplify/push-notifications/pinpoint:  undefined ()
    aws-amplify/storage:  undefined ()
    aws-amplify/storage/s3:  undefined ()
    aws-amplify/storage/s3/server:  undefined ()
    aws-amplify/storage/server:  undefined ()
    aws-amplify/utils:  undefined ()
    aws-cdk: ^2.140.0 => 2.140.0
    aws-cdk-lib: ^2.140.0 => 2.140.0
    aws-sdk: ^2.1613.0 => 2.1613.0
    babel-packages:  undefined ()
    browserify-zlib:  undefined ()
    browserslist:  undefined ()
    buffer:  undefined ()
    bytes:  undefined ()
    ci-info:  undefined ()
    cli-select:  undefined ()
    client-only:  0.0.1
    commander:  undefined ()
    comment-json:  undefined ()
    compression:  undefined ()
    conf:  undefined ()
    constants-browserify:  undefined ()
    constructs: ^10.3.0 => 10.3.0
    content-disposition:  undefined ()
    content-type:  undefined ()
    cookie:  undefined ()
    cross-spawn:  undefined ()
    crypto-browserify:  undefined ()
    css.escape:  undefined ()
    data-uri-to-buffer:  undefined ()
    debug:  undefined ()
    devalue:  undefined ()
    domain-browser:  undefined ()
    edge-runtime:  undefined ()
    esbuild: ^0.20.2 => 0.20.2
    eslint: ^8.57.0 => 8.57.0
    eslint-config-next: 14.2.3 => 14.2.3
    events:  undefined ()
    find-cache-dir:  undefined ()
    find-up:  undefined ()
    fresh:  undefined ()
    get-orientation:  undefined ()
    glob:  undefined ()
    gzip-size:  undefined ()
    http-proxy:  undefined ()
    http-proxy-agent:  undefined ()
    https-browserify:  undefined ()
    https-proxy-agent:  undefined ()
    icss-utils:  undefined ()
    ignore-loader:  undefined ()
    image-size:  undefined ()
    is-animated:  undefined ()
    is-docker:  undefined ()
    is-wsl:  undefined ()
    jest-worker:  undefined ()
    json5:  undefined ()
    jsonwebtoken:  undefined ()
    loader-runner:  undefined ()
    loader-utils:  undefined ()
    lodash.curry:  undefined ()
    lru-cache:  undefined ()
    mini-css-extract-plugin:  undefined ()
    nanoid:  undefined ()
    native-url:  undefined ()
    neo-async:  undefined ()
    next: 14.2.3 => 14.2.3
    node-fetch:  undefined ()
    node-html-parser:  undefined ()
    ora:  undefined ()
    os-browserify:  undefined ()
    p-limit:  undefined ()
    path-browserify:  undefined ()
    picomatch:  undefined ()
    platform:  undefined ()
    postcss: ^8.4.38 => 8.4.38 (8.4.31)
    postcss-flexbugs-fixes:  undefined ()
    postcss-modules-extract-imports:  undefined ()
    postcss-modules-local-by-default:  undefined ()
    postcss-modules-scope:  undefined ()
    postcss-modules-values:  undefined ()
    postcss-preset-env:  undefined ()
    postcss-safe-parser:  undefined ()
    postcss-scss:  undefined ()
    postcss-value-parser:  undefined ()
    process:  undefined ()
    punycode:  undefined ()
    querystring-es3:  undefined ()
    raw-body:  undefined ()
    react: ^18.3.1 => 18.3.1
    react-builtin:  undefined ()
    react-dom: ^18.3.1 => 18.3.1
    react-dom-builtin:  undefined ()
    react-dom-experimental-builtin:  undefined ()
    react-experimental-builtin:  undefined ()
    react-is:  18.2.0
    react-refresh:  0.12.0
    react-server-dom-turbopack-builtin:  undefined ()
    react-server-dom-turbopack-experimental-builtin:  undefined ()
    react-server-dom-webpack-builtin:  undefined ()
    react-server-dom-webpack-experimental-builtin:  undefined ()
    regenerator-runtime:  0.13.4
    sass-loader:  undefined ()
    scheduler-builtin:  undefined ()
    scheduler-experimental-builtin:  undefined ()
    schema-utils:  undefined ()
    semver:  undefined ()
    send:  undefined ()
    server-only:  0.0.1
    setimmediate:  undefined ()
    shell-quote:  undefined ()
    source-map:  undefined ()
    source-map08:  undefined ()
    stacktrace-parser:  undefined ()
    stream-browserify:  undefined ()
    stream-http:  undefined ()
    string-hash:  undefined ()
    string_decoder:  undefined ()
    strip-ansi:  undefined ()
    superstruct:  undefined ()
    tailwindcss: ^3.4.3 => 3.4.3
    tar:  undefined ()
    terser:  undefined ()
    text-table:  undefined ()
    timers-browserify:  undefined ()
    tsx: ^4.9.0 => 4.9.0
    tty-browserify:  undefined ()
    typescript: ^5.4.5 => 5.4.5 (4.4.4, 4.9.5)
    ua-parser-js:  undefined ()
    unistore:  undefined ()
    util:  undefined ()
    vm-browserify:  undefined ()
    watchpack:  undefined ()
    web-vitals:  undefined ()
    webpack:  undefined ()
    webpack-sources:  undefined ()
    ws:  undefined ()
    zod:  undefined ()
  npmGlobalPackages:
    @aws-amplify/cli: 12.10.3
    corepack: 0.22.0
    create-next-app: 14.2.3
    npm: 10.2.4

Describe the bug

Consider the use case in which a lambda function needs to use a custom mutation. Before v6.2 we could use allow.authenticated('iam'), however since the upgrade to v6.2 it doesn't work anymore.
Neither does the .authorization((allow) => [ allow.resource(...) ]) applied to the whole schema, this only works for non-custom queries and mutations.

Expected behavior

An authorization mechanism to authorize a lambda function to execute a custom mutation should exist

Reproduction steps

Define the schema:

const schema = a.schema({
  Impression: a.model({
    videoId: a.string().required(),
    impressions: a.integer().default(0)
  }).identifier(['videoId'])
    .authorization((allow) => [
      allow.publicApiKey(),
      allow.authenticated()
    ]),

  //Executes atomic increment operation on the impressions field of the Impression model
  increaseImpression: a
    .mutation()
    .arguments({
      videoId: a.string(),
      count: a.integer()
    })
    .returns(a.ref('Impression'))
    .authorization((allow) => [
      allow.authenticated()
    ])
    .handler(a.handler.custom({
      dataSource: a.ref('Impression'),
      entry: './increment-impression.js'
    })),
})
  .authorization((allow) => [
    allow.resource(incrementImpression),
  ]);

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
  schema,
  authorizationModes: {
    defaultAuthorizationMode: 'userPool',
    apiKeyAuthorizationMode: {}
  },
});

Define a function:

export const incrementImpression = defineFunction({
});

import { Amplify } from 'aws-amplify';
import { generateClient } from 'aws-amplify/data';
import { env } from '@env/increment-impression';
import { modelIntrospection } from '../../../amplifyconfiguration.json';
import { Schema } from '../../data/resource';

Amplify.configure(
  {
    API: {
      GraphQL: {
        endpoint: env.AMPLIFY_DATA_GRAPHQL_ENDPOINT, // replace with your defineData name
        region: env.AWS_REGION,
        defaultAuthMode: 'iam',
        modelIntrospection: modelIntrospection as never
      }
    }
  },
  {
    Auth: {
      credentialsProvider: {
        getCredentialsAndIdentityId: async () => ({
          credentials: {
            accessKeyId: env.AWS_ACCESS_KEY_ID,
            secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
            sessionToken: env.AWS_SESSION_TOKEN,
          },
        }),
        clearCredentialsAndIdentityId: () => {
          /* noop */
        },
      },
    },
  }
);

const dataClient = generateClient<Schema>();

export const handler = async (event: any) => {
const { data, errors } = await dataClient.mutations.increaseImpression({ videoId:'', count:10 }, { authMode: 'iam' });
    if (errors) {
      console.log('errors: ', errors);
    }
    console.log('data: ', data);
}

This results in the following error:

errors: [
{
path: [ 'increaseImpression' ],
data: null,
errorType: 'Unauthorized',
errorInfo: null,
locations: [ [Object] ],
message: 'Not Authorized to access increaseImpression on type Mutation'
}
]

Same problem can be seen by running the mutation from the AppSync console:
image
Unless the schema is manually edited and the @aws_iam is added to the increaseImpression declaration - then it works!

Code Snippet

// Put your code below this line.

Log output

// Put your logs below this line


aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

Metadata

Metadata

Labels

GraphQLRelated to GraphQL API issuespending-maintainer-responseIssue is pending a response from the Amplify team.questionGeneral question

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions