16. July 2026 By Ewout Albrecht
How to prevent token issues with custom connectors based on OAuth 2.0 in unattended flows
At adesso, integrating Dataverse environments with back-end systems like ERP or HR software is a common scenario. For smaller projects with SMB clients, a custom connector for Power Automate is often the quickest way to get multiple integrations up and running. We built one for Exact, one of the biggest ERP and HR software providers in the Netherlands. The authentication, however, turned out to be trickier than expected.
Especially in smaller Dataverse or Dynamics 365 CE projects with SMB clients, a re-usable, flexible tool such as a custom connector for Power Automate is paramount for quickly delivering multiple integrations.
For that reason, we developed a custom connector for Exact, one of the biggest ERP and HR software providers in The Netherlands. We did, however, struggle a bit with the authentication.
The issue
Exact uses OAuth 2.0 for the authentication of their REST API. More specifically, they support the implicit grant type and authorization code grant type flows. For our scenario, where we want automated integrations using Power Automate, we use the authorization code grant type flow.
So, next up we duly create our app registrations and make sure we have the login credentials, and after some effort we have a nice connector running. We have polling mechanisms to receive changes from Exact and some actions to actually perform CRUD operations.
This all worked fine and dandy until we noticed that after a while our connector started to become disconnected. We reauthenticated and went on our merry way, only to keep discovering this issue.
The actual error we received was either:
{ "error":"unauthorized_client", "error_description":"Old refresh token used." }
Or:
{ "error":"invalid_grant", "error_description":"Token is not allowed, because of invalid or empty chainId" }
Since Power Platform is handling all the authentication requests, this left us scratching our heads.
The cause
A deep dive into Exact's documentation reveals a few things regarding the tokens they return:
- Access tokens are valid for 10 minutes
- Refresh tokens are valid for 30 days
So… if the refresh token is valid for 30 days, how would it be possible to have an old refresh token used? And how does a token become invalid, as per the second error message? The answer lies in the fact that Exact uses consecutive tokens, and we use multiple flows to integrate with Exact.
What happens is that when a new instance of a flow is triggered, the connection tries to reauthenticate at execution time using the access token. If the token is still valid, there is no issue, but if the token is invalid, a new one is obtained using the refresh token.
If the refresh token already has been used to reauthenticate another flow, it is no longer valid, and we get the first message: "Old refresh token used".
If the refresh token has not been used, but another flow has already obtained a newer refresh token, the tokens are no longer used in the right order, and the second error is shown: "Token is not allowed, because of invalid or empty chainId".
The solution
So, how do we solve this issue? Because having to re-authenticate every (several) flow execution(s) is unworkable, especially when running unattended flows, such as those based on timer triggers or triggers from Exact.
Well, that's why custom connectors support OAuth 2.0's offline access scope. This scope is meant for cases where the user is not available to request new access tokens, such as in scheduled Power Automate flows.
And since custom connectors honour this implementation, we can simply add this scope to the default OAuth 2.0 settings of the custom connector. Token renewal is then taken care of by the connector, and we have continuous business processes.
Conclusion
In the end the failures of our OAuth 2.0-based custom connector were not caused by Power Automate itself, but rather by how Exact manages refresh tokens. When multiple flows share the same connection, they can attempt to refresh access tokens independently, causing refresh tokens to be used multiple times or out of sequence.
To solve this, we added the offline access scope in the custom connector's OAuth 2.0 configuration. This addition allows the connector to handle token renewal correctly for unattended and scheduled flows, reducing authentication failures and ensuring stable, continuous integrations.
A final word of warning: have a good look into the token management of the API your connector is using, as this example shows it could present you with some quirky challenges.