Goal: Custom auth to be reliable for all users, all the time.
Steps: We have a "Custom Auth" workflow setup for GraphQL, it produces a JWT based on the currently logged in Retool user and defines it as a variable which is passed as a header. The "Auth trigger" is set to "Every query run".
Sporadically this auth stops working and queries from within apps fail for the user until they navigate to the resource and click "Test auth workflow". Once this is done it will begin working again.
Because this last step always works to rectify the situation it feels like it can only be a Retool bug.
Hey @tommoor — is there a particular requirement to run auth on every query run? How frequently is your resource called?
I’m not entirely sure, but I imagine that setting is for more specific, far less frequent workflows rather than high traffic production queries. Especially GraphQL resources, which can be notoriously hard to secure/auth.
If you’re still in early stages of development, there are potentially better solutions for achieving the same outcome.
This does seem to be a bug on our end, I looks like auth trigger is never running. The token could be expiring and we are not getting a new one despite the fact that this flow is set to run with every query run.
For example:
With this Resource:
We are setting the token param to the value of CUSTOM_TOKEN, which should be defined with the following steps:
As a workaround, we could use a Refresh auth workflow instead of the auth trigger. This flow will run after "any non-200 response when querying a resource."
Hi, thanks for the acknowledgment. The workaround will not work in this case because we're using GraphQL and errors are returned with a 200 response code, as standard for this type of API.
I have changed it to "Time-based expiration" and I'm hoping that will help instead.
Thanks for the update! It sounds like a step in the right direction. Do we know how long it takes for the token to expire? Until this issue with Auth Trigger for every query run is fixed, we could reduce the seconds set for 'Re-run auth only once this many seconds have elapsed' to be lower than what it takes for the token to expire.
Do we know how long it takes for the token to expire?
From our side there is no expiry, from Retool's side I'm not sure how long it takes before it stops working – haven't been able to pin point that. I set the time-based expiration as low as 24h and still saw the issue
Let's try setting the expiration to 24h inside the object we pass to the jwt.sign function, and test it with your existing 24h expiration auth trigger.
I was suggesting manually setting the expiration for the JSON Web Token to ensure that Re-auth is not required because the token is expiring.
For example, if the time-based expiration auth trigger is set to one hour, we could sign the token with an expiration of one hour (or more):
That being said, the token shouldn't have an expiration if it's created without a expiresIn or exp key.
Re-authentication using JWT is required when the token expires, is revoked, or under certain security conditions. Since we are certain that it's not expiring, let's look at the other two options.
Since Retool is generating the token locally and using it, Retool doesn't manage the revocation of tokens directly. However, the token is attached to the user's session, logging out or ending the session in Retool would effectively "revoke" the token from Retool's perspective because it would no longer be available for use. This kind of revocation is more about session management within Retool rather than directly managing the JWT's validity from the server side.
If multiple users were using the same Retool account, they would experience this issue because the second session would invalidate the token from the existing one. But I doubt this is the case because they would also be prompted to log in again, which doesn't sound like it's happening.
The GraphQL endpoint or its associated authentication service is responsible for any revocation, including handling expiration and other security checks. Could you share a screenshot of this part of your setup:
Hi @tommoor, let’s try setting up a refresh auth workflow for your resource, alongside the Auth Trigger for every query run. I checked internally, and it seems the Auth Trigger is actually running the refresh auth flow instead of auth. In your case, it was never running because we did not have a refresh auth workflow set up. In other words, the Auth Trigger was being ignored due to the missing refresh flow.
Regardless of whether or not we receive a non 200 response from GQL, the refresh auth trigger will still run for every query, so this should resolve the issue you’re experiencing.
I'm glad to hear that things have been running smoothly on your end recently!
Thank you for the feedback!I completely agree with your point about improving the UX to prevent a broken setup. I've been working closely with the Resource Auth team on this, and they’ve been actively helping me to address this situation for you. Rest assured, I’ve added your feedback to our internal report, and we'll continue to work on making the refresh workflow a more seamless and required part of the process.
Wanted to follow up on this on behalf of engineering as well- we've updated the custom auth UI and our documentation on refresh auth workflow triggers, thanks again for flagging this for us!