Hello everyone, I have been dealing with this issue for more than a week now…
I have this manifest and I am trying to have Salesforce as external provider. The access token is working fine but it does not refresh. How do you usually debug this?
Thanks, @TziortzisKyprianou. I’ve looked at the app’s config, and they seem to be correct. Can you let me know how you are testing to reproduce this issue? What error do you see? I’m also trying to reproduce the error on my end.
As soon as the access token is expired, it never reauthenticates. And obviously, I can’t fetch my data anymore. My app is very basic, having just one view file, see the snippet attached.
I need to understand how forge is handling the refresh flow. In Salesforce, the expires_in property does not exist in the response. When does Forge trigger the refresh if it doesn’t know when it will expire? Is it based on that property? Is it based on the response if its status code is 401 for example? Is it possible to get on a call at some point?
Hey @TziortzisKyprianou, we did some more digging around the logs, we found one user account has provided consent to your app and that request has been successful on our end and we have received the refresh token from Salesforce.
But 30 mins later we see that an API call is made to revoke the user access which deletes all the tokens from our end (including the refresh token). As part of the same action, we also try to revoke the access from Salesforce which returned 404 error.
So next time the app makes an API call, we have to display the consent screen again since we don’t have any tokens on our end.
Have you revoked access for this user from “Connected Apps” in the user’s profile? Is the salesforce app still active?
Yes, I did that while I was testing after my access token was already expired. The Salesforce access token is configured to live only for 15 minutes now. I had to revoke it manually from the connected apps because the calls after the 15 minutes were failing with 401, and Forge app didn’t ask me to login again into salesforce, and the refresh flow was never updating the access token. Would it be useful to reauthenticate again and let it expire on its own to read the logs?
Thanks, @TziortzisKyprianou, the access token is retrieved as a pull mechanism, not as a push. So when the user invokes the forge app again, we check if the existing token is expired, if so we try and contact the provider to get the new token using the refresh token. Till now the logs look ok, the first invocation of the app has retrieved the access token and refresh token.
hey @TziortzisKyprianou, yep I wanted to check the logs for when that issue happens.
I have created an app with salesforce as a provider, I’ll try and get that set up and see if I can reproduce it on my end. I’ll keep you posted.
Hey Ash, I did something different yesterday to check. Instead of redirecting back to Jira when the salesforce provider is called, I redirected locally to my Node app to “debug” the flow and then back to Jira. What I noticed is that indeed when the expires_in doesn’t exist, Jira never calls the refresh flow again. When I redirected back to my node and then back to Jira, I set the expires_in manually to 60. Indeed after I added that, every 60 seconds when I invoke the app, a refresh flow happens.
My assumption is that Forge App is checking this expires_in property every time you invoke the app, and then if time passes, it’s calling the refresh flow. If that’s true, then it is a problem because expires_in is RECOMMENDED in the RFC 6749 but not REQUIRED. RFC 6749: The OAuth 2.0 Authorization Framework
RECOMMENDED. The lifetime in seconds of the access token. For
example, the value "3600" denotes that the access token will
expire in one hour from the time the response was generated.
If omitted, the authorization server SHOULD provide the
expiration time via other means or document the default value.
If the missing expires_in in the response is really the issue, then there should be a workaround for Providers like Salesforce that might not provide this key. Either by calling a different endpoint to get this info or by setting a default time in the manifest file??? I would also love to see a function that allows the developer to force a refresh flow, since the current implementation does not support access tokens revoked manually by the provider… In case of getting a 401 error and refresh token still works there is no reason to ask the user to login again…
hey @TziortzisKyprianou, thanks for your patience.
Yes, you’re right, from our investigation, we found that we rely on the expires_in attribute from the provider to decide if the token needs a refresh. We have an internal enhancement ticket created. Will keep you posted if we create an external facing ticket so you can track it.