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.4k stars 2.11k forks source link

V6 Unauthenticated `post` request throws `NoCredentials` error unless `Authorization` header is present #12687

Closed chrisbonifacio closed 6 months ago

chrisbonifacio commented 7 months ago

Before opening, please confirm:

JavaScript Framework

React, Next.js

Amplify APIs

REST API

Amplify Categories

api

Environment information

``` System: OS: macOS 13.5.2 CPU: (12) arm64 Apple M2 Pro Memory: 102.36 MB / 32.00 GB Shell: 3.6.1 - /usr/local/bin/fish Binaries: Node: 18.17.0 - /usr/local/bin/node Yarn: 1.22.21 - ~/.nvm/versions/node/v20.10.0/bin/yarn npm: 10.1.0 - /usr/local/bin/npm pnpm: 8.11.0 - ~/.nvm/versions/node/v20.10.0/bin/pnpm Watchman: 2023.11.20.00 - /opt/homebrew/bin/watchman Browsers: Chrome: 119.0.6045.199 Edge: 119.0.2151.97 Safari: 17.1.2 npmPackages: @ampproject/toolbox-optimizer: undefined () @aws-amplify/backend: ^0.5.5 => 0.5.5 @aws-amplify/backend-cli: ^0.9.1 => 0.9.1 @babel/core: undefined () @babel/runtime: 7.22.5 @edge-runtime/cookies: 4.0.2 @edge-runtime/ponyfill: 2.4.1 @edge-runtime/primitives: 4.0.2 @hapi/accept: undefined () @mswjs/interceptors: undefined () @napi-rs/triples: undefined () @next/font: undefined () @next/react-dev-overlay: undefined () @opentelemetry/api: undefined () @segment/ajv-human-errors: undefined () @types/node: ^20 => 20.10.3 @types/react: ^18 => 18.2.41 @types/react-dom: ^18 => 18.2.17 @vercel/nft: undefined () @vercel/og: 0.5.15 acorn: undefined () amphtml-validator: undefined () anser: undefined () arg: undefined () assert: undefined () async-retry: undefined () async-sema: undefined () autoprefixer: ^10.0.1 => 10.4.16 aws-amplify: ^6.0.6 => 6.0.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/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 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 () debug: undefined () devalue: undefined () domain-browser: undefined () edge-runtime: undefined () eslint: ^8 => 8.55.0 eslint-config-next: 14.0.3 => 14.0.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 () micromatch: undefined () mini-css-extract-plugin: undefined () nanoid: undefined () native-url: undefined () neo-async: undefined () next: 14.0.3 => 14.0.3 node-fetch: undefined () node-html-parser: undefined () ora: undefined () os-browserify: undefined () p-limit: undefined () path-browserify: undefined () platform: undefined () postcss: ^8 => 8.4.32 (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 => 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-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 () stacktrace-parser: undefined () stream-browserify: undefined () stream-http: undefined () string-hash: undefined () string_decoder: undefined () strip-ansi: undefined () superstruct: undefined () tailwindcss: ^3.3.0 => 3.3.5 tar: undefined () terser: undefined () text-table: undefined () timers-browserify: undefined () tty-browserify: undefined () typescript: ^5.3.2 => 5.3.2 (4.4.4) 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.8.0-rds-5.0 @capacitor/assets: 3.0.1 @ionic/cli: 7.1.1 aws-cdk: 2.109.0 corepack: 0.18.0 eas-cli: 5.4.0 npm: 10.1.0 ts-node: 10.9.1 ```

Describe the bug

Following this guide: https://docs.amplify.aws/javascript/build-a-backend/restapi/set-up-rest-api/

Trying to perform post request without Authorization headers results in the following error:

POST call failed:  NoCredentials: Credentials should not be empty.

Adding an arbitrary Authorization header and value allows the request to be sent and succeeds.

UPDATE: other methods (get, put, del) also throw the same error.

Expected behavior

I expect an unauthenticated request to an unrestricted REST API not to require an Authorization header

Reproduction steps

Follow guide: https://docs.amplify.aws/javascript/build-a-backend/restapi/set-up-rest-api/

Code Snippet

Doesn't work

post({
  apiName: "todoApi",
  path: "/todo",
  options: {
    body: {
      message: "Mow the lawn",
    },
  },
});

Works

post({
  apiName: "todoApi",
  path: "/todo",
  options: {
    body: {
      message: "Mow the lawn",
    },
    headers: {
      Authorization: "test",
    },
  },
});

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

cwomack commented 6 months ago

Thanks for opening this @chrisbonifacio. Marking this as a bug for now.

willjstevens commented 6 months ago

+1 on "aws-amplify": "^6.0.6"

mighty6ft5max commented 6 months ago

Exact same issue here. Worked with the "test" Authorization. "aws-amplify": "^6.0.7"

willjstevens commented 6 months ago

The problem of using the "test" workaround is it dominos into another error.

Access to fetch at 'https://XXXXX1wk0.execute-api.us-east-2.amazonaws.com/prod/abc123/xxxxxx7709' from origin 'https://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I believe this to be it needs Cognito signatures in subsequent API methods (get, post) for CORS calls. And yes, I tried adding headers like retval.headers = { Authorization: "test", "Access-Control-Allow-Origin": "*" };

@cwomack please let me know if this is planned to be resolved soon or else I will revert to Amplify v5. Thnx.

mighty6ft5max commented 6 months ago

The problem of using the "test" workaround is it dominos into another error.


Access to fetch at 'https://XXXXX1wk0.execute-api.us-east-2.amazonaws.com/prod/abc123/xxxxxx7709' from origin 'https://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I believe this to be it needs Cognito signatures in subsequent API methods (get, post) for CORS calls. And yes, I tried adding headers like ```retval.headers = {

    Authorization: "test",

    "Access-Control-Allow-Origin": "*"

};```

@cwomack please let me know if this is planned to be resolved soon or else I will revert to Amplify v5. Thnx.

In your lambda's response you should have the CORS permission.

willjstevens commented 6 months ago

You are right, but back to the workaround - when you do this:

headers: {
      Authorization: "test",
    },

It is overwriting the headers object with a new object you are providing, with one header in it, the Authorization with a placeholder value. This is opposed to an 'internal' headers object, managed by Amplify, which I am assuming Cognito injects or manages its headers. Headers that are dynamically generated by Amplify and/or Cognito with real runtime signature values. Therefore setting your own "headers" object with a bogus "Authorization" property overwrites that should be managed by the library. It might work for a simple post or get, but I am assuming not backed by a real identity manager requiring real signature values.

AllanZhengYP commented 6 months ago

Hi @willjstevens @mighty6ft5max

I can confirm this is indeed a regression. I'm working a fix right now. In short term you can workaround the issue by setting Authorization header to any string value. I will post here when the fix is up.

jimblanc commented 6 months ago

@chrisbonifacio A fix for this made it out with Amplify 6.0.10, could you please check if the issue has been resolved for you?

chrisbonifacio commented 6 months ago

@chrisbonifacio A fix for this made it out with Amplify 6.0.10, could you please check if the issue has been resolved for you?

@jimblanc just updated and tried it out, all good now! Thanks! 🙏