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.44k stars 2.13k forks source link

Sometimes Amplify tokens get multiplied #14007

Open didemkkaslan opened 1 day ago

didemkkaslan commented 1 day ago

Before opening, please confirm:

JavaScript Framework

Next.js

Amplify APIs

Authentication

Amplify Version

v6

Amplify Categories

auth

Backend

Amplify CLI

Environment information

``` # Put output below this line System: OS: macOS 14.7.1 CPU: (8) arm64 Apple M2 Memory: 156.86 MB / 8.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 18.16.0 - /usr/local/bin/node Yarn: 1.22.22 - /opt/homebrew/bin/yarn npm: 9.5.1 - /usr/local/bin/npm pnpm: 9.12.2 - /usr/local/bin/pnpm bun: 1.0.2 - ~/.bun/bin/bun Browsers: Chrome: 130.0.6723.117 Safari: 18.1 npmPackages: @amplitude/analytics-browser: ^2.3.3 => 2.11.1 @ampproject/toolbox-optimizer: undefined () @ant-design/cssinjs: 1.20.0 => 1.20.0 (1.21.1) @ant-design/icons: ^5.2.6 => 5.4.0 @ant-design/plots: 1.2.5 => 1.2.5 @aws-amplify/adapter-nextjs: ^1.2.26 => 1.2.23 @aws-amplify/adapter-nextjs/api: undefined () @aws-amplify/adapter-nextjs/data: undefined () @azure/msal-browser: ^3.24.0 => 3.24.0 @azure/msal-react: ^2.1.0 => 2.1.0 @babel/core: undefined () @babel/runtime: 7.22.5 @ckeditor/ckeditor5-build-classic: ^43.3.0 => 43.3.0 @ckeditor/ckeditor5-react: ^9.3.1 => 9.3.1 @edge-runtime/cookies: 5.0.0 @edge-runtime/ponyfill: 3.0.0 @edge-runtime/primitives: 5.0.0 @graphql-codegen/cli: ^5.0.3 => 5.0.3 @graphql-codegen/client-preset: ^4.4.0 => 4.4.0 @graphql-codegen/introspection: ^4.0.3 => 4.0.3 @hapi/accept: undefined () @mantine/hooks: ^7.1.5 => 7.12.2 @microsoft/teams-js: ^2.19.0 => 2.28.0 @mswjs/interceptors: undefined () @napi-rs/triples: undefined () @next/bundle-analyzer: 15.0.2 => 15.0.2 @next/font: undefined () @opentelemetry/api: undefined () @react-pdf/renderer: ^3.1.13 => 3.4.4 @tailwindcss/typography: ^0.5.10 => 0.5.15 @tanstack/query-codemods: undefined () @tanstack/react-query: ^5.0.5 => 5.54.1 @tanstack/react-query-devtools: ^5.8.9 => 5.54.1 @testing-library/jest-dom: ^6.1.4 => 6.5.0 @testing-library/react: ^14.0.0 => 14.3.1 @testing-library/user-event: ^14.5.1 => 14.5.2 @types/jest: ^29.5.6 => 29.5.12 @types/lodash: ^4.14.200 => 4.17.7 @types/mixpanel-browser: ^2.47.4 => 2.50.0 @types/node: ^20.8.8 => 20.16.5 (22.5.4) @types/react: ^18.3.12 => 18.3.12 @types/react-dom: ^18.3.1 => 18.3.1 @types/react-google-recaptcha: ^2.1.7 => 2.1.9 @types/react-highlight-words: ^0.16.6 => 0.16.7 @types/uuid: ^9.0.7 => 9.0.8 @typescript-eslint/eslint-plugin: ^8.13.0 => 8.13.0 @typescript-eslint/parser: ^8.13.0 => 8.13.0 @vercel/nft: undefined () @vercel/og: 0.6.3 acorn: undefined () amphtml-validator: undefined () anser: undefined () antd: 5.17.0 => 5.17.0 apexcharts: ^3.44.0 => 3.53.0 arg: undefined () assert: undefined () async-retry: undefined () async-sema: undefined () autoprefixer: ^10.4.16 => 10.4.20 aws-amplify: ^6.8.0 => 6.6.4 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-rum-web: ^1.15.0 => 1.19.0 axios: ^1.5.1 => 1.7.7 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.1.1 commander: undefined () comment-json: undefined () compression: undefined () conf: undefined () constants-browserify: undefined () content-disposition: undefined () content-type: undefined () cookie: undefined () cookies-next: ^4.3.0 => 4.3.0 cross-spawn: undefined () crypto-browserify: undefined () css.escape: undefined () data-uri-to-buffer: undefined () dayjs: ^1.11.10 => 1.11.13 debug: undefined () devalue: undefined () docx: ^8.5.0 => 8.5.0 domain-browser: undefined () edge-runtime: undefined () eslint: ^8.52.0 => 8.57.0 eslint-config-airbnb: ^19.0.4 => 19.0.4 eslint-config-airbnb-typescript: ^17.1.0 => 17.1.0 eslint-config-next: 15.0.2 => 15.0.2 eslint-config-prettier: ^9.0.0 => 9.1.0 eslint-plugin-i18next: ^6.0.3 => 6.0.9 eslint-plugin-import: ^2.29.0 => 2.30.0 (2.31.0) eslint-plugin-jest: ^27.4.3 => 27.9.0 eslint-plugin-jest-dom: ^5.1.0 => 5.4.0 eslint-plugin-jsx-a11y: ^6.7.1 => 6.10.0 (6.10.2) eslint-plugin-react: ^7.33.2 => 7.35.2 (7.37.2) eslint-plugin-testing-library: ^6.1.2 => 6.3.0 events: undefined () find-cache-dir: undefined () find-up: undefined () framer-motion: ^11.11.11 => 11.11.11 fresh: undefined () get-orientation: undefined () glob: undefined () graphql: ^16.9.0 => 16.9.0 (15.8.0) graphql-request: 6.1.0 => 6.1.0 gzip-size: undefined () http-proxy: undefined () http-proxy-agent: undefined () https-browserify: undefined () https-proxy-agent: undefined () husky: ^8.0.3 => 8.0.3 i18next: ^23.7.15 => 23.14.0 i18next-chained-backend: ^4.5.0 => 4.6.2 i18next-http-backend: ^2.2.2 => 2.6.1 i18next-localstorage-backend: ^4.2.0 => 4.2.0 icss-utils: undefined () ignore-loader: undefined () image-size: undefined () is-animated: undefined () is-docker: undefined () is-wsl: undefined () jest: ^29.7.0 => 29.7.0 jest-environment-jsdom: ^29.7.0 => 29.7.0 jest-worker: undefined () json5: undefined () jsonwebtoken: undefined () jwt-decode: ^3.1.2 => 3.1.2 loader-runner: undefined () loader-utils: undefined () lodash: ^4.17.21 => 4.17.21 lodash.curry: undefined () lru-cache: undefined () mini-css-extract-plugin: undefined () mixpanel-browser: ^2.47.0 => 2.55.1 nanoid: undefined () native-url: undefined () neo-async: undefined () next: 14.2.16 => 14.2.16 next-i18next: ^15.1.2 => 15.3.1 next-i18next-create-client: undefined () next-seo: ^6.1.0 => 6.6.0 node-fetch: undefined () node-html-parser: undefined () ora: undefined () os-browserify: undefined () p-limit: undefined () path-browserify: undefined () picomatch: undefined () platform: undefined () postcss: ^8.4.31 => 8.4.45 (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 () prettier: ^3.0.3 => 3.3.3 prettier-plugin-tailwindcss: ^0.5.6 => 0.5.14 process: undefined () punycode: undefined () querystring-es3: undefined () raw-body: undefined () react: ^18.3.1 => 18.3.1 react-apexcharts: ^1.4.1 => 1.4.1 react-builtin: undefined () react-dom: ^18.3.1 => 18.3.1 react-dom-builtin: undefined () react-dom-experimental-builtin: undefined () react-error-boundary: ^4.0.13 => 4.0.13 react-experimental-builtin: undefined () react-google-recaptcha: ^3.1.0 => 3.1.0 react-highlight-words: ^0.20.0 => 0.20.0 react-i18next: ^14.0.0 => 14.1.3 react-icons: ^4.11.0 => 4.12.0 react-infinite-scroll-component: ^6.1.0 => 6.1.0 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 () sharp: ^0.32.6 => 0.32.6 shell-quote: undefined () source-map: undefined () source-map08: undefined () stacktrace-parser: undefined () stream-browserify: undefined () stream-http: undefined () string-hash: undefined () string_decoder: undefined () strip-ansi: undefined () superstruct: undefined () tailwind-merge: ^1.14.0 => 1.14.0 tailwindcss: ^3.3.3 => 3.4.10 tar: undefined () terser: undefined () text-table: undefined () timers-browserify: undefined () tty-browserify: undefined () typescript: ^5.2.2 => 5.5.4 ua-parser-js: undefined () unistore: undefined () usehooks-ts: ^2.9.1 => 2.16.0 util: undefined () uuid: ^9.0.1 => 9.0.1 vm-browserify: undefined () watchpack: undefined () web-vitals: undefined () webpack: undefined () webpack-sources: undefined () ws: undefined () zod: ^3.22.4 => 3.23.8 () zustand: ^4.5.2 => 4.5.5 npmGlobalPackages: @aws-amplify/cli: 12.12.6 corepack: 0.17.0 eas-cli: 12.4.1 expo-cli: 6.3.10 npm: 9.5.1 pnpm: 9.12.2 turbo: 2.1.2 ```

