Skip to main content
New tool CRON Expression Builder — preview next run times before you schedule Apex. Open the builder →
Diagram of an OAuth username-password flow retirement migration to Client Credentials and JWT Bearer
Integration

OAuth Username-Password Flow Retirement: Migrate by Feb 20

Salesforce blocks new tokens from the OAuth username-password flow on February 20, 2027, and affected integrations fail without any warning in the UI. This guide shows how to find each one, choose Client Credentials or JWT Bearer for it, and cut over in January with time to spare.

The short answer

Salesforce blocks new tokens from the OAuth username-password flow on February 20, 2027 in every org. Find each integration through Release Updates, Login History and a sandbox test with the flow switched off, then move server-to-server jobs to Client Credentials or JWT Bearer and cut over in production by January.

Key takeaways Check Setup > Release Updates for "Retirement of OAuth 2.0 Username-Password Flow for Connected Apps"; if it is missing, your org already blocks the flow. Export a Login History inventory of OAuth Username-Password logins every month, because history only goes back about six months. Switch off "Allow OAuth Username-Password Flows" in a sandbox and force every integration to request a fresh token to confirm the list. Default middleware, ETL and scheduled jobs to Client Credentials against your My Domain token endpoint; use JWT Bearer where you want a certificate with no shared secret, or need to act as specific pre-authorized users. Cut over production in January and stay away from the week of February 20, 2027.

A nightly sync finishes green, processes zero records, and nobody notices until a pipeline report comes up short two days later. That is how the OAuth username-password flow retirement will show up in most orgs. Middleware that posts a username, password and security token with grant_type=password starts getting invalid_grant back, and Salesforce shows no banner anywhere. Enforcement lands on February 20, 2027, and this guide covers finding each affected integration, picking its replacement, and cutting over with weeks to spare.

Why a fixed date is harder to plan around

Most enforcements arrive with a major release, so teams plan against their instance's upgrade weekend and use the sandbox preview as an early warning. This one was first scheduled for Winter '27 and then moved to a calendar date: February 20, 2027, a Saturday, which Genesys notes lines up with the Spring '27 release date. Every org hits it on the same day whenever its instance upgrades, so no sandbox breaks a few weeks early to warn you.

The failure is also delayed. Existing sessions keep working, and an integration breaks the next time it asks for a new access token. A job holding a cached session can look healthy for hours after enforcement and then fail on its next refresh. You will see invalid_grant or authentication failure in the middleware log, and Login History may record a status such as "OAuth Username-Password Flow Disabled". If the job swallows auth errors, all you see is records that stopped changing.

The same enforcement shuffle moved several other dates. Put them on one calendar, because the same people will be touching the same apps:

Date Change What to do
December 1, 2026 Maintain Your Email Verification Exception (replaces the cancelled "Adopt Authorized Email Domains") Support can no longer switch off Email Change Verification. Set up DKIM signing or an authorized email domain before your next bulk user email update.
Winter '27 Assign Use Any API Auth Permission for SOAP login() PermissionsUseAnyApiAuth becomes mandatory for SOAP login() callers.
February 20, 2027 Retirement of OAuth 2.0 Username-Password Flow for Connected Apps New grant_type=password token requests fail.
Spring '27 Update Instanced URLs in API Traffic Calls to hostnames like na139.salesforce.com stop working. Use My Domain. This is its third scheduled window.
June 1, 2027 SOAP API login() retires See the SOAP login audit.
Summer '27 Legacy connected apps lose full support See connected apps end of support.

The device flow has its own end date, covered in the device flow post.

Find every integration still using the password grant

Start in Setup > Release Updates and look for "Retirement of OAuth 2.0 Username-Password Flow for Connected Apps". If the entry is missing, your org already blocks the flow. Orgs created in Summer '26 or later block it by default, so a working integration in a newer org is already on another grant. Older orgs need an inventory.

In Setup > Login History, create a list view filtered on Login Subtype equals "OAuth Username-Password" and add Login Subtype as a column. Two limits apply: history goes back about six months, and a list view caps at 20,000 records. A quarterly job, or one that held a session for months, can be missing from the results. I have seen a year-end reconciliation job escape an audit exactly this way and fail on the one night it mattered.

