forcedotcom / cli

Salesforce CLI
https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/
BSD 3-Clause "New" or "Revised" License
491 stars 79 forks source link

Invalid SFDX auth URL when running org:login:sfdx-url #2629

Closed gsbasso closed 7 months ago

gsbasso commented 9 months ago

Summary

The auth URL I am using does not appear to match the format specified in the error message (see below). Specifically, the URL has the following form:

force://PlatformCLI::<blah>@<instanceUrl>

I don't know if the content in <blah> is actually the refreshToken, but there appears to be no value for clientSecret.

Steps To Reproduce

  1. Follow the prescribed steps to obtain the SFDX auth url for an existing, authorized target org.
  2. Run sfdx org:login:sfdx-url --alias myAlias --sfdx-url-file <path>\authFile.txt
  3. Command fails.

Expected result

Command succeeds and specified alias is authorized

Actual result

Command fails with the following error:

Error (1): Invalid SFDX auth URL. Must be in the format "force://<clientId>:<clientSecret>:<refreshToken>@<instanceUrl>".  Note that the SFDX auth URL uses the "force" protocol, and not "http" or "https".  Also note that the "instanceUrl" inside the SFDX  auth URL doesn't include the protocol ("https://"

System Information

{
  "architecture": "win32-x64",
  "cliVersion": "@salesforce/cli/2.21.8",
  "nodeVersion": "node-v20.10.0",
  "osVersion": "Windows_NT 10.0.17763",
  "rootPath": "C:\\Users\\xxxxxxxx\\AppData\\Local\\sf\\client\\2.21.8-474381d",
  "shell": "cmd.exe",
  "pluginVersions": [
    "@oclif/plugin-autocomplete 3.0.2 (core)",
    "@oclif/plugin-commands 3.0.7 (core)",
    "@oclif/plugin-help 6.0.7 (core)",
    "@oclif/plugin-not-found 3.0.4 (core)",
    "@oclif/plugin-plugins 4.1.9 (core)",
    "@oclif/plugin-search 1.0.8 (core)",
    "@oclif/plugin-update 4.1.4 (core)",
    "@oclif/plugin-version 2.0.8 (core)",
    "@oclif/plugin-warn-if-update-available 3.0.5 (core)",
    "@oclif/plugin-which 3.0.11 (core)",
    "@salesforce/cli 2.21.8 (core)",
    "apex 3.0.8 (core)",
    "auth 3.0.10 (core)",
    "community 3.0.7 (link) D:\\Program Files\\sf\\client\\node_modules\\@salesforce\\plugin-community",
    "data 3.0.5 (core)",
    "deploy-retrieve 2.2.3 (core)",
    "info 3.0.7 (core)",
    "limits 3.0.5 (core)",
    "marketplace 1.0.10 (core)",
    "org 3.1.1 (core)",
    "packaging 2.0.1 (link) D:\\Program Files\\sf\\client\\node_modules\\@salesforce\\plugin-packaging",
    "schema 3.0.8 (core)",
    "settings 2.0.9 (core)",
    "sobject 1.0.5 (core)",
    "source 3.0.3 (core)",
    "telemetry 3.1.4 (core)",
    "templates 56.0.4 (core)",
    "trust 3.1.2 (core)",
    "user 3.1.0 (core)"
  ]
}

Additional information

I also tried the older force:auth:sfdxurl:store command but the result was the same.

github-actions[bot] commented 9 months ago

Thank you for filing this issue. We appreciate your feedback and will review the issue as soon as possible. Remember, however, that GitHub isn't a mechanism for receiving support under any agreement or SLA. If you require immediate assistance, contact Salesforce Customer Support.

gsbasso commented 9 months ago

The issue is with the regular expression used to parse the URL in authInfo.js. More specifically, removing the enclosing/outer / in the expression fixes the problem.

Also, make sure the file you use is not Unicode.

cristiand391 commented 9 months ago

We use a regex to validate the auth URL format is correct: https://github.com/forcedotcom/sfdx-core/blob/73d52124ecf94774cde8e1300a00975420d1d817/src/org/authInfo.ts#L364-L373

