Description
Before opening, please confirm:
- I have searched for duplicate or closed issues and discussions.
- I have read the guide for submitting bug reports.
- I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
Next.js
Amplify APIs
GraphQL API, Authentication
Amplify Version
v6
Amplify Categories
auth, api
Backend
Other
Environment information
System:
OS: macOS 15.4.1
CPU: (16) arm64 Apple M4 Max
Memory: 12.90 GB / 64.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 22.14.0 - ~/.nvm/versions/node/v22.14.0/bin/node
Yarn: 1.22.5 - ~/.yarn/bin/yarn
npm: 10.9.2 - ~/.nvm/versions/node/v22.14.0/bin/npm
Watchman: 2024.01.22.00 - /usr/local/bin/watchman
Browsers:
Brave Browser: 114.1.52.130
Chrome: 135.0.7049.115
Safari: 18.4
npmPackages:
@biomejs/biome: 1.9.4 => 1.9.4
@knowt/tsconfig: * => 0.0.0
dotenv-cli: latest => 8.0.0
husky: ^8.0.0 => 8.0.3
lint-staged: ^12.4.0 => 12.5.0
turbo: ^1.10.12 => 1.13.4
npmGlobalPackages:
@aws-amplify/cli: 12.14.4
corepack: 0.31.0
eas-cli: 16.1.0
npm: 10.9.2
vercel: 41.5.0
Describe the bug
We have been long time users of amplify, and it is currently supporting our production workload of 2M+ MAU. Overall, this is a fantastic library and has saved us thousands of hours of writing our own implementation.
We've made our own patches to this for some of our use cases, but I can't seem to figure out why some issues have been happening recently. We have a massive spike in users in the last week, and these problems have started around this time.
To rule out some other things:
Our UserAuthentication requests utilization % is well below the quota, so its not that we are reaching the 120RPS.
From my understanding, I believe the root cause of this is that cognito-identity network call still made even when custom Authorization is passed in
Currently, our setup is as follows:
const getCognitoAuthToken = async () => {
const cookieMap = Cookies.get();
const cookies = Object.keys(cookieMap).map(key => ({
name: key,
value: cookieMap[key],
}));
let idToken = cookies.filter(
cookie =>
cookie.name.includes("CognitoIdentityServiceProvider") &&
cookie.name.includes("idToken") &&
// on dev, since we switch between dev and prod a lot, we need to make sure we're using the right token
cookie.name.includes(USERPOOL_CLIENT_ID)
)?.[0]?.value;
if (!idToken) {
return {};
}
const parsedToken = jwtDecode(idToken);
const isExpired = parsedToken.exp && parsedToken.exp + TOKEN_BUFFER <= now();
try {
if (isExpired) {
// get the new token
idToken = (await fetchAuthSession()).tokens?.idToken?.toString();
}
return {
Authorization: idToken,
};
} catch {
return {};
}
};
export const amplifyAuthOverride = {
API: {
GraphQL: {
headers: async () => await getCognitoAuthToken(),
},
},
};
We noticed some slight differences needed in api-graphql/src/internals/InternalGraphQLAPI.ts
, where we made the necessary changes to make sure the fetchAuthSession call here was not made either.
Line 236
if (typeof customHeaders === 'function') {
customLibraryHeaders = await customHeaders(body) as Record<string, string>
} else {
customLibraryHeaders = {}
}
// if an authorization header is set, have the explicit authToken take precedence
if (authToken) {
additionalCustomHeaders = {
...additionalCustomHeaders,
Authorization: authToken,
};
}
const authHeaders = await headerBasedAuth(
amplify,
authMode,
apiKeyOverride ?? apiKey,
{ ...additionalCustomHeaders, ...customLibraryHeaders },
);
Along with the changes in headerBasedAuth
:
case 'userPool': {
if (additionalHeaders.Authorization) {
break;
}
let token: string | undefined;
try {
token = (
await amplify.Auth.fetchAuthSession()
).tokens?.idToken?.toString();
} catch (e) {
// pass, call with no authorization header
}
if (token) {
headers = {
Authorization: token,
};
}
break;
}
Now, we would expect that the call to fetchAuthSession
would be removed. However, we noticed in the network tab that the requests to https://cognito-identity.us-east-1.amazonaws.com are still made!
https://share.cleanshot.com/zQwxfV9n
Here you can see that there were 10 requests to cognito-identity, but 5 GraphQL API calls were made. I added console logs to make sure neither of the fetchAuthSession calls were made, but it seems like its getting called from somewhere else.
I don't expect this to be fixed in the main package, but if you could point me to where in the code this call is made from, that would help quite a bit as well!
I also guess that when the rate limit error happens, it automatically logs the user out and clears all the values from local storage. Is there a way to stop this behavior, and keep those values so that when the user reloads, they are still logged in? Some users are reporting that they are getting logged out every 5-10 minutes, which is not ideal.
We look forward to being able to patch these issues!
Expected behavior
When Authorization is explicitly passed, we should not be making calls to cognito-identify. Again, I'm not fully sure if this is what is causing it, but I assume this is the reason why they are getting logged out.
As per AWS Docs, there is a 10 request/user/second rate limit on these requests, and when making multiple API calls, this limit may get hit.
Reproduction steps
- copy the snippet above, and configure amplify with custom overrides.
- make a graphql call, and notice that cognito-identity calls are still made.
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