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.42k stars 2.12k forks source link

IAM auth for Appsync from Amplify/Next is (still)Broken #13121

Closed rexwreyes closed 5 months ago

rexwreyes commented 6 months ago

Before opening, please confirm:

JavaScript Framework

Next.js

Amplify APIs

GraphQL API

Amplify Version

v6

Amplify Categories

auth, api

Backend

None

Environment information

``` # Put output below this line System: OS: macOS 13.6.3 CPU: (8) x64 Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz Memory: 1.12 GB / 16.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 18.17.1 - /usr/local/bin/node Yarn: 1.22.19 - /usr/local/bin/yarn npm: 9.6.7 - /usr/local/bin/npm Browsers: Chrome: 122.0.6261.128 Safari: 17.2 npmPackages: @ampproject/toolbox-optimizer: undefined () @aws-amplify/adapter-nextjs: ^1.0.20 => 1.0.20 @aws-amplify/adapter-nextjs/api: undefined () @aws-amplify/adapter-nextjs/data: undefined () @aws-amplify/ui-react: ^6.0.6 => 6.0.6 @aws-amplify/ui-react-internal: undefined () @aws-sdk/client-bedrock-runtime: ^3.470.0 => 3.470.0 @babel/core: undefined () @babel/runtime: 7.22.5 @cloudscape-design/components: ^3.0.445 => 3.0.457 @cloudscape-design/design-tokens: ^3.0.34 => 3.0.34 @cloudscape-design/global-styles: ^1.0.16 => 1.0.17 @edge-runtime/cookies: 4.0.2 @edge-runtime/ponyfill: 2.4.1 @edge-runtime/primitives: 4.0.2 @hapi/accept: undefined () @mantine/code-highlight: ^7.6.0 => 7.6.0 @mantine/core: ^7.6.0 => 7.6.0 @mantine/form: ^7.6.0 => 7.6.0 @mantine/hooks: ^7.6.0 => 7.6.0 @mantine/modals: ^7.6.0 => 7.6.0 @mantine/notifications: ^7.6.1 => 7.6.1 @mswjs/interceptors: undefined () @napi-rs/triples: undefined () @next/bundle-analyzer: ^14.0.4 => 14.0.4 @next/font: undefined () @next/react-dev-overlay: undefined () @opentelemetry/api: undefined () @segment/ajv-human-errors: undefined () @tabler/icons-react: ^2.44.0 => 2.44.0 @types/node: ^20 => 20.10.4 @types/react: ^18 => 18.2.43 @types/react-dom: ^18 => 18.2.17 @vercel/nft: undefined () @vercel/og: 0.5.15 acorn: undefined () ai: ^2.2.29 => 2.2.29 amphtml-validator: undefined () anser: undefined () arg: undefined () assert: undefined () async-retry: undefined () async-sema: undefined () aws-amplify: ^6.0.20 => 6.0.20 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/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 () babel-packages: undefined () browserify-zlib: undefined () browserslist: undefined () buffer: undefined () bytes: undefined () ci-info: undefined () cli-select: undefined () client-only: 0.0.1 clsx: ^2.0.0 => 2.0.0 (1.2.1, 2.1.0) comment-json: undefined () compression: undefined () conf: undefined () constants-browserify: undefined () content-disposition: undefined () content-type: undefined () cookie: undefined () cross-spawn: undefined () crypto-browserify: undefined () css.escape: undefined () data-uri-to-buffer: undefined () dayjs: ^1.11.10 => 1.11.10 debug: undefined () devalue: undefined () domain-browser: undefined () edge-runtime: undefined () 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 () micromatch: undefined () mini-css-extract-plugin: undefined () nanoid: undefined () native-url: undefined () neo-async: undefined () next: ^14.0.4 => 14.0.4 node-fetch: undefined () node-html-parser: undefined () ora: undefined () os-browserify: undefined () p-limit: undefined () path-browserify: undefined () platform: undefined () 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 => 18.2.0 react-builtin: undefined () react-dom: ^18 => 18.2.0 react-dom-builtin: undefined () react-dom-experimental-builtin: undefined () react-experimental-builtin: undefined () react-hot-toast: ^2.4.1 => 2.4.1 react-intersection-observer: ^9.5.3 => 9.5.3 react-is: 18.2.0 react-markdown: ^9.0.1 => 9.0.1 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: ^1.71.1 => 1.71.1 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 () stacktrace-parser: undefined () stream-browserify: undefined () stream-http: undefined () string-hash: undefined () string_decoder: undefined () strip-ansi: undefined () superstruct: undefined () tar: undefined () terser: undefined () text-table: undefined () timers-browserify: undefined () tty-browserify: undefined () typescript: ^5 => 5.3.3 ua-parser-js: undefined () unistore: undefined () util: undefined () uuid: ^9.0.1 => 9.0.1 (8.3.2) vm-browserify: undefined () watchpack: undefined () web-vitals: undefined () webpack: undefined () webpack-sources: undefined () ws: undefined () zod: undefined () npmGlobalPackages: @aws-amplify/cli: 12.10.0 corepack: 0.18.0 n: 9.1.0 npm: 9.6.7 ```

Describe the bug

When trying to use IAM as the auth for AppSync calls i get an error. I am having the same issue described here : https://github.com/aws-amplify/amplify-js/issues/12931. t says that the issue was fixed with v6.0.17 but i tried v6.0.17 and v6.0.20 and still get the error. It all works if i just switch to apikey.

Expected behavior

To not get an error that tells me to "set the "authMode" in generateClient" even though I already did.

Reproduction steps

  1. Create Amplify App using CLI by following instructions from https://docs.amplify.aws/nextjs/start/
  2. Set up AppSync using CLI and choose IAM as auth
  3. Set up GraphQLClient for Server https://docs.amplify.aws/nextjs/build-a-backend/graphqlapi/connect-from-server-runtime/
  4. Try to load any page that does an AppSync call

