-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Error Graphql Error running query [query]. Authmode Cognito. Error: Unauthorized #13710
Comments
Finally, is my issue happening because in the GraphQl headers I am swapping IdToken for AccessToken?
Or does that have nothing to do with it? |
TEMP SOLUTION!!!!
I am testing if a token is about to expire within a 1/2 minute and then force a refresh. This worked for me because I triggered my API just as the accessToken was about to expire and it fetched a new token and loaded the music. |
Hey, @mattiLeBlanc 👋. It looks like there this issue has many similar details captured within the existing #13541 that you opened. Is there a need to keep this issue open rather than follow up within that one? Let me know if I'm missing any specific differences here, but wanting to make sure we help you efficiently within a single issue so the responses/context isn't lost. |
@mattiLeBlanc, wanted to follow up and double check on what the use case is here for calling the API's directly within your |
Hi @cwomack , I think this issue is more isolated now and accurate. Before I also had Federated JWT issue which I have resolved. |
Hi Chris, what I am doing in the headers is purely swap the accessToken for the idToken on each Graphql Request because I store custom data. Then yesterday I found out my accessToken doesn't get refreshed if a graphql query is executed right at the expiry moment of the token (it will use the expired token and result in unauthorised). But that didn't seem to work, I just got multiple errors in my console and not multiple POSTs to my grahpl endpoint (on unauthorised and then the retries with a valid auth token). SO, i thought how about force a refresh of the token if is about to expire. Does that answer your question? |
Hi @mattiLeBlanc 👋 thanks for opening this issue. At the moment your workaround of checking and force refreshing the tokens makes sense but there might be a race condition because even though you provide a token the graphql client internally performs its own fetchAuthSession call so we are discussing this internally as something that could use improvement. That being said, I've marked this as a bug for us to track |
Thank you. |
I think you are right. If the solution could be that when fetchAuthSession is called and it has not token, it may check if it can refresh the token based on a valid refresh token before throwing the error? |
Hi all, thanks for all the debugging so far! It's not super clear to me if #13541 is tackling the error I can see why the GQL mutations on localhost are failing - it's missing certain fields like "Authorization" in the request headers. export const cookieBasedClient = generateServerClientUsingCookies({
config:{...awsExports},
cookies,
}); The odd thing is if i don't make any queries from localhost for about ~12 hrs then attempt it again it'll work for ~5mins! then start throwing the jwt error. It seems like Here are the headers, localhost vs develop. POST /playground HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:129.0) Gecko/20100101 Firefox/129.0
Accept: text/x-component
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
Referer: http://localhost:3000/playground
Next-Action: 66296251718b88f81bc71510fbdbc3278914bc82
Next-Router-State-Tree: %5B%22%22%2C%7B%22children%22%3A%5B%22playground%22%2C%7B%22children%22%3A%5B%22__PAGE__%22%2C%7B%7D%2C%22%2Fplayground%22%2C%22refresh%22%5D%7D%5D%7D%2Cnull%2Cnull%2Ctrue%5D
Content-Type: multipart/form-data; boundary=---------------------------168850550536958586124075283889
Content-Length: 819
Origin: http://localhost:3000
Connection: keep-alive
Cookie: CognitoIdentityServiceProvider.3asq47ba2k87lvd00etkfg3kj8.LastAuthUser=username@gmail.com;
CognitoIdentityServiceProvider.3asq47ba2k87lvd00etkfg3kj8.username%40gmail.com.accessToken=xxx
CognitoIdentityServiceProvider.3asq47ba2k87lvd00etkfg3kj8.username%40gmail.com.idToken=xxx
CognitoIdentityServiceProvider.3asq47ba2k87lvd00etkfg3kj8.username%40gmail.com.refreshToken=xxx
CognitoIdentityServiceProvider.3asq47ba2k87lvd00etkfg3kj8.username%40gmail.com.signInDetails={%22loginId%22:%[email protected]%22%2C%22authFlowType%22:%22USER_SRP_AUTH%22};
CognitoIdentityServiceProvider.3asq47ba2k87lvd00etkfg3kj8.username%40gmail.com.clockDrift=-772
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Priority: u=0 Request Header Develop POST /playground HTTP/2
Host: develop.d1wp9ljz13k7ch.amplifyapp.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:129.0) Gecko/20100101 Firefox/129.0
Accept: text/x-component
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
Referer: https://develop.d1wp9ljz13k7ch.amplifyapp.com/playground
Next-Action: a1defeb1166b15ac8dd3085b8e9f4e5e88423a01
Next-Router-State-Tree: %5B%22%22%2C%7B%22children%22%3A%5B%22playground%22%2C%7B%22children%22%3A%5B%22__PAGE__%22%2C%7B%7D%2C%22%2Fplayground%22%2C%22refresh%22%5D%7D%5D%7D%2Cnull%2Cnull%2Ctrue%5D
Content-Type: multipart/form-data; boundary=---------------------------108270092293532131151870777
Content-Length: 605
Origin: https://develop.d1wp9ljz13k7ch.amplifyapp.com
Authorization: Basic YWRtaW46RzdaQ25wOGg=
Connection: keep-alive
Cookie: CognitoIdentityServiceProvider.3asq47ba2k87lvd00etkfg3kj8.LastAuthUser=username@gmail.com;
CognitoIdentityServiceProvider.3asq47ba2k87lvd00etkfg3kj8.username%40gmail.com.accessToken=xxx
CognitoIdentityServiceProvider.3asq47ba2k87lvd00etkfg3kj8.username%40gmail.com.idToken=xxx
CognitoIdentityServiceProvider.3asq47ba2k87lvd00etkfg3kj8.username%40gmail.com.refreshToken=xxx
CognitoIdentityServiceProvider.3asq47ba2k87lvd00etkfg3kj8.username%40gmail.com.signInDetails={%22loginId%22:%[email protected]%22%2C%22authFlowType%22:%22USER_SRP_AUTH%22};
CognitoIdentityServiceProvider.3asq47ba2k87lvd00etkfg3kj8.username%40gmail.com.clockDrift=-237
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Sec-GPC: 1
Priority: u=0 I hope all that makes sense, happy to open a new issues if need be. |
Hi @thedevopsguyblog at a glance I don't think the issue you encountered is unrelated to this one. Were the request headers you pasted were from the requests sent to your server action? (I presume so as it showed context type as form-data). If so, the In addition, when you get the error such as |
Hi @HuiSF, sorry for the delay, went to Germany! Here are some basic troubleshooting steps I took...
{
"name": "NoSignedUser",
"underlyingError": {
"name": "NotAuthorizedException",
"$metadata": {
"attempts": 1,
"httpStatusCode": 400,
"requestId": "abce83d8-35bd-4d69-9e0b-3c8b38e32fa7"
}
},
"recoverySuggestion": "Review the underlying exception field for more details. If you intended to make an authenticated API request, review if the current user is signed in."
} Interesting point, The client side S3 storage API const uploadFiles = files.map(async (f) => {
try {
await uploadData({ data: f, path:(identityId) => `protected/${identityId.identityId}/${formattedDate}/${f.name}`}).result.then((uploadedFile) => {
fileUploadResults.push({ name: uploadedFile.path, etag: uploadedFile.eTag! })
}
)} catch (error) {logger('REQ', 'UP', `Error:\n ${error}\nUploading file: ${f.name}`, 'error')}
}) I also seem to be experincing this issue in my amplify hosted app which is concerning as before this it was isolated to http://localhost:3000/ so I'm unsure how to proceed. I'll try digging into cloudwatch logs to see if the error message is the same as local development. |
Hi @thedevopsguyblog when you call |
No stress, how do I check the TTL of the refresh token? Does that exist on the return value of fetchAuthSession? |
Hey @HuiSF any update on this? |
@HuiSF I am still waiting on an update. We are still experiencing errors like Any news on this? Also, I am doing this in my
and the I know this Extra security option in Cognito allows me to customise my accesstoken but that is paid feature. And I don't think it should be. We should be able to choose if we pass ID token or Access Token to Appsync backend, right? It has almost the same information. |
@cwomack Hi Chris, is there a solution coming? I am forced to use Since I am getting no real response here, I am going to try to get the localstorage idtoken, decode it and see if it is expired already and try a forceRefresh in the hope that will resolve the issue for me. But I would appreciate an update on this. I know your team is busy, but I am waiting for this for many months now. Matti |
@mattiLeBlanc, appreciate your patience on this. Can you confirm what version of Amplify you're on? I ask because this may be resolved by changes we made to how tokens were unexpectedly cleared in v6.6.7. If you're on a lower version than this, can you see if upgrading to that (or latest ideally) helps resolve the issue? |
@cwomack After talking to AWS Business Support yday, I did a series of tests, including calling fetchAuthSession just before the Graphqp call is done, besides also doing it in the headers. In productcion I am still running 6.4.3 but I will upgrade that soon to 6.8.2. I can give you the AWS Support case if you want to look into what we tested there? |
Hi @mattiLeBlanc! Appreciate your patience on this. We've just released a tagged release that should mitigate some of the challenges you're encountering here. You can install this tagged version with npm install aws-amplify@token-exp-tolerance Please keep in mind the implementation is experimental and not for production, but let us know if this improves the situation on your end! We will keep testing as well to ensure everything is stable prior to a formal release. |
@jjarvisp I haven't been able to reproduce with the new version. |
Thanks for testing @mattiLeBlanc! We'll do what we need to do on our end to finalize this and follow up here once released. |
@jjarvisp Did you find anything off in the code that would have caused this issue? I am experiencing some other issues with our customers:
I have a refresh token for this customer (I can see that in my logging) which is valid for 10 years. The cognito user has permissions to do the query. So I am not sure if we are looking at a missing AccessToken (which would be caught by an Auth guard in my app and redirect back to login).
For this error I see there is no Refresh token, but apparently the user WAS Logged in, otherwise they wouldn't be on the page that triggers the getCategories query. |
Hey @mattiLeBlanc, I didn't see anything specific beyond the cause for the root issue here, but have you looked into upgrading to >= v6.6.7? I'm asking because there was a fix that went out with that version to handle the unexpected clearing of tokens; which could likely explain what you're seeing. |
@jjarvisp We would have been running 6.9.0 on production and now upgraded to 6.10.0. |
@jjarvisp James, when are we expecting this to be merged into the master? |
Hey @mattiLeBlanc, thanks for your patience! This has been merged to main and released to the |
Before opening, please confirm:
JavaScript Framework
Angular
Amplify APIs
GraphQL API
Amplify Version
v6
Amplify Categories
auth, api
Backend
None
Environment information
Describe the bug
I am seeing the clientside JS error
Error: Graphql Error running query getMusicStream. Authmode Cognito. Error: Unauthorized
occur many times in our client logging system.It is caught by the custom Angular Error handler that will redirect to an Oops page which is okay for a real error, but not this one.
The cause is an expired accessToken, I am sure of it.
The error was reported at 8:25 AM
When I look at the accessToken for this request (I logged that too), I see the expiry was at 8:25:
There is a valid Refresh token present.
The user did an action which resulted in a graphql Api call which caused the above issue and then resulted in an Oops page, instead of being issues a new accessToken by the graphql Api client code.
When does it issue not happen:
I was logged into our production system, last time used yesterday, so my accesstoken is expired. I got to the same URL with my dev console open. The application works as expected, new token is retrieved which is valid for 15min and the page displays. No error.
So the mechanism works fine this way.
The issue seems to be a live session where the accessToken expires and needs to be renewed; a graphql error slips through.
Question: is that by design or a bug?
Question: if I tell my custom error handler to ignore this, will the graphql Api attempt another call with a new accessToken, or will the JS Error mean the end of the execution and the application is dead as of that moment until a customer does a reload?
Expected behavior
I expect when an accessToken is expiring at the same moment a API call is made, I do not receive an UNAUTHORISED error.
Maybe the grahpql client code should consider each token that is about to expire within 15 seconds as expired and retrieve a new accessToken so that the API call that follows will not receive the UNAUTHORISED error.
Maybe that is already how the system works, not sure.
Reproduction steps
-Login to cognito via Amplify client in an Angular app
-Have an Graphql API call ready that requires you to be logged in to Cognito
-wait for the accessToken to expire and run a couple of API calls to try to trigger this error. Sometimes it happens, sometimes it doesnt.
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
The text was updated successfully, but these errors were encountered: