OAuth 2.0 Token Refresh on 401 Does Not Retry the Original Request — Integration Hub REST
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
2 hours ago
Hi Community,
I am exploring outbound REST integrations using Flow Designer and Integration Hub on a Yokohama PDI, and I ran into a behavior I want to understand and ideally solve without falling back to a fully manual script approach.
---
Setup
I have a local API (Node.js/Express) exposed via ngrok that implements OAuth 2.0 Client Credentials grant. The token endpoint is at /oauth/token and the protected endpoint is POST /incident. I configured the integration in ServiceNow as follows:
- Application Registry: OAuth provider pointing to my /oauth/token endpoint
- Connection & Credential Alias: OAuth 2.0 credential referencing the Application Registry
- Flow Action: Integration Hub REST step using the Connection Alias to POST to /incident
This works correctly when the token is valid.
---
Observed Behavior
To test token expiry handling, I set the token lifetime on my API to 20 seconds. Here is what I observed in my ngrok logs:
1. ServiceNow calls POST /oauth/token → 200 OK (token fetched and cached)
2. ServiceNow calls POST /incident → 201 Created (success, token valid)
3. Token expires on my server
4. Flow is triggered again → ServiceNow calls POST /incident → 401 Unauthorized
5. ServiceNow detects the 401 → calls POST /oauth/token → 200 OK (new token issued)
6. Flow execution ends as failed — the /incident call is NOT retried with the new token
Step 6 is the issue. ServiceNow correctly detects the expired token and successfully fetches a new one, but the current flow execution is abandoned rather than retried with the fresh token.
---
What I Tried
I enabled the Default HTTP Retry Policy on the action and edited it to include an additional condition triggering retry on status code 401, reasoning that since ServiceNow automatically calls the token endpoint on a 401, a retry would pick up the fresh token. However, the retry still receives a 401 — confirmed by ngrok showing the retried /incident call failing again even though /oauth/token returned 200 just before it.
My hypothesis is that the retry mechanism re-uses the token that was loaded into memory at the start of the execution, rather than reading the newly written value from the oauth_credential table. So the retry goes out with the expired token regardless of the refresh.
---
Questions
1. Is my hypothesis about in-memory token caching during a single execution correct?
2. Is there a native way to make the REST step retry the protected endpoint using the freshly fetched token — without abandoning the Connection & Credential Alias approach entirely?
3. Is the recommended production pattern to use RESTMessageV2 with an OAuth profile in a Script step instead of the Integration Hub REST step, specifically because it re-reads the credential on every .execute() call?
4. Is there a platform fix or known workaround for this in Yokohama or Zurich?
Any insight from people who have hit this in production integrations would be appreciated.
Thank you
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
an hour ago
Hi @bwaleed
A 401 error can occur for two reasons:
- The Client ID and Client Secret combination configured in the OAuth profile is incorrect.
- Check whether a MID Server is required in the Flow Action steps. If so, ensure that a MID Server is selected and that it is up and running.
Validate it .
