Skip to content

Salesforce Retires the OAuth Username-Password Flow in Winter '27: Migrate Before Your Integrations Break

Salesforce retires the OAuth 2.0 username-password flow for connected apps in Winter '27. What breaks, how to find affected integrations, and how to migrate.

TL;DR

  • Salesforce is retiring the OAuth 2.0 username-password flow (the one where an integration posts grant_type=password with a username, password, and security token) for connected apps. It ships as a Release Update enforced with Winter '27.
  • When your org reaches its Winter '27 upgrade date, every integration still using that flow stops getting an access token and simply fails to authenticate.
  • It is already blocked by default in newly created orgs, so this is mostly about existing orgs that still have long-running integrations wired the old way.
  • The fix is to move each integration to the client credentials flow or the JWT bearer flow, and to store the credential in a Named Credential rather than a script or config file.
  • A related change is coming right behind it: the SOAP login() call retires on 1 June 2027. If you are touching integration auth anyway, plan for both.

What You'll Learn

  • What the username-password flow is, in plain terms, and exactly what breaks
  • How to find every integration in your org that still uses it, without guessing
  • How to choose between the client credentials flow and the JWT bearer flow
  • The before-and-after for Data Loader, middleware (MuleSoft, Boomi, Informatica), and a custom script
  • Where the per-instance deadline actually comes from, so you can plan the work

The Problem

Most orgs have a handful of integrations that were set up years ago, still run every night, and that nobody has touched since. A worrying number of them authenticate the simplest possible way: the integration sends a Salesforce username, a password, and a security token to the token endpoint, and gets back an access token. That is the OAuth 2.0 username-password flow, also called the resource owner password credentials (ROPC) grant.

Salesforce is retiring it. It passes a real user's password directly in an HTTP request, which is exactly the pattern modern auth is trying to kill, so the platform is removing support for it in connected apps. The change is a Release Update, which means it is not optional and it enforces on your org's Winter '27 upgrade date. On that date, the token request stops working, the integration cannot authenticate, and whatever it was doing (a nightly data load, a middleware sync, a custom script) silently stops. There is no error in the UI for an admin to notice, because the failure happens server to server.

Common questions this article answers:

  • What exactly is Salesforce retiring, and when does my org hit the date?
  • How do I find which of my integrations still use the username-password flow?
  • What do I migrate them to, and how much work is it?

Quick Answer

Salesforce is retiring the OAuth 2.0 username-password flow for connected apps as a Release Update enforced with Winter '27. Any integration that authenticates by posting grant_type=password with a username, password, and security token will stop getting an access token on your org's Winter '27 upgrade date. To find your exposure, check Login History filtered by the login type for OAuth password logins, and review Connected Apps OAuth Usage in Setup. To fix it, migrate each server-to-server integration to the OAuth 2.0 client credentials flow (simplest swap: the connected app runs as a designated integration user) or the JWT bearer flow (certificate-based, no stored password), and keep the secret in a Named Credential. New orgs already have this flow blocked by default, so the work is concentrated in older orgs with legacy integrations. Confirm your exact date in Setup under Release Updates, and cross-check the major-release date for your instance on Salesforce Trust Status.

What the username-password flow is, and what breaks

The flow is a single HTTP request. An integration calls the Salesforce token endpoint like this:

# The retiring flow: grant_type=password (ROPC)
curl https://login.salesforce.com/services/oauth2/token \
  -d "grant_type=password" \
  -d "client_id=<consumer key>" \
  -d "client_secret=<consumer secret>" \
  -d "username=integration.user@example.com" \
  -d "password=<password><security token>"

Salesforce returns an access token, and the integration uses it for the rest of the session. It is popular because it is the least work to set up: no certificate, no redirect, no user interaction. That convenience is the problem. The integration is holding a real user's password, the password travels in the request, and anything that can read that request or the config that stores it has a full credential.

What breaks at Winter '27 is precisely that token request. Salesforce stops honouring grant_type=password for connected apps, so the call returns an error instead of a token, and the integration cannot authenticate. Everything downstream of that token, the queries, the record updates, the file loads, stops with it. Because the break is at authentication, it is total: the integration does not run in a degraded way, it does not run at all.

This applies to connected apps in every edition, across Lightning Experience and Salesforce Classic. It is already blocked by default in newly created orgs, which is Salesforce's signal that the flow is on the way out. Existing orgs keep working until their Winter '27 upgrade lands.

Finding the integrations that will break

You cannot migrate what you have not found, and the integrations using this flow are exactly the ones nobody remembers. Three places show you the truth.

Setup, Release Updates. Open Setup and go to Release Updates. Find the username-password flow retirement update. Salesforce often attaches an assessment to a Release Update that lists affected connected apps or gives you a way to see recent usage. Start here, because it is Salesforce's own view of your exposure and it tells you the enforcement date for your org.

Login History. In Setup, open Login History. Add or sort by the Application and Login Type columns and look for OAuth token-request logins tied to your integration users. Logins that came through the username-password flow show up as OAuth logins from the connected app rather than interactive UI logins. Export the last few weeks to a spreadsheet and group by application and user; each distinct integration user plus connected app pairing is one thing to migrate.

Connected Apps OAuth Usage. In Setup, open Connected Apps OAuth Usage. This lists the connected apps actually being used for OAuth in your org, with the user count behind each. It is the shortlist of apps to inspect, because an app with no OAuth usage is not your problem and an app with active usage from an integration user is.