the clientSecret is optional so that should be fine, I wonder if the refresh token and/org instance url has a character not allowed by the regex...

Since you can't share the URL you might need to manually check this, if you have node you can use this code to verify it:

const sfdxAuthUrl = '<auth-url>'

console.log(sfdxAuthUrl.match(/^force:\/\/([a-zA-Z0-9._-]+={0,2}):([a-zA-Z0-9._-]*={0,2}):([a-zA-Z0-9._-]+={0,2})@([a-zA-Z0-9._-]+)/)?.index)

if there's a match it should print 0, or undefined not.

EDIT: nvm, didn't see your second comment. hang on...

cristiand391 commented 9 months ago

The issue is with the regular expression used to parse the URL in authInfo.js. More specifically, removing the enclosing/outer / in the expression fixes the problem.

Can you share the modified regex that worked for you? Your suggestion shouldn't as the last / is part of the regex literal.

-/^force:\/\/([a-zA-Z0-9._-]+={0,2}):([a-zA-Z0-9._-]*={0,2}):([a-zA-Z0-9._-]+={0,2})@([a-zA-Z0-9._-]+)/
+/^force:\/\/([a-zA-Z0-9._-]+={0,2}):([a-zA-Z0-9._-]*={0,2}):([a-zA-Z0-9._-]+={0,2})@([a-zA-Z0-9._-]+)
gsbasso commented 9 months ago

The issue is with the regular expression used to parse the URL in authInfo.js. More specifically, removing the enclosing/outer / in the expression fixes the problem.

Can you share the modified regex that worked for you? Your suggestion shouldn't as the last / is part of the regex literal.

-/^force:\/\/([a-zA-Z0-9._-]+={0,2}):([a-zA-Z0-9._-]*={0,2}):([a-zA-Z0-9._-]+={0,2})@([a-zA-Z0-9._-]+)/
+/^force:\/\/([a-zA-Z0-9._-]+={0,2}):([a-zA-Z0-9._-]*={0,2}):([a-zA-Z0-9._-]+={0,2})@([a-zA-Z0-9._-]+)

