amplify-js: Undocumented breaking change: unauthenticated user can't call GraphQL APIs after upgrading from V5 to V6

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

Authentication, GraphQL API

Amplify Categories

Not applicable

Environment information

# Put output below this line

System:
    OS: macOS 14.2
    CPU: (16) arm64 Apple M3 Max
    Memory: 4.18 GB / 48.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.10.0 - ~/.nvm/versions/node/v18.10.0/bin/node
    npm: 8.19.2 - ~/.nvm/versions/node/v18.10.0/bin/npm
  Browsers:
    Chrome: 120.0.6099.109
    Safari: 17.2
  npmPackages:
    @aws-amplify/ui-react: ^6.0.6 => 6.0.6
    @aws-amplify/ui-react-internal:  undefined ()
    @emotion/react: ^11.11.1 => 11.11.1
    @flesh-and-blood/cards: ^0.0.128 => 0.0.128
    @flesh-and-blood/search: ^0.0.128 => 0.0.128
    @flesh-and-blood/types: ^0.0.128 => 0.0.128
    @fortawesome/fontawesome-pro: ^6.5.1 => 6.5.1
    @fortawesome/fontawesome-svg-core: ^6.5.1 => 6.5.1
    @fortawesome/free-brands-svg-icons: ^6.5.1 => 6.5.1
    @fortawesome/pro-duotone-svg-icons: ^6.5.1 => 6.5.1
    @fortawesome/pro-light-svg-icons: ^6.5.1 => 6.5.1
    @fortawesome/pro-regular-svg-icons: ^6.5.1 => 6.5.1
    @fortawesome/pro-solid-svg-icons: ^6.5.1 => 6.5.1
    @fortawesome/pro-thin-svg-icons: ^6.5.1 => 6.5.1
    @fortawesome/react-fontawesome: ^0.2.0 => 0.2.0
    @mdx-js/react: ^2.3.0 => 2.3.0
    @popperjs/core: ^2.11.8 => 2.11.8
    @testing-library/jest-dom: ^5.17.0 => 5.17.0
    @testing-library/react: ^14.1.2 => 14.1.2
    @testing-library/user-event: ^14.5.1 => 14.5.1
    @theme-ui/color-modes: ^0.16.1 => 0.16.1
    @theme-ui/presets: ^0.16.1 => 0.16.1
    @tiptap/extension-blockquote: ^2.1.13 => 2.1.13
    @tiptap/extension-bold: ^2.1.13 => 2.1.13
    @tiptap/extension-bullet-list: ^2.1.13 => 2.1.13
    @tiptap/extension-character-count: ^2.1.13 => 2.1.13
    @tiptap/extension-code: ^2.1.13 => 2.1.13
    @tiptap/extension-code-block: ^2.1.13 => 2.1.13
    @tiptap/extension-document: ^2.1.13 => 2.1.13
    @tiptap/extension-dropcursor: ^2.1.13 => 2.1.13
    @tiptap/extension-gapcursor: ^2.1.13 => 2.1.13
    @tiptap/extension-hard-break: ^2.1.13 => 2.1.13
    @tiptap/extension-heading: ^2.1.13 => 2.1.13
    @tiptap/extension-highlight: ^2.1.13 => 2.1.13
    @tiptap/extension-history: ^2.1.13 => 2.1.13
    @tiptap/extension-horizontal-rule: ^2.1.13 => 2.1.13
    @tiptap/extension-italic: ^2.1.13 => 2.1.13
    @tiptap/extension-link: ^2.1.13 => 2.1.13
    @tiptap/extension-list-item: ^2.1.13 => 2.1.13
    @tiptap/extension-mention: ^2.1.13 => 2.1.13
    @tiptap/extension-ordered-list: ^2.1.13 => 2.1.13
    @tiptap/extension-paragraph: ^2.1.13 => 2.1.13
    @tiptap/extension-placeholder: ^2.1.13 => 2.1.13
    @tiptap/extension-strike: ^2.1.13 => 2.1.13
    @tiptap/extension-text: ^2.1.13 => 2.1.13
    @tiptap/extension-typography: ^2.1.13 => 2.1.13
    @tiptap/extension-underline: ^2.1.13 => 2.1.13
    @tiptap/react: ^2.1.13 => 2.1.13
    @tiptap/suggestion: ^2.1.13 => 2.1.13
    @types/jest: ^29.5.11 => 29.5.11
    @types/node: ^20.10.4 => 20.10.4
    @types/papaparse: ^5.3.14 => 5.3.14
    @types/react: ^18.2.43 => 18.2.43
    @types/react-dom: ^18.2.17 => 18.2.17
    @types/react-flatpickr: ^3.8.11 => 3.8.11
    @types/react-helmet: ^6.1.11 => 6.1.11
    @types/sanitize-html: ^2.9.5 => 2.9.5
    @types/styled-components: ^5.1.34 => 5.1.34
    algoliasearch: ^4.20.0 => 4.20.0
    aws-amplify: ^6.0.7 => 6.0.7
    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 ()
    chart.js: ^4.4.1 => 4.4.1
    chart.js-auto:  undefined ()
    chart.js-helpers:  undefined ()
    chartjs-plugin-annotation: ^3.0.1 => 3.0.1
    chartjs-plugin-datalabels: ^2.2.0 => 2.2.0
    classnames: ^2.3.2 => 2.3.2
    countries-and-timezones: ^3.5.2 => 3.5.2
    graphql: ^16.8.1 => 16.8.1 (15.8.0)
    graphql-tag: ^2.12.6 => 2.12.6
    html2pdf.js: ^0.10.1 => 0.10.1
    i18next: ^22.5.1 => 22.5.1
    i18next-browser-languagedetector: ^7.2.0 => 7.2.0
    idb-keyval: ^6.2.1 => 6.2.1
    integration_tests_auth_server:  1.0.0
    netlify-plugin-ttl-cache: ^1.0.2 => 1.0.2
    p-limit: ^4.0.0 => 4.0.0 (3.1.0, 2.3.0)
    papaparse: ^5.4.1 => 5.4.1
    pusher-js: ^8.3.0 => 8.3.0
    qrcode.react: ^3.1.0 => 3.1.0
    react: ^18.2.0 => 18.2.0
    react-chartjs-2: ^5.2.0 => 5.2.0
    react-countdown: ^2.3.5 => 2.3.5
    react-css-transition-replace: ^5.0.1 => 5.0.1
    react-dom: ^18.2.0 => 18.2.0
    react-dropzone: ^14.2.3 => 14.2.3
    react-flatpickr: ^3.10.13 => 3.10.13
    react-helmet: ^6.1.0 => 6.1.0
    react-i18next: ^11.18.6 => 11.18.6
    react-instantsearch-hooks-web: ^6.47.3 => 6.47.3
    react-markdown: ^8.0.7 => 8.0.7
    react-modal: ^3.16.1 => 3.16.1
    react-popper: ^2.3.0 => 2.3.0
    react-popper-tooltip: ^4.4.2 => 4.4.2
    react-router-dom: ^6.20.1 => 6.20.1
    react-scripts: 5.0.1 => 5.0.1
    react-tabs: ^6.0.2 => 6.0.2
    react-terminal: ^1.4.4 => v1.4.4
    sanitize-html: ^2.11.0 => 2.11.0
    semver: ^7.5.4 => 7.5.4 (6.3.1)
    source-map-explorer: ^2.5.3 => 2.5.3
    styled-components: ^5.3.11 => 5.3.11
    styled-components/macro:  undefined ()
    styled-components/native:  undefined ()
    styled-components/primitives:  undefined ()
    swiper: ^10.3.1 => 10.3.1
    theme-ui: ^0.16.1 => 0.16.1
    tippy-headless:  0.1.0
    tippy.js: ^6.3.7 => 6.3.7
    ts-node: ^10.9.2 => 10.9.2
    typescript: 4.9.5 => 4.9.5
    web-vitals: ^3.5.0 => 3.5.0
  npmGlobalPackages:
    corepack: 0.14.1
    npm-check-updates: 16.14.11
    npm: 8.19.2