Code Snippet

// cookieBasedClient.ts
import { Amplify } from 'aws-amplify'
import { generateServerClientUsingCookies } from '@aws-amplify/adapter-nextjs/api'
import { cookies } from 'next/headers'
import config from '@/amplifyconfiguration.json'

Amplify.configure(config, { ssr: true })

export const cookieBasedClient = generateServerClientUsingCookies({
  config: config,
  cookies,
  authMode: 'iam'
})

console.debug('cookiesClient', cookieBasedClient)

//page.tsx
import React from 'react'
import { cookies } from 'next/headers'
import { cookieBasedClient } from '@/utils/cookieBasedClient'
import { projectsByUserIdAndCreatedAt } from '@/graphql/queries'
import type { Project } from '@/graphql/API'
import Projects from '@/components/projects'

export default async function Page() {
  const cookieStore = cookies()
  const userid = cookieStore.get('userid')?.value ?? ''
  const projectscall = (await cookieBasedClient.graphql({
    query: projectsByUserIdAndCreatedAt,
    variables: {
      userId: userid,
      filter: {
        _deleted: {
          ne: true,
        },
      },
    },
  })) as {
    data: {
      projectsByUserIdAndCreatedAt: {
        items: Project[]
      }
    }
  }
  const prjlist = projectscall.data.projectsByUserIdAndCreatedAt.items

  return <Projects projects={prjlist} userid={userid} />
}

Log output

``` // Put your logs below this line ⨯ { data: {}, errors: [ UnauthorizedException: Unknown error at buildRestApiError (webpack-internal:///(rsc)/./node_modules/@aws-amplify/api-rest/dist/esm/utils/serviceError.mjs:85:26) at parseRestApiServiceError (webpack-internal:///(rsc)/./node_modules/@aws-amplify/api-rest/dist/esm/utils/serviceError.mjs:28:16) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async job (webpack-internal:///(rsc)/./node_modules/@aws-amplify/api-rest/dist/esm/utils/createCancellableOperation.mjs:31:23) at async GraphQLAPIClass._graphql (webpack-internal:///(rsc)/./node_modules/@aws-amplify/api-graphql/dist/esm/internals/InternalGraphQLAPI.mjs:239:44) at async wrapper (webpack-internal:///(rsc)/./node_modules/@aws-amplify/api-graphql/dist/esm/internals/InternalGraphQLAPI.mjs:134:40) at async runWithAmplifyServerContext (webpack-internal:///(rsc)/./node_modules/aws-amplify/dist/esm/adapterCore/runWithAmplifyServerContext.mjs:23:24) at async Page (webpack-internal:///(rsc)/./src/app/projects/page.tsx:24:26) { recoverySuggestion: `If you're calling an Amplify-generated API, make sure to set the "authMode" in generateClient({ authMode: '...' }) to the backend authorization rule's auth provider ('apiKey', 'userPool', 'iam', 'oidc', 'lambda')` } ] } ⨯ [Error: Error: [object Object]] { digest: '193452068' }

aws-exports.js


  "aws_project_region": "us-west-2",
  "aws_appsync_graphqlEndpoint": "https://haithere.appsync-api.us-west-2.amazonaws.com/graphql",
  "aws_appsync_region": "us-west-2",
  "aws_appsync_authenticationType": "AWS_IAM",
  "aws_appsync_apiKey": "da2-haithere",
  "aws_cognito_identity_pool_id": "us-west-2:haithere",
  "aws_cognito_region": "us-west-2",
  "aws_user_pools_id": "us-west-2_haithere",
  "aws_user_pools_web_client_id": "haithere",
  "oauth": {},
  "aws_cognito_username_attributes": [
    "EMAIL"
  ],
  "aws_cognito_social_providers": [],
  "aws_cognito_signup_attributes": [
    "EMAIL"
  ],
  "aws_cognito_mfa_configuration": "OFF",
  "aws_cognito_mfa_types": [],
  "aws_cognito_password_protection_settings": {
    "passwordPolicyMinLength": 8,
    "passwordPolicyCharacters": [
      "REQUIRES_LOWERCASE",
      "REQUIRES_UPPERCASE",
      "REQUIRES_NUMBERS",
      "REQUIRES_SYMBOLS"
    ]
  },
  "aws_cognito_verification_mechanisms": [
    "EMAIL"
  ]
}

### 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_
chrisbonifacio commented 6 months ago

Hi @rexwreyes 👋 thanks for raising this issue. I have not been able to reproduce it on the latest version of aws-amplify and @aws-amplify/adapter-nextjs

However, I did notice that you are calling Amplify.configure with ssr: true in the same file you are generating the cookie based client. Are you configuring Amplify anywhere else in your app?

Amplify.configure should be called on the client side, the ssr: true makes it so that credentials are stored in cookies rather than local storage and sent to the server on SSR page requests.

If moving Amplify.configure to an entry point file such as layout.tsx doesn't work, another thing I would try is setting the authMode on the request.

(await cookieBasedClient.graphql({
    query: projectsByUserIdAndCreatedAt,
    variables: {
      userId: userid,
      filter: {
        _deleted: {
          ne: true,
        },
      },
    },
    authMode: "iam",
  })) as {
    data: {
      projectsByUserIdAndCreatedAt: {
        items: Project[];
      };
    };
  };

If that still doesn't work, then I would ask if you can provide a small sample app (could be a public github repo) that reproduces the issue consistently .

cwomack commented 5 months ago

Closing this issue as we have not heard back from you. If you are still experiencing this, please feel free to reply back and provide any information previously requested and we'd be happy to re-open the issue.

Thank you!