Restricted usage of the `Salesforce CLI` connected app
Salesforce CLI requires a connected app in the org that you're authorizing. We provide a default connected app (called Salesforce CLI) when you authorize an org with the org login web command. The Salesforce CLI connected app is uninstalled by default.
Salesforce recently restricted the use of uninstalled connected apps, which in turn affected the default Salesforce CLI connected app usage in these two ways.
OAuth 2.0 Device Flow is Blocked in the Default Salesforce CLI Connected App
Starting on 8/28/2025, new and existing authorizations to any org using the OAuth 2.0 Device Flow that also use the default Salesforce CLI connected app will be blocked.
For example, if you use the org login device CLI command with the default Salesforce CLI connected app, then starting on 8/28/2025 the authorization will be blocked.
We recommend that instead of the OAuth 2.0 Device Flow, you use a different OAuth 2.0 flow, such as:
- Web Server Flow: Authorize an org using a browser. CLI command:
org login web. - JWT Bearer Flow: Authorize an org in a headless environment, such as CI. CLI command:
org login jwt.
See Prepare for Connected App Usage Restrictions Change for additional details.
NOTE: You can't work around this issue by installing the default Salesforce CLI connected app and enabling device flow, because the Enable for Device Flow option in the API (Enable OAuth Settings) section has been disabled. You must now be the org admin to install the Salesforce CLI connected app.
New Org Permission Required to Use the Default (Uninstalled) Salesforce CLI Connected App
As of September 2025, users can use uninstalled connected apps only if they have the new Approve Uninstalled Connected Apps user permission. Org administrators have this permission by default.
Because the default Salesforce CLI connected app is uninstalled by default, you must now also have the new user permission to use the connected app.
See Prepare for Connected App Usage Restrictions Change for additional details.
Lol. This is going to piss off a lot of lazy DevOps engineers.
So, right now I'm not able to create scratch orgs and I believe this is the source of the problem. Salesforce CLI is installed in my Prod Org(which is also DevHub), it creates the scratch org but the flow stops when the cli tries to connect to the new scratch org. To give you more info, we use a org shape to create the scratch orgs and after a few minutes to create the scratch, I got the message
Error (AuthCodeExchangeError): Error authenticating with auth code due to: invalid_app_access::user is not admin approved to access this app
Workaround:
Change the project-scratch-def.json to use
"release": "preview"
Can we add remote browser support? I want to SSH into a remote dev environment and run sf org login web. Right now, that fails because there are no browsers to open.
It's easy to get around this with VSCode, since dev tunnels port forward automatically. However, it would be ideal to be able to pass flags like --port and --no-browser to sf org login web. Short of this, users like me will need to find a way to patch xdg-open in remote environments.
Why don't you just use JWT auth flow. You can store the certificate in a secret variable in GitHub Actions, and use it at runtime to authenticate using sfdx or sf cli. No username, passwords or connected app client secrets required.
As a consultant, I'm often connecting to new orgs for the first time. If no one has ever used the CLI in an org, the app will not be installed. That means if I want to authorize with the CLI with Web Server Flow, I must either:
- Be granted the Approve Uninstalled Connected Apps user permission, or
- Be granted access directly to the app after it is installed in the org
My question is that about the second option: is there any way to install the CLI Connected App into the org besides first giving someone the new User Permission, and having them log in, so that it appears in "Connect Apps Oauth Usage", where the install button lives? I've searched but cannot find a way to install the connected app unless someone has already logged in with the app at least once.
It's not called connected app anymore. It's now called external client apps.
Server to server integration, better use JWT bearer flow (without user interaction).
I’m a system admin with the “Approve Uninstalled Connected Apps” permission. I’m trying to connect a brand new org to VS Code for the first time using the command:
'sf org login web'
However, the connection is being refused. Am I missing a configuration step?
@MatheusAugustoDeSouza if you are setting up machine-to-machine automated processes, then 'sf org login web' is not advised because it requires human interaction.
Instead use: sfdx force:auth:jwt:grant -i "YOUR_SF_CONNECTED_APP_CLIENT_ID" -f server.key --username "YOUR_SALESFORCE_USERNAME" -r "SF_LOGIN_URL" -s
SF_LOGIN_URL is "https://login.salesforce.com" for PROD and "https://test.salesforce.com" for Sandboxes.
server.key is a file stored in the same local folder that sfdx is running in. This server.key file is the result of running the following commands on a Windows, Unix or Mac in a terminal window:
- openssl genpkey -algorithm RSA -out server.key -pkeyopt rsa_keygen_bits:2048
This will generate the server.key file locally. This is your PRIVATE KEY. This is what the sfdx force:auth:jwt:grant command needs. However you also need to complete the steps below to get the corresponding PUBLIC KEY to upload to Salesforce.
- openssl req -new -key server.key -out server.csr
This will generate a certificate request file which is needed to generate a PUBLIC KEY (step 3 below). Once you enter the above command, just fill out the fields with random info as below:
Country Name (2 letter code) []:GB State or Province Name (full name) []:State Locality Name (eg, city) []:City Organization Name (eg, company) []:Name Organizational Unit Name (eg, section) []:Unit Common Name (eg, fully qualified host name) []:github.com Email Address []:[email protected]
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
- openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
This will use the server.csr file generated in step 2 above, and use it to generate the server.crt file (the PUBLIC KEY) which you then need to upload to your JWT-enabled Connected App in Salesforce.
Can we add remote browser support? I want to SSH into a remote dev environment and run
sf org login web. Right now, that fails because there are no browsers toopen.It's easy to get around this with VSCode, since dev tunnels port forward automatically. However, it would be ideal to be able to pass flags like
--portand--no-browsertosf org login web. Short of this, users like me will need to find a way to patchxdg-openin remote environments.
I'd like to reiterate that this is definitely a QoL issue right now for teams using Dev Containers.
@dclappert im guessing you've not read anything about the suggestions above to use JWT certificate based machine-to-machine web-server auth flows rather than "sf org login web" which requires human interaction.
Thanks for the feedback. We already use JWT-based auth for our CI pipelines, and other server-to-server integrations. The dev container use case is different though, since it’s still a local development workflow, just running inside a containerized environment. I wouldn’t categorize that as a server-to-server integration.
Forcing users to adopt JWT auth in this context creates unnecessary friction. Developers often need to switch between many orgs and environments, and requiring JWT setup for each one leads to bad DX and slows down iteration. The sf org login web flow, while interactive, is much more aligned with how developers actually work day-to-day.
Thanks a lot, a quick session turned into a nice ordeal.
Can we add remote browser support? I want to SSH into a remote dev environment and run
sf org login web. Right now, that fails because there are no browsers toopen.It's easy to get around this with VSCode, since dev tunnels port forward automatically. However, it would be ideal to be able to pass flags like
--portand--no-browsertosf org login web. Short of this, users like me will need to find a way to patchxdg-openin remote environments.
(Note: agreeing with the post above)
Use of xdg-open (if installed into the devcontainer) should make this transparent.
This works transparently for AWS SSO - their equivalent cli to login via is aws configure sso.
If you have a devcontainer on a remote host with a dockerfile like:
FROM docker.io/salesforce/cli:latest-rc-slim
RUN sf plugins install code-analyzer; \
apt-get update; \
apt-get install -y xdg-utils
Then running
xdg-open https://google.com
Will pop up this on the local workstation from VSCode, and then navigate to the web site:
vscode devcontainers set a BROWSER environment variable:
BROWSER="/vscode/vscode-server/bin/linux-x64/f220831ea2d946c0dcb0f3eaa480eb435a2c1260/bin/helpers/browser.sh"
which is respected by xdg-open
This method needs to be updated to recognise remote web browsing: https://github.com/salesforcecli/plugin-auth/blob/1dc3de68e90ff4712259e79ba7f0087dc23e87b1/src/commands/org/login/web.ts#L204 So it doesn't throw the error: https://github.com/salesforcecli/plugin-auth/blob/1dc3de68e90ff4712259e79ba7f0087dc23e87b1/src/commands/org/login/web.ts#L100
It looks like this line would be needed to support xdg-open :
https://github.com/salesforcecli/plugin-auth/blob/1dc3de68e90ff4712259e79ba7f0087dc23e87b1/src/commands/org/login/web.ts#L39
options: ['chrome', 'edge', 'firefox'], // These are ones supported by "open" package
@stephen-cox-nzx @stephenlf
In the CLI docs, there is an environment variable called SF_CONTAINER_MODE which is suppose to output the URL to the console when set to true for org open and org login web commands. I couldn't get it working however (and opened an issue for it)
@mhemani-reach Issue #3415, that's exactly it! Thanks!
In the meantime, I worked around the issue by connecting to the remote host with VSCode. VSCode intercepts xdg-open $BROWSER and sets up port forwarding automatically. It's not perfect, but it's something.
Here is a successful workaround based on the info from @mhemani-reach and @stephenlf .
Replace <YourSandboxAlias>, <MyDomainName> and <SandboxName> as appropriate:
export SF_CONTAINER_MODE=false
export SFDX_CONTAINER_MODE=false
alias firefox='xdg-open'
sf org login web --alias <YourSandboxAlias> --instance-url https://<MyDomainName>--<SandboxName>.sandbox.my.salesforce.com
# run a test command
sf apex list log -o <YourSandboxAlias>
This is using this devcontainer:
{
"name": "Salesforce Project",
"dockerFile": "Dockerfile",
"extensions": [
"salesforce.salesforcedx-vscode",
"redhat.vscode-xml",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
],
"settings": {
"salesforcedx-vscode-apex.java.home": "/usr/lib/jvm/java-11-openjdk-amd64"
}
}
and this Dockerfile:
FROM docker.io/salesforce/cli:latest-rc-slim
RUN sf plugins install code-analyzer; \
apt-get update; \
apt-get install -y xdg-utils
And the devcontainer is running on a remote RHEL8 server with podman as the container runtime, with a local Windows 10 workstation via vscode.
The devcontainer will need additional configuration to:
- support mounting the workspace if SELinux is configured
- mounting the user's SSH etc. for git access
- proxying SSH (if required)