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

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

Open
3 tasks done
asp3 opened this issue Jul 18, 2023 · 12 comments
Open
3 tasks done
Assignees
Labels
Auth Related to Auth components/category feature-request Request a new feature

Comments

@asp3
Copy link

asp3 commented Jul 18, 2023

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 asp3 added the pending-triage Issue is pending triage label Jul 18, 2023
@asp3
Copy link
Author

asp3 commented Jul 18, 2023

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
Copy link
Author

asp3 commented Jul 18, 2023

Cookies:

image

vs.

Local Storage:

image

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

userData
clockDrift
idToken

@asp3
Copy link
Author

asp3 commented Jul 18, 2023

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

@nadetastic nadetastic added Auth Related to Auth components/category Next.js labels Jul 19, 2023
@cwomack cwomack self-assigned this Jul 19, 2023
@cwomack
Copy link
Member

cwomack commented Jul 19, 2023

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?

@cwomack cwomack added investigating This issue is being investigated and removed pending-triage Issue is pending triage labels Jul 19, 2023
@asp3
Copy link
Author

asp3 commented Jul 20, 2023

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 asp3 changed the title Next 13 App Dir, Server Component: The user is not authenticated [Auth][next.js] - idToken cookie is too large to store, so server side authentication does not work Jul 20, 2023
@cwomack cwomack removed the Next.js label Jul 24, 2023
@asp3 asp3 changed the title [Auth][next.js] - idToken cookie is too large to store, so server side authentication does not work [Auth] - idToken cookie is too large to store, so server side authentication does not work Jul 26, 2023
@asp3
Copy link
Author

asp3 commented Jul 26, 2023

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
Copy link
Member

cwomack commented Jul 28, 2023

@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).

@cwomack cwomack added feature-request Request a new feature and removed investigating This issue is being investigated labels Jul 28, 2023
@asp3
Copy link
Author

asp3 commented Aug 5, 2023

@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
Copy link
Author

asp3 commented Aug 6, 2023

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
Copy link
Member

cwomack commented Aug 9, 2023

@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
Copy link

rdsedmundo commented Jan 24, 2024

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

#1545 should not have been closed.

Related #10498.

@rdsedmundo
Copy link

rdsedmundo commented Jan 24, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Auth Related to Auth components/category feature-request Request a new feature
Projects
None yet
Development

No branches or pull requests

4 participants