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

[Auth] - idToken cookie is too large to store, so server side authentication does not work #11649

Open asp3 opened 1 year ago

asp3 commented 1 year ago

Before opening, please confirm:

JavaScript Framework

Next.js

Amplify APIs

Authentication

Amplify Categories

auth

Environment information

aws-amplify -> 5.3.4

Describe the bug

req {
  headers: {
    cookie: 'CognitoIdentityServiceProvider.id.user.refreshToken=eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.Bg6oA42drn1r53l_HX8NWke8_zAi7VjHiqmVe4wGyD6U_yyKw4__rdnw9jToVa9FUvaQ0fKX8F6IHWu2G6-qL6tRi2P9kP9zITVKvSAtqv6QZh8RnHdGKs7aJxTCbj--2xckRxFlpnaY3SLjgqrqxiP55GziPz9aBRWWQlIByVgYkYfgUar7Z-qk_FfCpGWUsxIRHPTAdlSVkcvR3unSnf9asdfok6vFGkeOqxsInPekkYWFb91kJgmHkmie-IQCrmB4NWm7GVJovGSXB4Chmk_tPznEG0f5ugM2LINnfV9k9jbejye2DoUsPrv0rm9yO6d5WhLxft4Az-dMoZexJHPQ0w.bxuXl1zkVgwway7c.zjGezxcvKCX66zU8q6400cXsL7JGC2oivPfvpfsG4oBe2HkBDZKKx3lRGsffHgQHXp-RkFZcSnqW_p1UU3zpeVjWeI_HzqryM2QVXwivMt4Qu0WKVE1S-dlw7Qg9IkEO96XbJ8Eb3bwzs20oo8l950_vwLXBeaKCJ8tNjN8rdFejZXYC472GalQ4AVqOKUGHh8JMNEOMaN_2TPQxyOk65qxAa6G80nUYRo3nrni_UIvc0EIJ7HMWp-36YXTE47Ndlf9G03F8-LKqKvTMqma3QjMpNGmSdmKPlzuwn7-r7-1_C8ISCqCgXCQ7il0p4NCJD8GOrrOOc3nmH0_FqSHS-hMppetDPFA6XuoFu6lvI2mxJ-st60EfwTlyczyhKATdVa4G1n1RzgZnyLGC1hIZqg_42EnfFV4mUy2wepdoMUlO8vihVb3Q88nGZE4dxnC_H9KreKOdk79qV0-qLkCuTesV2KKtBI8Z63NHMAD58src9JRUVEDWzCmskgpLOPovuwevBcQE95fExv-Z7co5ixM2sQ0Iy0yjyWQkrmrROduFrkc2Pvwz18CEhMSSw54AWQDhj2tdutdxfw6aZNMqRd6u5c6KPvLX20LFqeagjE1FT0a9Y12Tu-fmF1bA7UbFFsMiUYkxEc_so3T_p1QJEhE_OB03Nblbn6xxHjV9o2d0y1234d_BLmENVQZXlgu4APouOlX_P2dR8swsYxB0Cn-Y875XIfZ_wr2X7H8JxDgQ1S-m-9NqufpkhnELTYnk2SFWh1zF8E4VOD5pPhfP4nQOHIFOXtD1PK0HE4Ik5zHZJAOVFMCPILhATXc-9tyOf7whPTomxOlcKQvbWov0y-9Q-mYwj2edVQWeaBSEZSBasdfTDnj00k8NiAqLxRN8ln8nwi9Amn9wrQa5qNv7sU53xR4ZhgV-ah-Ovxf3linUKLXbBOpNJ-rNfXJZpUV4RgwVx197Iaq1gv6iafSxKk6EzggFJLskqCGVsor1-eMuMjk6c3w9QiCxl0Gd1Aq-bmJJN7BBGKRAx-_o6xDbMhkqSpoAIm8dpVKNm2hvOIYUX_yoNFtH0Pm51VCmOMoMM37Xd5TTd44xYZcRJP5WYXybONG_iecynd2XEDPhgtbyK8H9ZxyT5ob2wrWEPTkSq9N8b_eirg2Ega5yLyrdZ3-lwI9RMoTBO5CKeHl1a6cfyy_Y7MJuePHXsuZFB3twp5E5bZvTVTbeJK8KeVf8BZoOLwm9kkhWG0QukpAcE0jBGcea5FUQzx1oFJd04-n7UKIPoBtbqLdjH_GT8pAQfUKsD6Orx3DQFMoE35kTVkjf_k.M3a9Lp4xpF2JE1XInXGcWg; CognitoIdentityServiceProvider.id.LastAuthUser=user; CognitoIdentityServiceProvider.id.user.accessToken=eyJraWQiOiJOTkxDWEJDVUVoa0djdzFxY01sOWhrQWk4aFBEMHdQYVB1eDVHKytiMWhNPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiI4MjMyODQyOS1kYmI5LTQzxcv2ZDktYjhlYi0wZWJkMjM4ZTIyMWMiLCJldmVudF9pZCI6IjFjYmIwOTFjLTQ0ZmYtNDZjYy1hOTljLTA4N2E2ODI5OTQ2MSIsInRva2VuX3VzZSI6ImFjY21234VzcyIsInNjb3BlIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE2ODk3MjA2MzksImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbVwvdXMtZWFzdC0xX3BqM0ZkRkc2QyIsImV4cCI6MTY4OTc5MjY0MCwiaWF0IjoxNjg5NzIwNjQwLCJqdGkiOiIwNDUwNWQzOC00YjNiLTQ2MTMtYTZjNC1lMzJlZDQ3MzIxN2IiLCJjbGllbnRfaWQiOiJsaW5vdjJvcm9raWhwbmZzcTJhcXF1Z3NjIiwidXNlcm5hbWUiOiJrc3R1ZGVudDEyQC1Aa25vd3QuaW8ifQ.I31LzaPrSnhdOuVbKgjpAkDUTh2Nq_gFK_yVqYwokKQ7KKTVNrEXkPoAPTLbYhYj6EzEBRgJdc8LDe6-FKfQBrdT2B9vC29ObBuGS60Ngkc4mCOB7p5lMtjKtqQ9ABqcoHG-a7ayXj4E4Gm_eYTHtvZ5CdFOR5UOkg0FFskxocIopXnSNQ2KPTNSLb3ldFefdQCX9pryaSaAnuwST6G5U4cHmqp3hf8rz3m9Y97thvNSJ7oSRSeORMqBC_UnvTARRFY1HR9tisyAaL4hTOQacx-UNvavc1p0SNGp-8F2bH4PCuuvB18A2yVsfhwoq0vlRGmdu_NRMJ6SfE0CqDbvPA'
  }
}

