Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Undocumented breaking change: unauthenticated user can't call GraphQL APIs after upgrading from V5 to V6 #12710

Closed
3 tasks done
manwaring opened this issue Dec 14, 2023 · 17 comments
Assignees
Labels
GraphQL Related to GraphQL API issues investigating This issue is being investigated question General question React React related issues V6 V6 of Amplify JS

Comments

@manwaring
Copy link

manwaring commented Dec 14, 2023

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

@manwaring manwaring added the pending-triage Issue is pending triage label Dec 14, 2023
@nadetastic nadetastic added the GraphQL Related to GraphQL API issues label Dec 14, 2023
@daudiihhdau
Copy link

Same problem here

@cwomack cwomack added the to-be-reproduced Used in order for Amplify to reproduce said issue label Dec 18, 2023
@cwomack cwomack added investigating This issue is being investigated and removed pending-triage Issue is pending triage labels Dec 18, 2023
@cwomack
Copy link
Member

cwomack commented Dec 18, 2023

Possibly related to #12687 (although that one is REST API).

@daudiihhdau, is your AppSync API managed by Amplify? Or do you also have the GraphQL endpoints managed outside of Amplify?

@daudiihhdau
Copy link

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.

@chrisbonifacio
Copy link
Member

Ah, nice catch! Thanks for letting us know the cause of the issue, that rules out that this might've been related to the REST API issue, so that's good to know 🙏

@chrisbonifacio chrisbonifacio added Vue Related to Vue Framework issues V6 V6 of Amplify JS and removed to-be-reproduced Used in order for Amplify to reproduce said issue investigating This issue is being investigated labels Dec 20, 2023
@manwaring
Copy link
Author

manwaring commented Dec 20, 2023

@chrisbonifacio I opened this issue and I'm glad it's working now for @daudiihhdau but the issue is still unresolved for my app. My app is also React and not Vue as far as issue tagging for triage/support.

@daudiihhdau was the missing setup keyword something that is Vue specific, or is this a keyword you needed to include in your Amplify config? I've been searching the Amplify documentation to see if it's something I also missed in my app config but couldn't find anything.

@chrisbonifacio
Copy link
Member

chrisbonifacio commented Dec 20, 2023

My apologies, @manwaring, I confused who was the OP 😅

Reopened.

I'd be curious to see what the request headers and response look like for the failing graphql queries. Can you share those details from the network activity?

Or is there not even a request being sent? Just the error being thrown?

One other thing that might be worth looking at is the value of authenticated that determines whether to use cognito or iam. Is it what you'd expect it to be?

@chrisbonifacio chrisbonifacio added investigating This issue is being investigated React React related issues and removed Vue Related to Vue Framework issues labels Dec 20, 2023
@daudiihhdau
Copy link

Hello,

here is the crucial code snippet from my Vue3 app.
Hopefully it will also help with your React app.

import { createApp } from 'vue'
import App from './App.vue'

// https://docs.amplify.aws/javascript/tools/libraries/configure-categories/
import { Amplify } from 'aws-amplify';
import { Hub } from 'aws-amplify/utils';

// configure amplify
import amplifyconfig from '../amplifyconfiguration.json';
const redirectUri = (process.env.NODE_ENV == "development") ? "http://localhost:5173" : "https://dev.XYZ.amplifyapp.com"

let config = {
  ...amplifyconfig,
  "aws_appsync_graphqlEndpoint": "https://abc.appsync-api.eu-central-1.amazonaws.com/graphql",
  "aws_appsync_region": "eu-central-1",
  "aws_appsync_authenticationType": "AMAZON_COGNITO_USER_POOLS",
  "aws_appsync_apiKey": "da2-xyz",
  "oauth": {
    "domain": "myappname.auth.eu-central-1.amazoncognito.com", // cognito domain
    "scope": ['email', 'profile', 'openid'],
    "redirectSignIn": redirectUri,
    "redirectSignOut": redirectUri,
    "responseType": 'code'
   },
}
console.log(config)
Amplify.configure(config)

The missing setup keyword is Vue specific. It starts the Vue3 Composition API.

@sascha93
Copy link

sascha93 commented Dec 25, 2023

Hey guys, I've had a similar problem, had a long call with AWS support.
The claims from Cognito are not sent to lambda in V6.
Here is my current AWS config:

Amplify.configure(
  {
    Auth: {
      Cognito: {
        region: process.env.AWS_REGION,
        userPoolId: process.env.USER_POOL_ID,
        userPoolClientId: process.env.USER_POOL_WEB_ID,
      },
    },
    API: {
      GraphQL: {
        endpoint: process.env.GRAPH_QL_ENDPOINT,
        region: process.env.AWS_REGION,
        defaultAuthMode: "userPool",
      },
    },
  },
  {
    API: {
      GraphQL: {
        headers: async () => ({
          Authorization: (await fetchAuthSession()).tokens?.idToken?.toString(),
        }),
      },
    },
  },
);