Between these three, you can build a list of every integration, which connected app and user it uses, and therefore which ones need new auth. If you run the sf-audit plugin, it inventories your connected apps, their OAuth scopes, and your integration and service accounts in one command, which is a fast way to cross-check the list you build by hand. We cover it in Catch Salesforce Security Gaps in One Command.

Choosing the replacement flow

Two flows replace the username-password grant for server-to-server integrations. Pick by whether the integration should act as a fixed user, and whether you can manage a certificate.

Client credentials flow. The connected app is configured to run as a single designated integration user, and the integration authenticates with just the consumer key and secret, no username or password. This is the closest one-for-one swap for most nightly jobs and middleware, because the integration keeps acting as one known user and you only change how it gets its token. The trade is that the connected app is bound to that run-as user, so you manage it as a first-class identity.

# The replacement: grant_type=client_credentials
curl https://login.salesforce.com/services/oauth2/token \
  -d "grant_type=client_credentials" \
  -d "client_id=<consumer key>" \
  -d "client_secret=<consumer secret>"

JWT bearer flow. The integration signs a JWT with a private key whose certificate is uploaded to the connected app, and exchanges it for an access token. There is no password anywhere, which makes it the stronger option for high-value integrations, and it suits automated systems that can hold a private key securely. The trade is certificate management: you generate a key pair, upload the certificate, and rotate it before it expires.

For either flow, store the secret or key outside your integration code. A Named Credential holds the endpoint and the authentication for you, so Apex and middleware reference the Named Credential instead of carrying a consumer secret or a private key in a script or a config file. That is the difference between rotating one credential in one place and hunting through scripts when it changes.

Migrating the common cases

Data Loader and command-line tools. Older Data Loader setups and scripted sf/sfdx jobs sometimes authenticate with a username and password. Move them to an OAuth flow: for interactive Data Loader use the standard OAuth login, and for headless CLI jobs use the JWT bearer flow, which the Salesforce CLI supports directly with a connected app and a key file. The nightly job stops carrying a password and starts exchanging a signed JWT.

Middleware (MuleSoft, Boomi, Informatica, and similar). These connectors almost all support the client credentials and JWT bearer flows; the username-password option was just the easiest checkbox at setup time. In the connection configuration, switch the grant type, point it at a connected app configured for client credentials with an integration run-as user, or at one with your certificate for JWT, and remove the stored password. Test in a sandbox first, because the run-as user's permissions, not the original user's, now govern what the integration can see.

Custom scripts and server-to-server code. Replace the grant_type=password token request with grant_type=client_credentials (shown above) or a JWT bearer exchange. If the script runs inside Salesforce as Apex calling out, move the whole thing behind a Named Credential so there is no token request in your code at all. If it runs outside, put the consumer secret or private key in your platform's secret store, not in the repository.

A note on scope while you are in there: the client credentials flow runs as the user you designate, so give that user a least-privilege permission set rather than reusing a broad admin. Swapping the auth flow is the moment to also fix an over-permissioned integration user, not to carry the old one forward.

Frequently Asked Questions

Q: When exactly does my org hit this deadline?

A: It enforces with your org's Winter '27 major-release upgrade, not on a single global date. Salesforce rolls major releases out by instance, so find your instance on Salesforce Trust Status and check its maintenance window for the Winter '27 date, and open Setup then Release Updates to see the update and its enforcement date for your org. Treat that date as the point after which the old flow no longer works.

Q: We only use this in one old integration. Is it really going to break?

A: Yes. The retirement is a Release Update, so it enforces whether or not you act, and the break is at authentication, so the integration fails completely rather than degrading. A single nightly job that nobody has touched in three years is exactly the kind of thing that stops silently on the upgrade date and is noticed only when the data it loads goes stale.

Q: What is the difference between this and the SOAP login() retirement?

A: They are two separate deprecations of the same bad habit, passing a username and password to authenticate. The OAuth username-password flow retires with Winter '27. The SOAP login() call, used by older server-to-server integrations and some tools, retires on 1 June 2027. If an integration authenticates with a username and password by either route, it needs to move to OAuth, so it is worth auditing both at once.

Q: Do we have to use certificates?

A: No. The client credentials flow needs only a consumer key and secret and a designated run-as user, with no certificate, which makes it the simplest migration for most integrations. Certificates come with the JWT bearer flow, which is the stronger choice for sensitive integrations because no password or secret is stored, but it is not mandatory.

Q: Will this affect our users logging in through SSO or the UI?

A: No. This change is about connected apps authenticating server to server with a password. Interactive user logins, SSO, and the standard OAuth web-server flow are unaffected. The impact is confined to integrations using the username-password grant.

Key Takeaways

  • Winter '27 removes the username-password flow for connected apps. Any integration posting grant_type=password stops authenticating on your org's upgrade date.
  • The failure is silent and total. It breaks at authentication, server to server, with nothing in the UI to warn an admin.
  • Find your exposure in three places: the Release Update assessment, Login History, and Connected Apps OAuth Usage.
  • Migrate to client credentials or JWT bearer, and store the secret or key in a Named Credential rather than in code.
  • Fix the run-as user's permissions while you are there, and plan for the SOAP login() retirement on 1 June 2027 in the same pass.

What's Next?

Recommended Reading:

Action Items:

  1. Open Setup then Release Updates and read the username-password retirement assessment for your org, and note your Winter '27 date from Trust Status.
  2. Build the list of affected integrations from Login History and Connected Apps OAuth Usage.
  3. Migrate each one to client credentials or JWT bearer in a sandbox, behind a Named Credential, and give the run-as user a least-privilege permission set.

Resources & References