Describe the bug

While upgrading from V5 > V6 I’ve found a blocker issue / breaking change that I can’t find documentation for and am unable to complete the migration without a fix - either in my setup or in the lib.

  • I manage the GraphQL endpoint outside of the Amplify CLI
  • I’m using AWS Cognito for GraphQL Auth
  • I have authenticated and unauthenticated IdentityPool roles
  • After upgrading to V6, GraphQL calls for unauthenticated users fail in the browser (before calling the endpoint)

Error: No credentials at GraphQLAPIClass._headerBasedAuth

Thank you so much for your help with this issue, and my sincerest apologies if I’m missing a step from the upgrade guide - I’ve tried multiple times going through it but it feels like this could be a config error.

Expected behavior

  • GraphQL API calls for unauthenticated users succeed

Reproduction steps

  • See Code Snippets below for V5 and V6 config

Code Snippet

CloudFormation GraphQL Authentication configuration

IdentityPoolRoleMapping:
  Type: AWS::Cognito::IdentityPoolRoleAttachment
  Properties:
    IdentityPoolId: !Ref IdentityPool
    Roles:
      authenticated: !GetAtt AuthenticatedRole.Arn
      unauthenticated: !GetAtt UnauthenticatedRole.Arn

React V5 GraphQL call

const result = await API.graphql({
  query: gql`
    query searchCards($text: String!) {
      searchCards(text: $text) {
        ...MinimalCard
      }
    }
    ${minimalCardFragment}
  `,
  variables: {
    text: searchCriteria,
  },
  authMode: authenticated ? "AMAZON_COGNITO_USER_POOLS" : "AWS_IAM",
});