error The user is not authenticated

Expected behavior

This function should return the current user, as the cookies are set properly. in our backend, we recently made a change to our claims override, where we added a few more values. The cookies here, however, are well under the 4096 limit.

image

Reproduction steps

set up aws amplify with next 13 app dir. log in. notice that client side values work as expected. However, on server side, it returns user not authenticated.

Code Snippet

import awsConfig from "@/config/aws";
import { oauth } from "@/config/deployConstants";
import { Amplify, withSSRContext } from "aws-amplify";
import { headers } from "next/headers";

Amplify.configure({ ...awsConfig, oauth, ssr: true });

export type SSRContextType = ReturnType<typeof createSSRContext>;

export const createSSRContext = () => {
    // Construct a req object & prepare an SSR enabled version of Amplify
    const req = {
        headers: {
            cookie: headers().get("cookie"),
        },
    };

    console.log("req", req);

    return withSSRContext({ req });
// (await SSR.Auth.currentAuthenticatedUser())
};

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

asp3 commented 1 year ago

In debug mode, I got this extra information:

[DEBUG] 08:25.576 AuthClass - Failed to get the session from user CognitoUser {
  username: 'user',
  pool: CognitoUserPool {
    userPoolId: 'userpoolId',
    clientId: 'id',
    client: Client {
      endpoint: 'https://cognito-idp.us-east-1.amazonaws.com/',
      fetchOptions: {}
    },
    advancedSecurityDataCollectionFlag: true,
    storage: UniversalStorage {
      cookies: [Cookies],
      store: [Object: null prototype]
    },
    wrapRefreshSessionCallback: [Function (anonymous)]
  },
  Session: null,
  client: Client {
    endpoint: 'https://cognito-idp.us-east-1.amazonaws.com/',
    fetchOptions: {}
  },
  signInUserSession: null,
  authenticationFlowType: 'USER_SRP_AUTH',
  storage: UniversalStorage {
    cookies: Cookies {
      changeListeners: [],
      HAS_DOCUMENT_COOKIE: false,
      cookies: [Object]
    },
    store: [Object: null prototype] {
      'CognitoIdentityServiceProvider.id.user.refreshToken': 'eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.Bg6oA42drn1r53l_HX8NWke8_zAi7VjHiqmVe4wGyD6U_yyKw4__rdnw9jToVa9FUvaQ0fKX8F6IHWu2G6-qL6tRi2P9kP9zITVKvSAtqv6QZh8RnHdGKs7aJxTCbj--2xckRxFlpnaY3SLjgqrqxiP55GziPz9aBRWWQlIByVgYkYfgUar7Z-qk_FfCpGWUsxIRHPTAdlSVkcvR3unSnf9ok6vFGkeOqxsInPekkYWFb91kJgmHkmie-IQCrmB4NWm7GVJovGSXB4Chmk_tPznEG0f5ugM2LINnfV9k9jbejye2DoUsPrv0rm9yO6d5WhLxft4Az-dMoZexJHPQ0w.bxuXl1zkVgwway7c.zjGeKCX66zU8q6400cXsL7JGC2oivPfvpfsG4oBe2HkBDZKKx3lRGsffHgQHXp-RkFZcSnqW_p1UU3zpeVjWeI_HzqryM2QVXwivMt4Qu0WKVE1S-dlw7Qg9IkEO96XbJ8Eb3bwzs20oo8l950_vwLXBeaKCJ8tNjN8rdFejZXYC472GalQ4AVqOKUGHh8JMNEOMaN_2TPQxyOk65qxAa6G80nUYRo3nrni_UIvc0EIJ7HMWp-36YXTE47Ndlf9G03F8-LKqKvTMqma3QjMpNGmSdmKPlzuwn7-r7-1_C8ISCqCgXCQ7il0p4NCJD8GOrrOOc3nmH0_FqSHS-hMppetDPFA6XuoFu6lvI2mxJ-st60EfwTlyczyhKATdVa4G1n1RzgZnyLGC1hIZqg_42EnfFV4mUypdoMUlO8vihVb3Q88nGZE4dxnC_H9KreKOdk79qV0-qLkCuTesV2KKtBI8Z63NHMAD58src9JRUVEDWzCmskgpLOPovuwevBcQE95fExv-Z7co5ixM2sQ0Iy0yjyWQkrmrROduFrkc2Pvwz18CEhMSSw54AWQDhj2tdutdxfw6aZNMqRd6u5c6KPvLX20LFqeagjE1FT0a9Y12Tu-fmF1bA7UbFFsMiUYkxEc_so3T_p1QJEhE_OB03Nblbn6xxHjV9o2d0yd_BLmENVQZXlgu4APouOlX_P2dR8swsYxB0Cn-Y875XIfZ_wr2X7H8JxDgQ1S-m-9NqufpkhnELTYnk2SFWh1zF8E4VOD5pPhfP4nQOHIFOXtD1PK0HE4Ik5zHZJAOVFMCPILhATXc-9tyOf7whPTomxOlcKQvbWov0y-9Q-mYwj2edVQWeaBSEZSBTDnj00k8NiAqLxRN8ln8nwi9Amn9wrQa5qNv7sU53xR4ZhgV-ah-Ovxf3linUKLXbBOpNJ-rNfXJZpUV4RgwVx197Iaq1gv6iafSxKk6EzggFJLskqCGVsor1-eMuMjk6c3w9QiCxl0Gd1Aq-bmJJN7BBGKRAx-_o6xDbMhkqSpoAIm8dpVKNm2hvOIYUX_yoNFtH0Pm51VCmOMoMM37Xd5TTd44xYZcRJP5WYXybONG_iecynd2XEDPhgtbyK8H9ZxyT5ob2wrWEPTkSq9N8b_eirg2Ega5yLyrdZ3-lwI9RMoTBO5CKeHl1a6cfyy_Y7MJuePHXsuZFB3twp5E5bZvTVTbeJK8KeVf8BZoOLwm9kkhWG0QukpAcE0jBGcea5FUQzx1oFJd04-n7UKIPoBtbqLdjH_GT8pAQfUKsD6Orx3DQFMoE35kTVkjf_k.M3a9Lp4xpF2JE1XInXGcWg',
      'CognitoIdentityServiceProvider.id.LastAuthUser': 'user',
      'CognitoIdentityServiceProvider.id.user.accessToken': 'eyJraWQiOiJOTkxDWEJDVUVoa0djdzFxY01sOWhrQWk4aFBEMHdQYVB1eDVHKytiMWhNPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiI4MjMyODQyOS1kYmI5LTQ2ZDktYjhlYi0wZWJkMjM4ZTIyMWMiLCJldmVudF9pZCI6IjFjYmIwOTFjLTQ0ZmYtNDZjYy1hOTljLTA4N2E2ODI5OTQ2MSIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE2ODk3MjA2MzksImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbVwvdXMtZWFzdC0xX3BqM0ZkRkc2QyIsImV4cCI6MTY4OTc5MjY0MCwiaWF0IjoxNjg5NzIwNjQwLCJqdGkiOiIwNDUwNWQzOC00YjNiLTQ2MTMtYTZjNC1lMzJlZDQ3MzIxN2IiLCJjbGllbnRfaWQiOiJsaW5vdjJvcm9raWhwbmZzcTJhcXF1Z3NjIiwidXNlcm5hbWUiOiJrc3R1ZGVudDEyQC1Aa25vd3QuaW8ifQ.I31LzaPrSnhdOuVbKgjpAkDUTh2Nq_gFK_yVqYwokKQ7KKTVNrEXkPoAPTLbYhYj6EzEBRgJdc8LDe6-FKfQBrdT2B9vC29ObBuGS60Ngkc4mCOB7p5lMtjKtqQ9ABqcoHG-a7ayXj4E4Gm_eYTHtvZ5CdFOR5UOkg0FFskxocIopXnSNQ2KPTNSLb3ldFefdQCX9pryaSaAnuwST6G5U4cHmqp3hf8rz3m9Y97thvNSJ7oSRSeORMqBC_UnvTARRFY1HR9tisyAaL4hTOQacx-UNvavc1p0SNGp-8F2bH4PCuuvB18A2yVsfhwoq0vlRGmdu_NRMJ6SfE0CqDbvPA'
    }
  },
  keyPrefix: 'CognitoIdentityServiceProvider.id',
  userDataKey: 'CognitoIdentityServiceProvider.id.user.userData'
}
[DEBUG] 08:25.576 AuthClass - The user is not authenticated by the error Error: Local storage is missing an ID Token, Please authenticate
    at CognitoUser.getSession (webpack-internal:///(sc_server)/../../node_modules/amazon-cognito-identity-js/lib/CognitoUser.js:1063:22)
    at eval (webpack-internal:///(sc_server)/../../node_modules/@aws-amplify/auth/lib/Auth.js:2031:38)
    at new Promise (<anonymous>)
    at AuthClass.eval (webpack-internal:///(sc_server)/../../node_modules/@aws-amplify/auth/lib/Auth.js:2030:59)
    at step (webpack-internal:///(sc_server)/../../node_modules/@aws-amplify/auth/node_modules/tslib/tslib.es6.js:194:23)
    at Object.eval [as next] (webpack-internal:///(sc_server)/../../node_modules/@aws-amplify/auth/node_modules/tslib/tslib.es6.js:135:20)
    at eval (webpack-internal:///(sc_server)/../../node_modules/@aws-amplify/auth/node_modules/tslib/tslib.es6.js:113:71)
    at new Promise (<anonymous>)
    at Module.__awaiter (webpack-internal:///(sc_server)/../../node_modules/@aws-amplify/auth/node_modules/tslib/tslib.es6.js:95:12)
    at AuthClass._userSession (webpack-internal:///(sc_server)/../../node_modules/@aws-amplify/auth/lib/Auth.js:2013:24)
    at AuthClass.eval (webpack-internal:///(sc_server)/../../node_modules/@aws-amplify/auth/lib/Auth.js:1756:42)
    at step (webpack-internal:///(sc_server)/../../node_modules/@aws-amplify/auth/node_modules/tslib/tslib.es6.js:194:23)
    at Object.eval [as next] (webpack-internal:///(sc_server)/../../node_modules/@aws-amplify/auth/node_modules/tslib/tslib.es6.js:135:20)
    at eval (webpack-internal:///(sc_server)/../../node_modules/@aws-amplify/auth/node_modules/tslib/tslib.es6.js:113:71)
    at new Promise (<anonymous>)
    at Module.__awaiter (webpack-internal:///(sc_server)/../../node_modules/@aws-amplify/auth/node_modules/tslib/tslib.es6.js:95:12)
    at eval (webpack-internal:///(sc_server)/../../node_modules/@aws-amplify/auth/lib/Auth.js:1702:32)
fetchUser error The user is not authenticated
asp3 commented 1 year ago

Cookies:

image

vs.

Local Storage:

image

Seems like the Local Storage has a few more keys, namely:

userData
clockDrift
idToken
asp3 commented 1 year ago

Seems to be a size issue! I tried to manually copy my idToken into the cookies, and the idToken length was around 6k characters, which is definitely more than what can be stored in cookies (4096). Any workaround for this? Maybe for server side, we can split the token across multiple cookies

CognitoIdentityServiceProvider.id.username.idToken_0
CognitoIdentityServiceProvider.id.username.idToken_1

thoughts? @cwomack

cwomack commented 1 year ago

Hello @asp3, and thanks for opening this issue. As you've already indicated, there's usually a cookie size limitation of 4 KB (4096 bytes) that browsers implement. If you're at over 6k bytes, it's likely that you'd experience this on most (if not all) browsers I think.

Can you help me understand the reason why the cookies are so large? Do you have a large number of attributes within your User Pool that's causing this?

asp3 commented 1 year ago

Can you help me understand the reason why the cookies are so large? Do you have a large number of attributes within your User Pool that's causing this?

Hey @cwomack, thanks for the response - I guess this isn't next 13 app dir specific, yeah. We use the claimsToAddOrOverride in the cognito pre_token trigger to add more user info from our db to the payload. This saves us making an extra call to our db, and amplify handles all the auth information. This information is necessary, so theres not much we can do around it in terms of the size of it, and I assume others might run into this issue as well (since the local storage limit is a lot higher, theres no issue for client side rendering)

If this is pretty specific to our use case, I could make a fork and just make the changes to the cookie storage/retreival myself (if you could provide some code pointers, that would be great), but it seems like others might be running into this as well, so maybe it would be useful to support larger payloads for server side.

Please let me know your thoughts! This is blocking some of our larger refactors, so looking to either

asp3 commented 1 year ago

any update on this? @cwomack This is a blocking issue for us, so I was wondering if you could give a code pointer of where the code to store and retrieve cookies is so we could fix this issue

cwomack commented 1 year ago

@asp3, thank you for the additional context above! There’s not a straightforward solution to this at the moment, so we’ll convert this issue into a feature request to see if we can provide a better option out of the box when customers run into this limitation.

Your use of claimsToAddOrOverride in the Cognito pre-token generation Lambda trigger is going to impact cookie storage and likely the reason why the idToken cannot be written into cookie storage. To be clear, we don’t capture what’s coming from the idToken and it will just get passed as is.

The only two workarounds that I can think of here would be to either:

  1. Do some “optimizing” of your cookies to see if you can get their size down and work within the standard limits.
  2. Fork the repo so that you can modify how cookies are set on the client side and possibly implement your suggested splitting of the token across multiple cookies (if this is all something you’re comfortable with doing as it will create additional complexity).
asp3 commented 1 year ago

@cwomack I know what changes need to be made (inside UniversalStorage), but I am not sure about the process for forking and using the built fork in my repo. Could you please provide some documentation around this part?

asp3 commented 1 year ago

In case anyone finds this later, here's how I fixed it.

// awsConfig:

const storage = new UniversalStorage();

const awsConfig = {
    ...
    storage,
    cookiesStorage: storage,
}

// UniversalStorage (copied from amplify/core, with minor modifications)

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import Cookies, { CookieSetOptions } from 'universal-cookie';

const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';

type Store = Record<string, string>;

// Avoid using @types/next because @aws-amplify/ui-angular's version of TypeScript is too old to support it
type Context = { req?: any };

const ONE_YEAR_IN_MS = 365 * 24 * 60 * 60 * 1000;
const MAX_CHUNK_SIZE = 4000;

const getCookieKey = (key, i) => i === 0 ? key : `${key}_${i}`;

export class UniversalStorage implements Storage {
    cookies = new Cookies();
    store: Store = isBrowser ? window.localStorage : Object.create(null);

    constructor(context: Context = {}) {
        this.cookies = context.req
            ? new Cookies(context.req.headers.cookie)
            : new Cookies();

        Object.assign(this.store, this.cookies.getAll());
    }

    get length() {
        return Object.entries(this.store).length;
    }

    clear() {
        Array.from(new Array(this.length))
            .map((_, i) => this.key(i))
            .forEach(key => this.removeItem(key));
    }

    getItem(key: keyof Store) {
        return this.getChunkedItem(key);
    }

    protected getLocalItem(key: keyof Store) {
        return Object.prototype.hasOwnProperty.call(this.store, key)
            ? this.store[key]
            : null;
    }

    protected getChunkedItem(key: keyof Store) {
        const values: string[] = [];
        let i = 0;

        // eslint-disable-next-line no-constant-condition
        while (true) {
                const cookieKey = getCookieKey(key, i);
                const value = this.getLocalItem(cookieKey);
                if (value) {
                        values.push(value);
                        i++;
                } else {
                        break;
                }
        }

        if (values.length === 0) {
                return null;
        }

        return values.join("");
    }

    protected getUniversalItem(key: keyof Store) {
        return this.cookies.get(key);
    }

    key(index: number) {
        return Object.keys(this.store)[index];
    }

    removeItem(key: string) {
        this.removeLocalItem(key);
        this.removeUniversalItem(key);
    }

    protected removeLocalItem(key: keyof Store) {
        delete this.store[key];
    }

    protected removeUniversalItem(key: keyof Store) {
        this.cookies.remove(key, {
            path: '/',
        });
    }

    setItem(key: keyof Store, value: string) {
        this.setLocalItem(key, value);

        // keys take the shape:
        //  1. `${ProviderPrefix}.${userPoolClientId}.${username}.${tokenType}
        //  2. `${ProviderPrefix}.${userPoolClientId}.LastAuthUser
        const tokenType = key.split('.').pop();

        const sessionTokenTypes = [
            'LastAuthUser',
            'accessToken',
            // refreshToken originates on the client, but SSR pages won't fail when this expires
            // Note: the new `accessToken` will also be refreshed on the client (since Amplify doesn't set server-side cookies)
            'refreshToken',
            // Required for CognitoUserSession
            'idToken',
            // userData is used when `Auth.currentAuthenticatedUser({ bypassCache: false })`.
            // Can be persisted to speed up calls to `Auth.currentAuthenticatedUser()`
            // 'userData',

            // Ignoring clockDrift on the server for now, but needs testing
            // 'clockDrift',
        ];

        if (sessionTokenTypes.includes(tokenType ?? '')) {
            // if the value is larger than 4000 chars, split it into multiple cookies
            const numberOfCookies = Math.ceil(value.length / MAX_CHUNK_SIZE);

            if (numberOfCookies === 1) {
                this.setUniversalItem(key, value, {
                    expires: new Date(Date.now() + ONE_YEAR_IN_MS),
                });
                return;
            }

            for (let i = 0; i < numberOfCookies; i++) {
                const cookieKey = getCookieKey(key, i);
                const cookieValue = value.substr(i * MAX_CHUNK_SIZE, MAX_CHUNK_SIZE);

                this.setUniversalItem(cookieKey, cookieValue, {
                    expires: new Date(Date.now() + ONE_YEAR_IN_MS),
                });
            }
        }
    }

    protected setLocalItem(key: keyof Store, value: string) {
        this.store[key] = value;
    }

    protected setUniversalItem(
        key: keyof Store,
        value: string,
        options: CookieSetOptions = {}
    ) {
        this.cookies.set(key, value, {
            ...options,
            path: '/',
            // `httpOnly` cannot be set via JavaScript: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#JavaScript_access_using_Document.cookie
            sameSite: true,
            // Allow unsecure requests to http://localhost:3000/ when in development.
            secure:
                isBrowser && window.location.hostname === 'localhost' ? false : true,
        });
    }
}
cwomack commented 1 year ago

@asp3, that's awesome to hear you got it working and we appreciate you taking the time to add the comment showing your workaround!

rdsedmundo commented 7 months ago

I'm also facing this, getting HTTP 494 Error Codes in CloudFront.

1545 should not have been closed.

Related #10498.

rdsedmundo commented 7 months ago

After some investigations I figured out that at least in our case, where the base tokens are not that big as we don't have lots of custom claims, that the issue is Amplify/Cognito not cleraing up device data from the storage, and it starts to pile up as you log out and log in again, especially when different accounts are used. Eventually you then hit the CloudFront limits.

The keys that keep repeating themselves are:

CognitoIdentityServiceProvider.{$USER_POOL_CLIENT_ID}.${COGNITO_USER_COGNITO_ID}.randomPasswordKey
CognitoIdentityServiceProvider.{$USER_POOL_CLIENT_ID}.${COGNITO_USER_COGNITO_ID}.deviceGroupKey
CognitoIdentityServiceProvider.{$USER_POOL_CLIENT_ID}.${COGNITO_USER_COGNITO_ID}.deviceKey
Screenshot 2024-01-24 at 12 41 45 PM

Those keys are saved even if the "Remember me" option is not checked.