For a repeatable inventory, pull the raw rows and group them in the export:

SELECT Application, UserId, LoginTime, LoginSubType, SourceIp, Status
FROM LoginHistory
WHERE LoginTime = LAST_N_DAYS:90
  AND LoginType = 'Remote Access 2.0'
ORDER BY Application, LoginTime DESC

Filter the export on the LoginSubType column and pivot by Application and UserId to get one row per integration. Check the subtype value against one known row first, because the stored value can differ from the UI label. If your API version rejects LoginSubType, drop it from the query and rely on the list view for that column. Run this monthly and keep the exports, so the six-month window never erases an integration you saw once.

Then widen the search:

  • In Setup > App Manager, record the purpose, owner and authentication method of each connected app. Skip the Connected Apps OAuth Usage page for this job, because it does not list username-password integrations even when they are active.
  • Search repositories, middleware configs and secrets stores for grant_type=password and "ROPC". Hits on /services/oauth2/token are leads only, since every OAuth flow shares that endpoint.
  • Ask every vendor whose package authenticates into your org which grant it uses.

Confirm the list in a sandbox. In OAuth and OpenID Connect Settings, turn off "Allow OAuth Username-Password Flows", then run each integration. Clear cached tokens or restart the connector first so it requests a fresh token. Anything that fails belongs on your list.

Choose Client Credentials or JWT Bearer per integration

Client Credentials JWT Bearer Web Server + PKCE
Runs as The Run As user configured on the app The pre-authorized user named in the token's subject The person who signs in
Held by the caller Client ID and secret Private key (certificate uploaded to the app) Client ID; the user signs in
Interactive No No Yes
Renewal Request a new access token; no refresh token Sign a new assertion Refresh token
Best for Middleware, ETL, scheduled jobs, data sync Certificate-based server auth, or acting as specific users Apps where individual users sign in

My default for middleware and ETL is Client Credentials, provided a single integration user is acceptable. It is the smallest change from the password grant: one secret, one request, no key handling. The cost is secret sprawl. Every middleware instance holds a client secret, and rotating it means touching each one.

I pick JWT Bearer when the security team does not want a shared secret stored in middleware, or when the integration has to act as particular pre-authorized users so that record ownership and audit trails stay accurate. The cost is certificate management. Certificates expire, and an expired one takes the integration down as completely as the retirement would. Put the expiry date in the same tracker as the integration owner. The JWT bearer webhook walkthrough covers building the assertion. Anything with a human signing in belongs on Web Server flow with PKCE.

Cut over: app, run-as user, token request, test

Build the new app as an External Client App so you are not migrating it again before Summer '27. Moving an existing connected app across leaves its password-grant callers exactly where they were, so the token request has to change too. Enable the Client Credentials flow and set a Run As user.

For that user, start with the account the integration logs in as today. Permissions, sharing and field access then stay identical, and the cutover tests the auth change on its own. Move to a dedicated, least-privilege integration user as a separate change later.

The token request change looks like this:

# Before: password grant, fails after February 20, 2027
curl -s https://login.salesforce.com/services/oauth2/token \
  -d grant_type=password \
  -d client_id="$ORDERSYNC_CLIENT_ID" \
  -d client_secret="$ORDERSYNC_CLIENT_SECRET" \
  -d username="[email protected]" \
  --data-urlencode password="${ORDERSYNC_PASSWORD}${ORDERSYNC_SECURITY_TOKEN}"

# After: client credentials against the My Domain token endpoint
curl -s https://northwind.my.salesforce.com/services/oauth2/token \
  -d grant_type=client_credentials \
  -d client_id="$ORDERSYNC_CLIENT_ID" \
  -d client_secret="$ORDERSYNC_CLIENT_SECRET"

Client Credentials needs the My Domain host. A request to login.salesforce.com with that grant will fail. In a sandbox the host looks like northwind--uat.sandbox.my.salesforce.com. The response carries no refresh token, so middleware that stored one and called the refresh grant needs a small change: on a 401, request a new access token with the same call.