React V5 Amplify Configuration

Amplify.configure({
  Auth: {
    identityPoolId: process.env.REACT_APP_IDENTITY_POOL_ID,
    mandatorySignIn: false,
    region: process.env.REACT_APP_AWS_REGION,
    userPoolId: process.env.REACT_APP_USER_POOL_ID,
    userPoolWebClientId: process.env.REACT_APP_USER_POOL_WEB_CLIENT_ID,
  },
});

const appsyncConfig = {
  aws_appsync_graphqlEndpoint: process.env.REACT_APP_APPSYNC_GRAPHQL_ENDPOINT,
  aws_appsync_region: process.env.REACT_APP_AWS_REGION,
  aws_appsync_authenticationType: "AMAZON_COGNITO_USER_POOLS",
};
Amplify.configure(appsyncConfig);

React V6 GraphQL call

const result = await client.graphql({
  query: gql`
    query searchCards($text: String!) {
      searchCards(text: $text) {
        ...MinimalCard
      }
    }
    ${minimalCardFragment}
  `,
  variables: {
    text: searchCriteria,
  },
  authMode: authenticated ? "userPool" : "iam",
});

React V6 Amplify Configuration

Amplify.configure({
  API: {
    GraphQL: {
      defaultAuthMode: "iam",
      endpoint: process.env.REACT_APP_APPSYNC_GRAPHQL_ENDPOINT as string,
      region: process.env.REACT_APP_AWS_REGION as string,
    },
  },
  Auth: {
    Cognito: {
      identityPoolId: process.env.REACT_APP_IDENTITY_POOL_ID as string,
      userPoolId: process.env.REACT_APP_USER_POOL_ID as string,
      userPoolClientId: process.env.REACT_APP_USER_POOL_WEB_CLIENT_ID as string,
    },
  },
});

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

About this issue

  • Original URL
  • State: open
  • Created 7 months ago
  • Reactions: 1
  • Comments: 16 (5 by maintainers)

Most upvoted comments

FWIW anybody who is trying to get unauthenticated identity pool access to use with an external provider if you enable allowGuestAccess: true in the amplify config fetchAuthSession will automatically return the session token when not logged in.

For example,

export const config : ResourcesConfig= {
    Auth: {
      Cognito: {
        userPoolId: process.env.NEXT_PUBLIC_COGNITO_USER_POOL_ID!,
        userPoolClientId: process.env.NEXT_PUBLIC_COGNITO_CLIENT_ID!,
        identityPoolId: process.env.NEXT_PUBLIC_COGNITO_IDENTITY_POOL_ID!,
        allowGuestAccess: true,
      },
    },
  }

If your Identity Pool is setup correctly

const session = await fetchAuthSession()

session will be

{
  "credentials": {
    "accessKeyId": "KEY_ID",
    "secretAccessKey": "ACCESS_KEY",
    "sessionToken": "TOKEN",
    "expiration": "DATETIME"
  },
  "identityId": "ap-southeast-2:UUID"
}

and you can check if this session is defined versus a cognito session with a token.

Thanks @kochie

when making config changes I removed “mandatorySignIn: false” but didn’t replace it with “allowGuestAccess: true”

Yes, I use a CDK stack that uses Appsync to provide an external GraphQL API. Yesterday I found a solution for my specific problem. I had forgotten the little keyword “setup” in <script setup> in my Vue3 application. Now it works.