aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.43k stars 2.13k forks source link

"IAM" unauthorized for custom mutations #13506

Closed jewells07 closed 4 months ago

jewells07 commented 4 months ago

Before opening, please confirm:

JavaScript Framework

Vue

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: (12) x64 Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz Memory: 690.76 MB / 7.91 GB Binaries: Node: 20.14.0 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD npm: 10.7.0 - C:\Program Files\nodejs\npm.CMD pnpm: 9.3.0 - ~\AppData\Local\pnpm\pnpm.EXE Browsers: Edge: Chromium (126.0.2592.56) Internet Explorer: 11.0.22621.3527 npmPackages: %name%: 0.1.0 @aws-amplify/backend: ^1.0.3 => 1.0.3 @aws-amplify/backend-cli: ^1.0.4 => 1.0.4 @commitlint/cli: ^19.3.0 => 19.3.0 @commitlint/config-conventional: ^19.2.2 => 19.2.2 @nuxt/eslint: ^0.3.13 => 0.3.13 @pinia/nuxt: ^0.5.1 => 0.5.1 @quasar/extras: ^1.16.11 => 1.16.11 aws-amplify: ^6.3.6 => 6.3.6 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.145.0 => 2.145.0 aws-cdk-lib: ^2.145.0 => 2.145.0 constructs: ^10.3.0 => 10.3.0 esbuild: ^0.21.5 => 0.21.5 (0.20.2) eslint: ^9.4.0 => 9.4.0 husky: ^9.0.11 => 9.0.11 lint-staged: ^15.2.6 => 15.2.7 nuxt: ^3.12.1 => 3.12.1 nuxt-quasar-ui: ^2.1.2 => 2.1.2 pinia: ^2.1.7 => 2.1.7 prettier: ^3.3.2 => 3.3.2 (2.3.2, 2.8.8, 1.19.1) quasar: ^2.16.4 => 2.16.4 tsx: ^4.15.4 => 4.15.4 typescript: ^5.4.5 => 5.4.5 (4.4.4, 4.9.5) vue: ^3.4.27 => 3.4.27 vue-router: ^4.3.3 => 4.3.3 npmGlobalPackages: @aws-amplify/cli: 12.12.2 corepack: 0.28.1 npm: 10.7.0 ```

Describe the bug

I have "PostConfirmationTriggerHandler" on auth. When the user successfully creates (signup) it, it will trigger and create user profile data. So on PostConfirmationTriggerHandler, I am trying to call mutation to create a user profile; It gives me error 'Not Authorized to access CreatingUserProfile on type Mutation'. I have followed these steps. https://docs.amplify.aws/vue/build-a-backend/functions/examples/create-user-profile-record/, but with mutations

Expected behavior

It should authorized "iam" for mutation

Reproduction steps

In amplify/data/resource.ts

    CreatingUserProfile: a
      .mutation()
      .arguments({
        owner: a.string().required(),
        firstName: a.string().required(),
        lastName: a.string().required(),
        email: a.email().required(),
        birthdate: a.datetime().required(),
        location: a.string(),
      })
      .returns(a.ref('UserProfile'))
      .handler([
        a.handler.custom({
          entry: './userProfile/createUserProfile.js',
          dataSource: a.ref('UserProfile'),
        }),
      ])
      .authorization((allow) => [allow.authenticated()])

In amplify/auth/post-confirmation/handler.ts

export const handler: PostConfirmationTriggerHandler = async (event) => {
  try {
    const res = await client.graphql({
      query: CreatingUserProfile,
      variables: {
        firstName: event.request.userAttributes.given_name,
        lastName: event.request.userAttributes.family_name,
        email: event.request.userAttributes.email,
        birthdate: convertToISOStringExtended(event.request.userAttributes.birthdate),
        owner: `${event.request.userAttributes.sub}::${event.userName}`,
      },
      authMode: 'iam',
    });
    console.log('res', res);
  } catch (error: any) {
    console.log('ERROR HERE', error);
    throw new Error(`Failed to create user profile: ${error.message}`);
  }
  return event;
};

image

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

david-mcafee commented 4 months ago

Hi @jewells07 - thanks for creating this ticket! Looking at your amplify/auth/post-confirmation/handler.ts, it does not include an example of your call to Amplify.configure, nor the generation of the API client. To help us better reproduce the issue, can you please include the complete code examples for the following?

  1. amplify/auth/post-confirmation/handler.ts - to see how you are configuring Amplify within the handler.
  2. amplify/auth/resource.ts
  3. amplify/data/resource.ts - I'd like to see how you are configuring the authorization rule to allow the postConfirmation resource.

Lastly, I wanted to point out that unlike the docs you linked to above, it appears that you're missing the nested input within the variables input. In your case, your call to client.graphql should be as follows:

const res = await client.graphql({
    query: CreatingUserProfile,
    variables: {
        input: {
            firstName: event.request.userAttributes.given_name,
            lastName: event.request.userAttributes.family_name,
            email: event.request.userAttributes.email,
            birthdate: convertToISOStringExtended(event.request.userAttributes.birthdate),
            owner: `${event.request.userAttributes.sub}::${event.userName}`,
        },
    },
});
jewells07 commented 4 months ago

it works now.


const client = generateClient<Schema>({
  authMode: 'iam',
});

export const handler: PostConfirmationTriggerHandler = async (event) => {
  try {
    await client.graphql({
      query: createUserProfile,
      variables: {
        input: {
          firstName: event.request.userAttributes.given_name,
          lastName: event.request.userAttributes.family_name,
          email: event.request.userAttributes.email,
          birthdate: convertToISOStringExtended(event.request.userAttributes.birthdate),
          owner: `${event.request.userAttributes.sub}::${event.userName}`,
        },
      },
    });
  } catch (error: any) {
    throw new Error(`Failed to create user profile: ${error.message}. full error ${error}`);
  }
  return event;
};