Hi @cristiand391 - Remove the first / character as well (you'll also need to enclose the entire expression in quotes).

shetzel commented 9 months ago

@gsbasso - I'm not opposed to changing this but without a way to reproduce it we can't add a unit test to know what it's fixing. Please provide either an authFile.txt that reproduces it or the contents of that file. It doesn't have to contain the exact tokens or instance url; remove or replace any characters you want. We just need it to fail with the current code and succeed with the updated code.

gsbasso commented 9 months ago

@gsbasso - I'm not opposed to changing this but without a way to reproduce it we can't add a unit test to know what it's fixing. Please provide either an authFile.txt that reproduces it or the contents of that file. It doesn't have to contain the exact tokens or instance url; remove or replace any characters you want. We just need it to fail with the current code and succeed with the updated code.

The URL force://PlatformCLI::123456@test.salesforce.com returns a value of false with the following regex:

        const match = sfdxAuthUrl.match(/^force:\/\/([a-zA-Z0-9._-]+={0,2}):([a-zA-Z0-9._-]*={0,2}):([a-zA-Z0-9._-]+={0,2})@([a-zA-Z0-9._-]+)/);

but returns true with the following revised regex:

        const match = sfdxAuthUrl.match('^force:\/\/([a-zA-Z0-9._-]+={0,2}):([a-zA-Z0-9._-]*={0,2}):([a-zA-Z0-9._-]+={0,2})@([a-zA-Z0-9._-]+)');
mshanemc commented 8 months ago

In a browser console (to use basic js)

Screenshot 2024-01-16 at 10 19 25 AM

.match doesn't return boolean. We must have some difference in how we're running match/regex

shetzel commented 8 months ago

fwiw, I used Node.js v20.11.0 with both str.match(...) variants and it returned the same array output.

gsbasso commented 8 months ago

In a browser console (to use basic js)

Screenshot 2024-01-16 at 10 19 25 AM

.match doesn't return boolean. We must have some difference in how we're running match/regex

@mshanemc I assumed match returned a Boolean value based on the the line that follows, which is if (!match). But of course you are right, the return value is not a Boolean. I should have just wrote matches/does not match instead.

Also, the second expression is not as I had specified. You need to remove the first and last / characters, just inside the quotes.

That said, I found that both returned a result (i.e. matched) when run in the Chrome console on Windows 10. But of course, this does not run in a browser.

I actually tried the original expression in Apex and it did not match, while my revised version did.

I see that @shetzel tested both expressions in version 20.11.0 of Node.js and found both worked. The version of Node.js on which I observed the issue was 20.10.0 so that is a difference. Maybe it's related to the OS/environment?

Anyways, all I know is I had to change the expression to get the sf command to work.

shetzel commented 8 months ago

@gsbasso - Is the sfdx url within your authFile.txt surrounded with quotes? If so, that could be the problem. I see this error when I surround the url with quotes in the file. However, it fails for both regex versions.

gsbasso commented 8 months ago

@gsbasso - Is the sfdx url within your authFile.txt surrounded with quotes? If so, that could be the problem. I see this error when I surround the url with quotes in the file. However, it fails for both regex versions.

No quotes.

AllanOricil commented 8 months ago

@gsbasso - Is the sfdx url within your authFile.txt surrounded with quotes? If so, that could be the problem. I see this error when I surround the url with quotes in the file. However, it fails for both regex versions.

No quotes.

Learn how to debug a node package. I share some steps that could help you. Add some good breakpoints in the auth package, start the debugger, debug and later post your results here.

steps:

  1. find where the cli package is installed. It is not in the same place as the binary, usually. Not sure how windows installations work.
  2. Open its node_modules folder, then search for the auth plugin. It is a dependency of the cli package.
  3. Now add some breakpoints where you can determine the root of the problem
  4. Run node --inspect-break PATH_TO_CLI_BINARY org:login:sfdx-url --alias myAlias --sfdx-url-file <path>\authFile.txt in the root of the sfdx project you are using. Do it on the same project where you are having the problem.
  5. Open vscode in the root of the cli package you got in step 1.
  6. Open vscode's "Command Pallete" (ctrl+shift+p) and type "Attach debugger" (or something like that). Once you find the right option, click on it. A list with some items will appear, select the first option.
  7. The debugger will start and stop in the first line of the entry point of the code that runs when you typed it on your terminal. Press the play button, and let the command continue its execution. Eventually, it will stop in one of the breakpoints you added in step 3.
  8. Investigate it, and come back with the results. Prefably print screens showing important variable values. Learn how to use debugger`s Watch feature.

Steps 6, 7 e 8 can be done using chrome instead of vscode, if you prefer.

optional step 9: throw away your computer just kidding

String.prototype.match spec also works with strings. It automatically converts the given escaped string into new RegExp.

mshanemc commented 8 months ago

That said, I found that both returned a result (i.e. matched) when run in the Chrome console on Windows 10. But of course, this does not run in a browser.

seems valid without a browser, too. I think the "apex regex didn't like it" isn't related.

Got any other clues?

➜  repros node      
Welcome to Node.js v20.9.0.
Type ".help" for more information.
> const str = 'force://PlatformCLI::123456@test.salesforce.com'
undefined
> str.match(/^force:\/\/([a-zA-Z0-9._-]+={0,2}):([a-zA-Z0-9._-]*={0,2}):([a-zA-Z0-9._-]+={0,2})@([a-zA-Z0-9._-]+)/)
[
  'force://PlatformCLI::123456@test.salesforce.com',
  'PlatformCLI',
  '',
  '123456',
  'test.salesforce.com',
  index: 0,
  input: 'force://PlatformCLI::123456@test.salesforce.com',
  groups: undefined
]
> 
AllanOricil commented 8 months ago

Considering the regex states that the giving string must start with the word force (because of the ^), If his "match" is returning null, I'm "almost certain" his auth url isn't starting with the word force. There has to have a hidden character before the word force. You can do a simple experiment to verify this is true, and then you can ask @gsbasso to show evidence with a picture/video showing the string passed to the match, as well as the expression he used.

mshanemc commented 8 months ago

@gsbasso we just got another one (see link right above this one). There's a suggested workaround there (setting the property in a json file instead of plain text) that I'd be interested in seeing if it helps.

I think this might be related to whitespace in the file perhaps. If so, we could try trimming it to get rid of whitespace, or adjusting the regex to handle whitespace better

AllanOricil commented 8 months ago
gsbasso commented 8 months ago

After restoring the original expression in authInfo.js I find I can no longer reproduce the issue. Nothing has changed in terms of the CLI but there have been updates to the (Windows 2019) server (I don't know the specific updates). It's also possible there was some additional characters in the original URL I attempted to import as some have suggested, though I'm skeptical (plus it was the same URL that ultimately succeeded after I revised the expression).

Also, I realize the behaviour in Apex is not relevant but I only mentioned it earlier because it reinforced my original theory that the expression was flawed. More specifically, the code snippet below will pass if run in the developer console. The first pattern does not produce a match while the second does.

String sfdxAuthUrl = 'force://PlatformCLI::123456@reds--obaqa.sandbox.my.salesforce.com'; 
Pattern p = Pattern.compile('/^force:\\/\\/([a-zA-Z0-9._-]+={0,2}):([a-zA-Z0-9._-]*={0,2}):([a-zA-Z0-9._-]+={0,2})@([a-zA-Z0-9._-]+)/');
Matcher m = p.matcher(sfdxAuthUrl);
System.assert(!m.matches());
p = Pattern.compile('^force:\\/\\/([a-zA-Z0-9._-]+={0,2}):([a-zA-Z0-9._-]*={0,2}):([a-zA-Z0-9._-]+={0,2})@([a-zA-Z0-9._-]+)');
m = p.matcher(sfdxAuthUrl);
System.assert(m.matches());

In any case I would suggest marking this as closed for now unless someone else encounters a similar issue.

shetzel commented 7 months ago

Closing per above comment. Feel free to reopen should more details be discovered.

tggagne commented 1 month ago

I'm getting this error now in the SF-supplied docker image. When I try the node suggestion above it returns 0 (success), but I get errors with sf org login sfdx-url --sfdx-url-file <filename>.

root@4421097c5aa1:/# sf version --verbose CLI Version: @salesforce/cli/2.57.7 published 7 days ago (Wed Aug 28 2024)

Architecture: linux-x64

Node Version: node-v20.16.0

Plugin Version: @oclif/plugin-autocomplete 3.2.2 (core) @oclif/plugin-commands 4.0.13 (core) @oclif/plugin-help 6.2.10 (core) @oclif/plugin-not-found 3.2.18 (core) @oclif/plugin-plugins 5.4.6 (core) @oclif/plugin-search 1.2.7 (core) @oclif/plugin-update 4.5.5 (core) @oclif/plugin-version 2.2.11 (core) @oclif/plugin-warn-if-update-available 3.1.13 (core) @oclif/plugin-which 3.2.12 (core) @salesforce/cli 2.57.7 (core) apex 3.4.5 (core) api 1.2.1 (core) auth 3.6.51 (core) data 3.6.3 (core) deploy-retrieve 3.12.0 (core) info 3.4.2 (core) limits 3.3.27 (core) marketplace 1.2.24 (core) org 4.5.4 (core) packaging 2.8.0 (core) schema 3.3.26 (core) settings 2.3.15 (core) sobject 1.4.32 (core) source 3.5.16 (core) telemetry 3.6.10 (core) templates 56.3.14 (core) trust 3.7.25 (core) user 3.5.26 (core) sfdx-git-delta 5.43.0 (user) published 0 days ago (Wed Sep 04 2024)

OS and Version: Linux 6.6.16-linuxkit

Shell: bash

Root Path: /usr/local/lib/nodejs/lib/node_modules/@salesforce/cli