Describe the bug

Hello:), I can rarely reproduce this but here is a user reporting it:

I was at home fully. And I used the platform let’s say 45 mins ago or so. Then I clicked on “Report Link” in my email and that’s when I saw this browser output.

Email link is just a redirection to meeting detail page. Since token sizes are big we also get request header too large error when they got multiplied and page crash

image (4) image (5)

We use a custom cookie storage where I tried to prevent token multiplication error:

import amplifyconfig from '../../amplifyconfiguration.json';
import { deduplicatedFetchAuthSession } from '../lib/deduplicatedFetchAuthSession';
import { Amplify } from 'aws-amplify';
import { parseAmplifyConfig } from 'aws-amplify/utils';
import { createKeyValueStorageFromCookieStorageAdapter } from 'aws-amplify/adapter-core';
import { deleteCookie, getCookie, setCookie, getCookies } from 'cookies-next';
import { cognitoUserPoolsTokenProvider } from 'aws-amplify/auth/cognito';
import { OptionsType } from 'cookies-next/lib/types';

const amplifyConfig = parseAmplifyConfig(amplifyconfig);

const cookieOptions: OptionsType =
  process.env.NEXT_PUBLIC_ENV === 'msteams'
    ? {
        domain: 'tab.app.spiky.ai' as string,
        sameSite: 'none' as 'lax' | 'strict' | 'none',
        secure: true,
      }
    : {};