For JWT Bearer, the middleware signs an assertion with its private key and exchanges it:

curl -s https://northwind.my.salesforce.com/services/oauth2/token \
  -d grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer \
  -d assertion="$ORDERSYNC_SIGNED_JWT"

Test each integration in the sandbox with the password flow switched off, so a fallback to old credentials fails loudly. Here is the plan I would run. Between now and November, export the inventory monthly and build the new apps. In December, finish the sandbox tests. In January, cut over production and watch Login History for remaining password-flow logins. Once it has shown nothing for a few weeks, I would turn off "Allow OAuth Username-Password Flows" in production in early February. A straggler then fails on a weekday with the team watching, and nothing changes during the week of February 20.

Third-party connectors with their own notices

Oracle Integration: Salesforce Adapter connections using the ROPC security policy work until the February 20, 2027 release. Oracle's migration target is its "Authorization Code Credentials" security policy, so the Client Credentials steps above do not apply to this adapter. Migrate the connected app to an External Client App if it qualifies, create or update the connection with the new policy, then replace the connection in each integration, refresh endpoints and reactivate. The Salesforce REST Adapter is unaffected because it never supported ROPC. Oracle also recommends My Domain over instance URLs, which covers the Spring '27 change too.

Genesys: Salesforce Data Actions using username-password must move to Client Credentials before the date. Genesys advises building and validating the new integration first, with the External Client App running as the same Salesforce user as the existing one. Credentials on existing integrations can then be updated in place without downtime or republishing. External Contact Sync is handled by a different Genesys team, so open a ticket for it.

Medallia for Salesforce: Invitation sync, Response sync and customer-specific Omni Exporters that authenticate directly with Salesforce are affected. You create a customer-owned External Client App with Client Credentials and a dedicated Run As user with API, object, field and record access, then share the client ID and secret through an approved channel. Each Omni Exporter's login configuration then changes to grant_type client_credentials with the client ID and secret. Validate the token and run an end-to-end test before enforcement.

UiPath: I have found no confirmed vendor guidance yet, only community forum threads. Ask UiPath directly and check the authentication settings on your Salesforce activities.

What to watch for

  • Cached sessions hide the break. Force fresh tokens in every test.
  • An empty Login History view proves nothing, given the six-month window and the 20,000-record cap.
  • The Connected Apps OAuth Usage page leaves username-password integrations off its list.
  • Changing the grant to Client Credentials without moving to the My Domain token endpoint fails immediately.
  • Middleware still holding instance hostnames will break again in Spring '27. Replace them with My Domain while you are editing the config.
  • The worst failures are jobs that report success on zero records. Add an alert on empty runs before you start cutting over, so you can trust the result afterwards.

Originally reported by salesforcedictionary.com

Frequently asked questions

When does Salesforce block the OAuth username-password flow?

February 20, 2027, for every org on the same day. It was first scheduled for Winter '27 and later moved to this fixed date, which does not follow your instance's upgrade weekend.

What error do I get when grant_type=password is blocked?

Token requests return invalid_grant or an authentication failure, and Login History may show a status such as "OAuth Username-Password Flow Disabled". Nothing appears in the Salesforce UI, so the middleware log is usually the first place it shows up.

Does migrating my connected app to an External Client App fix the username-password flow retirement?

No. The integration has to request tokens with a different grant, such as Client Credentials or JWT Bearer. Moving the app to an External Client App is worth doing ahead of Summer '27 anyway, but the auth method still has to change.

Why does my Salesforce client credentials token request fail on login.salesforce.com?

The client credentials flow needs your My Domain token endpoint, for example https://yourdomain.my.salesforce.com/services/oauth2/token. Swap the generic login host when you change the grant type.

How do I find integrations using the username-password flow if Login History is empty?

An empty result proves nothing, because Login History keeps about six months and list views cap at 20,000 records. Search code and config for grant_type=password and ROPC, ask vendors about their packages, and run a sandbox test with "Allow OAuth Username-Password Flows" turned off.

Newsletter

One email every Tuesday

New guides, tool updates, and the release-note changes that break things.

No spam. Unsubscribe in one click.

Comments

Loading comments...

Leave a Comment