Here also an example GraphQL call:

export const listWebsites = async () => {
  const result = await client.graphql({
    query: gql`
      query listWebsites {
        listWebsites {
          websiteId
          name
          createdAt
          lastModified
        }
      }
    `,
    authMode: 'userPool'
  });

  return result.data.listWebsites;
};

Maybe it helps someone :)

@kochie
Copy link

kochie commented Jan 18, 2024

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.

@gzimbron
Copy link

I solved this, by upgrading aws-amplify to 6.0.16

@rmjwilbur
Copy link

Thanks @kochie

when making config changes I removed "mandatorySignIn: false" but didn't replace it with "allowGuestAccess: true"

@mattiLeBlanc
Copy link

I am having the exact same issue getting an Error: No credentials when I am calling a Grapql Query that is annotated with @aws_iam only.
With Amplify 5.6 I had no problem accessing this by providing authMode = IAM (as described by the main author of this issue).
Now I use iam or userPool. For userPool it works as expected but when I am not authenticated and do a call to an endpoint using my identity pool, it throws that error.

I read through these comments and adding allowGuestAccess: true, to my awsConfig solved it.

So my question is; is that the recommended solution or is that a shortcut/hack?

@chrisbonifacio
Copy link
Member

chrisbonifacio commented Feb 26, 2024

@mattiLeBlanc from what I know, there were two different issues folks were running into with iam as an auth mode. Historically, enabling unauthenticated access via the Amplify CLI was a step that could be missed by some and is required for the Amplify graphql client to use the UnauthRole and sign requests. This can also now be enabled on the Amplify configuration using the allowGuestAccess field on the Auth.Cognito resource config option and is the recommended approach.

There was a separate issue regarding using public iam as an auth mode in SSR apps. This was fixed recently in last week's release (v6.0.17).

@mattiLeBlanc
Copy link

@chrisbonifacio Just for clarity; I am not using any amplify generated stuff, I just use the Auth lib and Graphql API in my own Angular services.
I deploy all my resources (graphql, cognito, dynamo etc) via comprehensive microservices using the AWS CDK.
So my configuration for Amplify is pretty manual and simple.

I have a cognito pool and an identity pool for IAM users (non auth) that need to do some things like passwordless login or other no authenticated flows.

So, is setting allowGuestAccess = true the right move for me?

@hanna-becker
Copy link

hanna-becker commented Mar 5, 2024

I have this query along with this type:

type Query {
    getPublicReadOnlyMediaDownloadUrl(s3Path: String!): SignedUrl @function(name: "getPublicReadOnlyMediaDownloadUrl-${env}") @auth(rules: [{ allow: public, provider: iam }, { allow: private }])
}

type SignedUrl {
  url: String!
  filename: String!
}

After following the proposed changes/workarounds here and from this closed(why?) issue my unauthenticated user sees the error: "Not Authorized to access url on type SignedUrl"

Is it necessary to configure auth rules on simple types?

EDIT:
Client code:

import { generateClient } from "aws-amplify/api";

const client = generateClient();

const response = await this.client.graphql({
  query: `query GetPublicReadOnlyMediaDownloadUrl($s3Path: String!) {
    getPublicReadOnlyMediaDownloadUrl(s3Path: $s3Path) {
      __typename
      url
      filename
    }
  }`,
  variables: {
    s3Path: <S3_PATH>,
  },
  authMode: 'iam',
});

Edit #2:
I worked around my issue by changing the return type from my custom type "SignedUrl" to "String". Would love to understand why this was necessary and if there is a way for me to use my custom type, instead.

@chrisbonifacio
Copy link
Member

Hi @manwaring following up on this issue. It seems the fix has been a bit different for the other users in this thread. I noticed when you opened this issue you were on 6.0.7 and a fix has been released since. Can you try upgrading to the latest version of aws-amplify and let us know if the issue persists?

@chrisbonifacio chrisbonifacio added the question General question label Apr 15, 2024
@chrisbonifacio
Copy link
Member

Hi 👋 Closing this as we have not heard back from you. If you are still experiencing this issue and in need of assistance, please feel free to comment and provide us with any information previously requested by our team members so we can re-open this issue and be better able to assist you.

Thank you!

@chrisbonifacio chrisbonifacio closed this as not planned Won't fix, can't repro, duplicate, stale May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
GraphQL Related to GraphQL API issues investigating This issue is being investigated question General question React React related issues V6 V6 of Amplify JS
Projects
None yet
Development

No branches or pull requests