const keyValueStorage = createKeyValueStorageFromCookieStorageAdapter({
  get(name) {
    const value = getCookie(name, cookieOptions);
    return { name, value };
  },
  getAll() {
    const cookies = getCookies(cookieOptions);
    return Object.keys(cookies).map((name) => ({ name, value: cookies[name] }));
  },
  set(name, value) {
    const cookieAlreadyExists = getCookie(name, cookieOptions);

    if (cookieAlreadyExists) {
      console.log(
        'cookieAlreadyExists so Im deleting it and setting new one',
        cookieAlreadyExists,
      );
      deleteCookie(name, cookieOptions);
    }
    setCookie(name, value, cookieOptions);
  },
  delete(name) {
    deleteCookie(name, cookieOptions);
  },
});

export const getAuthToken = async () => {
  const session = await deduplicatedFetchAuthSession();
  return session.tokens?.idToken?.toString() as string;
};

export function configureAmplify() {
  Amplify.configure(
    {
      ...amplifyConfig,
      Auth: {
        ...amplifyConfig.Auth,
        Cognito: {
          ...amplifyConfig.Auth?.Cognito,
          identityPoolId:
            process.env.NEXT_PUBLIC_PLATFORM_COGNITO_IDENTITY_POOL_ID!,
          userPoolId: process.env.NEXT_PUBLIC_PLATFORM_COGNITO_USER_POOL_ID!,
          userPoolClientId:
            process.env.NEXT_PUBLIC_PLATFORM_COGNITO_USER_POOL_WEB_CLIENT_ID!,
        },
      },
      API: {
        ...amplifyConfig.API,
        REST: {
          ...amplifyConfig.API?.REST,
          PlatformCorePublicRestApi: {
            endpoint: `${process.env.NEXT_PUBLIC_PLATFORM_CORE_REST_API_ENDPOINT}/public`,
          },
          PlatformCoreRestApi: {
            endpoint: `${process.env.NEXT_PUBLIC_PLATFORM_CORE_REST_API_ENDPOINT}/platform`,
          },
          PlatformCoreCalendarRestApi: {
            endpoint: `${process.env.NEXT_PUBLIC_PLATFORM_CORE_REST_API_ENDPOINT}/calendar-v2`,
          },
          PlatformCoreTeamsRestApi: {
            endpoint: `${process.env.NEXT_PUBLIC_PLATFORM_CORE_REST_API_TEAMS_ENDPOINT}`,
          },
          PlatformIntegrationRestApi: {
            endpoint: `${process.env.NEXT_PUBLIC_PLATFORM_INTEGRATION_REST_API_ENDPOINT}`,
          },
          PlatformRestApi: {
            endpoint: `${process.env.NEXT_PUBLIC_PLATFORM_REST_API_ENDPOINT}`,
          },
        },
      },
    },
    {
      ssr: true,
      API: {
        REST: {
          headers: async () => ({
            Authorization: `Bearer ${await getAuthToken()}`,
          }),
        },
      },
    },
  );

  cognitoUserPoolsTokenProvider.setKeyValueStorage(keyValueStorage);
}

Expected behavior

Tokens shouldn't get multiplied

Reproduction steps

Not really sure why and when this happens but it usually happens when a tab is left open 45mins or so

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

didemkkaslan commented 1 day ago

Added another screenshot, this time there is smth like username I'm not sure maybe its helpful CleanShot 2024-11-13 at 20 12 41@2x

cwomack commented 22 hours ago

Hello, @didemkkaslan 👋. Can you help me understand how you're looking to use that OptionsType import from the cookies-next library? It looks like you're setting secure: true within your cookieOptions, but in the screenshots the cookies don't look to be marked with the secure ✅ in the dev tools column.

Is this intentional? Just want to make sure we aren't missing any intended functionality here.

didemkkaslan commented 20 hours ago

Sure, we also have msteams tab app on the domain tab.app.spiky.ai. Its an iframe on msteams app so we weren't able to login there with the default local storage method amplify uses. So this is actually why we implemented custom cookie storage. But we get the duplicate token error when NEXT_PUBLIC_ENV is not msteams. so cookie options are empty in this case. I'm not sure if I'm missing smth