This is an extremely annoying unsolved issue that I see more people than I have been, and are(?), struggling with without a solution to date. Please help! Workaround or guidance.

  • Auth Provider (AP): Azure Ad via Open ID Connect. Works fine.
  • Named Credential (NC): OAuth2 using the AP, with Scope including offline_access. Upon saving the NC everything looks and works fine, authorization granted and NC saves without warning about missing refresh token (which is the case if omitting the offline_access in Scope).
  • Apex (future) callout (CO): works fine until the original access token expires, upon which a 401 is received.

I.e. no automatic refresh of the access token, despite having a refresh token.

I have tried adding a "manual" retry call in my Apex CO upon receiving a 401, to no avail.

I have not (yet) set up a proxy in front of the Azure AD auth and token endpoints to see what happens behind the scenes by the NC and AP, and wish it doesn't come to that.

I tried using Beeceptor as a proxy in front of MS Azure AD authorize and token urls, but that does not work at all. Stops at a failing sign in dialog (I can't share a screen shot for privacy reasons).

Error logs:

05:19:50.682 (1682989819)|NAMED_CREDENTIAL_REQUEST|NamedCallout[Named Credential Id=0XAIY00000001PW, Named Credential Name=Azure_Entity_SFChangeEvent, Endpoint=https://prod-12.westeurope.logic.azure.com:443/workflows/qwerty/triggers/manual/paths/invoke?api-version=2016-10-01, Method=POST, External Credential Type=EXTERNAL, HTTP Header Authorization=Method: Bearer - Authorization Credential Hash: -2022866655, Content-Type=null, Request Size bytes=776, Retry on 401=True]
05:19:50.684 (1684291301)|NAMED_CREDENTIAL_RESPONSE|NamedCallout[Named Credential Id=0XAIY00000001PW, Named Credential Name=Azure_Entity_SFChangeEvent, Status Code=401, Content-Type=application/json; charset=utf-8, Response Size bytes=166, Overall Callout Time ms=459, Connect Time ms=278
05:19:50.109 (1692101634)|CALLOUT_RESPONSE|[18]|System.HttpResponse[Status=Unauthorized, StatusCode=401]
05:19:50.187 (1701634210)|EXCEPTION_THROWN|[15]|AzureFutureCallout.AzureCalloutException: 401 Unauthorized {"error":{"code":"SecurityTokenExpired","message":"The provided token is expired and valid till: '6/3/2022 8:39:31 AM' UTC. Please try again with refreshed token."}}
  • 1
    Based on your comments in a very similar question, you understand that this needs debugging via a proxy, the logs won't help you. In a somewhat related SOAP scenario, SF suggests using beeceptor.com as the request interceptor and logger. This service also happens to support a proxy mode. We haven't tried beeceptor but give it a shot, then edit your question to include the results (all relevant HTTP requests/responses)
    – identigral
    Jun 3, 2022 at 15:27
  • The usual disclaimer: enabling a 3rd party to see your tokens is a risk. Recommended approach is to do this exercise in a sandbox and expire the tokens (incl. refresh, if issued) after you're done.
    – identigral
    Jun 3, 2022 at 15:31
  • Similar question with some answers
    – metasync
    Jun 3, 2022 at 16:16
  • I tried using Beeceptor as a proxy in front of MS Azure AD authorize and token urls, but that does not work at all. Stops at a failing sign in dialog (I can't share a screen shot for privacy reasons).
    – Andreas
    Jun 7, 2022 at 7:28
  • @Andreas Bummer! Look for another proxy and/or contact beeceptor for support, it sounds like it should work
    – identigral
    Jun 7, 2022 at 15:36

1 Answer 1


In this particular case, the issue was that Azure AD returns an error upon using the refresh_token for a new access_token.

So, on the Salesforce side of things everything worked fine and as should be.

For anyone interested Azure AD returned when Salesforce tried to refresh the access token: "AADSTS90009 Application is requesting a token for itself. This scenario is supported only if resource is specified using the GUID based App Identifier."

This is resolved by creating two "App registrations" in Azure AD.

One App registration for the service (API/endpoint) on Azure side of things. Having nothing more, basically, than scope definition, such as "api:/..

And one App registration for the client, i.e. Salesforce (with my callout and its auth.provider and named credential). Having a client id, secret callback uri, and a permission to use the scope of the App registration above.

I.e. the above becomes separate from he client's client id guid.

My Salesforce Auth Provider (OpendID) authenticates using the client app registration client Id and secret.

And my Salesforce Named Credential uses the scope definition from the service app registration.

  • Also, ensure the Named Credential API returns 401 when the token is expired instead of 403. Salesforce only attempts to renew the token when the return code is 401. Jan 3 at 23:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .