> ## Content Index
> Fetch the complete content index at: https://www.bulkifiedthinking.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Salesforce Is Changing How Integrations Log In
- URL: https://www.bulkifiedthinking.com/salesforce-is-changing-how-integrations-log-in/
- Published: 2026-10-20T03:53:20.000Z
- Updated: 2026-10-20T03:53:20.000Z
- Description: Salesforce is changing how integrations log in: refresh tokens expire after 30 days unused, the device flow works only from local External Client Apps, and the username-password and user-agent flows retire in February. Here is what breaks and how to check.
- Author: Andrii Sukhetskyi
- Tags: Salesforce Updates

In the upcoming weeks, your organization will face another set of security upgrades designed to strengthen your integrations and add a little bit of suffering to your life.

Allow me to simplify this phase in your life and discuss how you should approach each of these updates, where to look and what to watch for. You can see a complete list of all the changes discussed today below. I am specifically omitting the SOAP API retirement, as we talked about it quite a bit [here](https://www.bulkifiedthinking.com/posts/soap-api-login-retirement-i-think-everyone-has-the-wrong-date/).

| Date         | Change                                                                     | Status    |
| ------------ | -------------------------------------------------------------------------- | --------- |
| Oct 21, 2026 | 30-day idle rule reaches sandboxes, rolling                                | Confirmed |
| Nov 4, 2026  | 30-day idle rule in production                                             | Confirmed |
| Nov 30, 2026 | Device flow only from local External Client Apps with a localhost callback | Confirmed |
| Feb 20, 2027 | Username-password, user-agent and hybrid user-agent flows retired          | Confirmed |

## Refresh tokens expire after 30 days unused

This enforcement is coming up and will start rolling out to your sandboxes **tomorrow**, October 21st, 2026, and to production orgs on **November 4, 2026** (scratch orgs and Developer Edition orgs follow the production date).

The concept of this enforcement is simple: when any external application, VS Code or anything else connects to Salesforce, it gets an access token with a specific scope to access certain data/metadata in Salesforce, and a refresh token, so that it can renew the access token without requiring you to authenticate from scratch.

When configuring such integrations with External Client Apps (or Connected Apps), you could always specify a validity term for the refresh token, and most of us set it to "Refresh token is valid until revoked", which basically means indefinitely.

![](https://storage.ghost.io/c/92/d5/92d55211-2cfe-45c9-b8c4-b7c7b1595cdb/content/images/2026/10/Salesforce-efresh-token-policy-option.png)

Refresh Token Policy

This option will no longer be possible. Additionally, the other option, "Expire refresh token if not used for N", is now capped at 30 days. You cannot set it to more than 30 days. If an external application is trying to access Salesforce after 30 days of silence (no previous calls) - it will need to be re-authenticated.

💡

Salesforce switches every app that had "Refresh token is valid until revoked" to "Expire refresh token if not used for 30 days" for you.

There is also one thing that happens only once, at the moment of enforcement: Salesforce revokes all existing access tokens and immediately expires every refresh token that has not been used for 30 days or more. Therefore, you do not get 30 days of grace, instead, it fails with this error message:

```json
[{"message":"Session expired or invalid","errorCode":"INVALID_SESSION_ID"}]

```

And when I say you will need to "re-authenticate", I mean that someone has to go through the very first login again: log in to Salesforce through that application and approve the access, so that Salesforce issues a brand new refresh token.

### What to Check

To start with, in your sandbox you can activate a new checkbox "Limit Idle Refresh Token Time-to-Live (TTL) to 30 Days" for a particular External Client App or Connected App (or for all of them, one by one). That said, **it won't help you much**. The enforcement starts rolling out to sandboxes tomorrow, so you can just wait it out and see what breaks.

![](https://storage.ghost.io/c/92/d5/92d55211-2cfe-45c9-b8c4-b7c7b1595cdb/content/images/2026/10/image.png)

Limit Idle Refresh Token Time-to-Live (TTL) to 30 Days

With this in mind, your main priority shall be verifying the affected areas yourself, by following these steps:

- Go to Setup → Connected Apps OAuth Usage (and Setup → External Client Apps → OAuth Usage for External Client Apps) and look for any apps that have been used. You can look into those that haven't been used too, but maybe they shouldn't exist at all?
  - **Find the last use.** Click the number in the User Count column to see the most recent use for every user.
  - **More than 30 days ago** \- that's the problem, and it will be affected.
  - **Less than 30 days ago** \- watch it for a few days, contact external teams or look into the documentation to determine the frequency of such calls.
  - **Do it before the enforcement lands.** These pages list only apps with an active token, so once Salesforce expires the idle ones, they simply disappear from the list.

![](https://storage.ghost.io/c/92/d5/92d55211-2cfe-45c9-b8c4-b7c7b1595cdb/content/images/2026/10/image-1.png)

Setup → Connected Apps OAuth Usage

- Use the SOQL query below to find the exact same information on all Connected Apps that were last used more than 30 days ago. Salesforce documents this object for Connected Apps only, so for External Client Apps I would rely on their OAuth Usage page from the previous step.

```SQL
SELECT AppName, User.Username, User.IsActive, CreatedDate, LastUsedDate, UseCount
FROM OauthToken WHERE LastUsedDate < LAST_N_DAYS:30 ORDER BY AppName, LastUsedDate
```

Once you have determined the affected integrations, you can:

- **Keep the frequent ones as they are.** If an integration's LastUsedDate keeps moving (its refresh token is used at least every week), the 30 days never run out. Just make sure it uses that refresh token when its access token gets revoked on enforcement day (just watch your sandbox).
- **Keep the rare ones alive.** For monthly or quarterly jobs (or anything else with an old LastUsedDate), schedule a refresh every 25 days or so. Each refresh resets the 30 days. If you run the first one before the enforcement, it also rescues tokens that have already been idle for longer.
- **Re-authenticate the ones that have already expired**, and write down who connected each of them and how, as you will need it again.
- **Or move them to JWT bearer or client credentials**, which never get a refresh token at all. It is the cleanest fix, but it means changing the integration, so treat it as the long-term solution.
- **Update your source control**
  - Connected App: set `refreshTokenPolicy` to `specific_inactivity:30:DAYS`
  - External Client App: set `refreshTokenPolicyType` to `SpecificInactivity`, with `refreshTokenValidityPeriod` as "30" and `refreshTokenValidityUnit` as "Days".

## Device flow from local External Client Apps

This enforcement lands on **November 30, 2026**. There is no separate sandbox date this time, but it comes as a release update, so you can switch it on in a sandbox yourself before Salesforce does it for you.

The concept of the device flow is simple: an app that cannot show you a proper login page (let's say a command-line tool) asks Salesforce for a short code and shows it to you. You type that code on another device, for example your laptop or phone, then log in and approve the access, while the app keeps asking Salesforce whether you are done.

After November 30, 2026, Salesforce allows this flow only from a local External Client App (created directly in your org, not installed from a package) that has a localhost callback URL, such as [http://localhost:1717/OauthRedirect](http://localhost:1717/OauthRedirect?ref=bulkifiedthinking.com).

![](https://storage.ghost.io/c/92/d5/92d55211-2cfe-45c9-b8c4-b7c7b1595cdb/content/images/2026/10/image-2.png)

External Client App Manager

### What to Check

To start with, go to Setup → Release Updates and open "Restrict the OAuth 2.0 Device Flow to Local External Client Apps". Follow its testing steps in a sandbox, as this is the closest you get to a preview.

![](https://storage.ghost.io/c/92/d5/92d55211-2cfe-45c9-b8c4-b7c7b1595cdb/content/images/2026/10/image-3.png)

Setup → Release Updates

After that, find out who actually uses the device flow:

1. Go to Setup → Login History, create a new view, add the Login Subtype column and look for "OAuth Device". Or run the query below for the last 180 days.

```SQL
SELECT LoginTime, UserId, Application, Status, SourceIp
FROM LoginHistory
WHERE LoginSubType = 'OAuth Device' AND LoginTime = LAST_N_DAYS:180
ORDER BY LoginTime DESC

```

1. Go to Setup → App Manager, open each Connected App and look at the API (Enable OAuth Settings) section. If "Enable for Device Flow" is ticked and the app is still in use - that is your problem.
2. Go to Setup → External Client App Manager → each app → Edit Settings → OAuth Settings. If "Enable Device Flow" is ticked, check two more things: the app must be local, and its callback URL must be localhost.

## Username-password flows are retired

This one is the furthest away, **February 20, 2027** (it was planned for Winter '27 and got postponed). But this is potentially the most time-consuming one, so buckle up.

The reason for this retirement is that all three flows (username-password, user agent and hybrid user-agent flows) have the same problem: they expose either your credentials or your access token.

The username-password flow sends a username, a password and a security token straight to Salesforce and gets an access token back:

```HTTP
POST https://login.salesforce.com/services/oauth2/token
grant_type=password&client_id=<consumer key>&client_secret=<consumer secret>&username=integration@acme.com&password=<password><security token>

```

The user-agent flow (and its hybrid version) returns the access token right in the browser, after the # sign of the redirect URL:

```TEXT
https://app.acme.com/callback#access_token=00D...&instance_url=https%3A%2F%2Facme.my.salesforce.com&token_type=Bearer
```

And indeed, this seems like a security concern and Salesforce has finally decided to address it (not judging, it's a good idea, just annoying).

### What to Check

To start with, go to Setup → OAuth and OpenID Connect Settings. If both "Allow OAuth Username-Password Flows" and "Allow OAuth User-Agent Flows" are off, nothing in your org can use these flows today anyway, so you're good.

![](https://storage.ghost.io/c/92/d5/92d55211-2cfe-45c9-b8c4-b7c7b1595cdb/content/images/2026/10/Salesforce-OAuth-Flow-Options.png)

Setup → OAuth and OpenID Connect Settings

If any of them is on, Setup → Release Updates shows you "Retirement of OAuth 2.0 Username-Password Flow for Connected Apps" and "OAuth User-Agent and Hybrid User-Agent Flows Retirement", each with its testing steps.

That said, your main priority shall be finding who still uses these flows:

- Go to Setup → Login History, create a new view, add the Login Subtype column and look for these four values:
  - "OAuth Username-Password"
  - "OAuth User-Agent"
  - "OAuth User-Agent for Hybrid Apps"
  - "OAuth User-Agent with ID Token"

Or run the query below, which gives you every app and the last time it used one of these flows:

```SQL
SELECT Application, LoginSubType, COUNT(Id) logins, MAX(LoginTime) lastLogin
FROM LoginHistory
WHERE LoginSubType IN ('OAuth Username-Password', 'OAuth User-Agent', 'OAuth User-Agent for Hybrid Apps', 'OAuth User-Agent with ID Token')
AND LoginTime = LAST_N_DAYS:180
GROUP BY Application, LoginSubType
ORDER BY MAX(LoginTime) DESC

```

Once you have determined the affected integrations, you can:

- **Move server-to-server integrations to the client credentials flow.** You do not even need a new app for it. On the same Connected App:
  1. Tick "Enable Client Credentials Flow" in Setup → App Manager → your app → Edit → API (Enable OAuth Settings).
  2. Pick the user it runs as in Manage → Edit Policies → Client Credentials Flow → Run As, ideally a user with the API Only User permission.

Then, the integration will be sending the same consumer key and secret with no password at all:

```HTTP
POST https://MyDomainName.my.salesforce.com/services/oauth2/token
grant_type=client_credentials&client_id=<consumer key>&client_secret=<consumer secret>

```

- **Move user-facing apps to PKCE.** Web apps go to the web server flow with PKCE, and hybrid mobile apps to the hybrid web server flow with PKCE.
- **For apps you didn't build**, such as managed packages, contact the vendor (there is no much you can do here).

## Useful Links  

- [Refresh Token Idle TTL Is Limited to 30 Days](https://help.salesforce.com/s/articleView?id=release-notes.rn%5Fsecurity%5Frefresh%5Ftoken%5Fttl.htm&release=264&type=5&ref=bulkifiedthinking.com)
- [Limit the Idle Refresh Token TTL in Connected Apps](https://help.salesforce.com/s/articleView?id=xcloud.connected%5Fapp%5Flimit%5Fidle%5Fttl.htm&type=5&ref=bulkifiedthinking.com)
- [Limit the Idle Refresh Token TTL in External Client Apps](https://help.salesforce.com/s/articleView?id=xcloud.eca%5Flimit%5Fidle%5Frefresh%5Ftoken%5Fttl.htm&type=5&ref=bulkifiedthinking.com)
- [Restrict the OAuth 2.0 Device Flow to Local External Client Apps (Release Update)](https://help.salesforce.com/s/articleView?id=release-notes.rn%5Fsecurity%5Foauth%5Fdevice.htm&release=264&type=5&ref=bulkifiedthinking.com)
- [Retirement of OAuth 2.0 Username-Password Flow for Connected Apps (Release Update)](https://help.salesforce.com/s/articleView?id=release-notes.rn%5Fsecurity%5Foauth%5Funpw.htm&release=264&type=5&ref=bulkifiedthinking.com)
- [OAuth User-Agent and Hybrid User-Agent Flows Retirement (Release Update)](https://help.salesforce.com/s/articleView?id=release-notes.rn%5Fsecurity%5Foauth%5Fuseragent.htm&release=264&type=5&ref=bulkifiedthinking.com)
- [Block Authorization Flows to Improve Security](https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess%5Fdisable%5Fusername%5Fpassword%5Fflow.htm&type=5&ref=bulkifiedthinking.com)