Open asp3 opened 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
Cookies:
vs.
Local Storage:
Seems like the Local Storage has a few more keys, namely:
userData
clockDrift
idToken
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
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?
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
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
@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:
@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?
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,
});
}
}
@asp3, that's awesome to hear you got it working and we appreciate you taking the time to add the comment showing your workaround!
I'm also facing this, getting HTTP 494 Error Codes in CloudFront.
Related #10498.
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
Those keys are saved even if the "Remember me" option is not checked.
Before opening, please confirm:
JavaScript Framework
Next.js
Amplify APIs
Authentication
Amplify Categories
auth
Environment information
aws-amplify -> 5.3.4
Describe the bug
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.
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
Log output
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