Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions command-snapshot.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,28 @@
[
{
"alias": [],
"command": "org:auth:show-access-token",
"flagAliases": [],
"flagChars": ["o", "p"],
"flags": ["flags-dir", "json", "no-prompt", "target-org"],
"plugin": "@salesforce/plugin-org"
},
{
"alias": [],
"command": "org:auth:show-sfdx-auth-url",
"flagAliases": [],
"flagChars": ["o", "p"],
"flags": ["flags-dir", "json", "no-prompt", "target-org"],
"plugin": "@salesforce/plugin-org"
},
{
"alias": [],
"command": "org:auth:show-user-password",
"flagAliases": [],
"flagChars": ["o", "p"],
"flags": ["flags-dir", "json", "no-prompt", "target-org"],
"plugin": "@salesforce/plugin-org"
},
{
"alias": [],
"command": "org:create:agent-user",
Expand Down
41 changes: 41 additions & 0 deletions messages/org.auth.show-access-token.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# summary

Show the current access token for an org.

# description

Because access tokens are sensitive credentials that grant full access to an org, this command prompts for confirmation before revealing the token. Skip confirmation by specifying either the --no-prompt or --json flag.

# flags.no-prompt.summary

Skip the security warning and reveal the access token without confirmation.

# prompt.show-access-token

You're about to reveal the access token for "%s". This token grants full access to the org with your current permissions. Sharing or logging this token is equivalent to sharing your credentials. Do you want to continue?

# warning.show-access-token

This command exposes a sensitive Access Token that allows for subsequent activity using your current authenticated session. Sharing this information is equivalent to logging someone in under the current credential, resulting in unintended access and escalation of privilege. For additional information about org authorization, review https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_auth.htm.

# error.noAccessToken

No access token found for "%s". The org may need to be re-authenticated.

# examples

- Show the access token for the default org:

<%= config.bin %> <%= command.id %>

- Show the access token for an org with alias "my-org":

<%= config.bin %> <%= command.id %> --target-org my-org

- Show the access token without the confirmation prompt:

<%= config.bin %> <%= command.id %> --target-org my-org --no-prompt

- Get the access token as JSON for use in scripts:

<%= config.bin %> <%= command.id %> --target-org my-org --json
41 changes: 41 additions & 0 deletions messages/org.auth.show-sfdx-auth-url.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# summary

Show the SFDX Auth URL for an org.

# description

Shows the SFDX Auth URL for an org. This URL is only available for orgs authenticated via a web-based OAuth flow. This command prompts for confirmation before revealing it. Skip confirmation by specifying either the --no-prompt or --json flag.

# flags.no-prompt.summary

Skip the security warning and reveal the SFDX Auth URL without confirmation.

# prompt.show-sfdx-auth-url

You're about to reveal the SFDX Auth URL for "%s". This URL contains a refresh token that can be used to authenticate to the org without user interaction. Do you want to continue?

# warning.show-sfdx-auth-url

This command exposes an SFDX Auth URL. Unlike an access token, this credential contains a refresh token that allows extended access to an org. Avoid sharing or logging this URL. For additional information about org authorization, review https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_auth_url.htm.

# error.noRefreshToken

An SFDX Auth URL is not available for "%s". This URL is only available for orgs authenticated via a web-based login flow. Re-authenticate to the org using "sf org login web" to make it available.

# examples

- Show the SFDX Auth URL for the default org:

<%= config.bin %> <%= command.id %>

- Show the SFDX Auth URL for an org with alias "my-org":

<%= config.bin %> <%= command.id %> --target-org my-org

- Show the SFDX Auth URL without the confirmation prompt:

<%= config.bin %> <%= command.id %> --target-org my-org --no-prompt

- Get the SFDX Auth URL as JSON for use in scripts:

<%= config.bin %> <%= command.id %> --target-org my-org --json
43 changes: 43 additions & 0 deletions messages/org.auth.show-user-password.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# summary

Show the stored password for an org's user.

# description

This command shows only passwords that were generated locally in your DX project with either the "org generate password" or "org create user" CLI command. If you generated a password for a user in Setup in your org, you can't show it with this command.

Because passwords are sensitive credentials, this command prompts for confirmation before revealing it. Skip confirmation by specifying either the --no-prompt or --json flag.

# flags.no-prompt.summary

Skip the security warning and reveal the password without confirmation.

# prompt.show-user-password

You're about to reveal the password for "%s". Do you want to continue?

# warning.show-user-password

This command exposes a user password. While a password alone isn't sufficient to gain access to an org (additional factors like a security token or an enabled OAuth username-password flow are required), treat it as a sensitive credential and avoid sharing or logging it.

# error.noPassword

No password found for "%s". A password is available only if one was previously generated locally in your DX project by running either "sf org generate password" or "sf org create user". If you generated a password in your org using Setup, it's not available to this command.

# examples

- Show the password for the default org's user:

<%= config.bin %> <%= command.id %>

- Show the password for an org with alias "my-org":

<%= config.bin %> <%= command.id %> --target-org my-org

- Show the password without the confirmation prompt:

<%= config.bin %> <%= command.id %> --target-org my-org --no-prompt

- Get the password as JSON for use in scripts:

<%= config.bin %> <%= command.id %> --target-org my-org --json
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@
},
"disable": {
"description": "Disable source tracking in an org."
},
"auth": {
"description": "Commands for printing sensitive auth info."
}
},
"external": true
Expand Down
16 changes: 16 additions & 0 deletions schemas/org-auth-show__access__token.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/OrgAuthShowAccessTokenResult",
"definitions": {
"OrgAuthShowAccessTokenResult": {
"type": "object",
"properties": {
"accessToken": {
"type": "string"
}
},
"required": ["accessToken"],
"additionalProperties": false
}
}
}
16 changes: 16 additions & 0 deletions schemas/org-auth-show__sfdx__auth__url.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/OrgAuthShowSfdxAuthUrlResult",
"definitions": {
"OrgAuthShowSfdxAuthUrlResult": {
"type": "object",
"properties": {
"sfdxAuthUrl": {
"type": "string"
}
},
"required": ["sfdxAuthUrl"],
"additionalProperties": false
}
}
}
16 changes: 16 additions & 0 deletions schemas/org-auth-show__user__password.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/OrgAuthShowUserPasswordResult",
"definitions": {
"OrgAuthShowUserPasswordResult": {
"type": "object",
"properties": {
"password": {
"type": "string"
}
},
"required": ["password"],
"additionalProperties": false
}
}
}
81 changes: 81 additions & 0 deletions src/commands/org/auth/show-access-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
import { AuthInfo, Messages, SfError } from '@salesforce/core';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@salesforce/plugin-org', 'org.auth.show-access-token');

export type OrgAuthShowAccessTokenResult = {
accessToken: string;
};

export default class OrgAuthShowAccessToken extends SfCommand<OrgAuthShowAccessTokenResult> {
public static readonly summary = messages.getMessage('summary');
public static readonly description = messages.getMessage('description');
public static readonly examples = messages.getMessages('examples');

public static readonly flags = {
'target-org': Flags.requiredOrg(),
'no-prompt': Flags.boolean({
summary: messages.getMessage('flags.no-prompt.summary'),
char: 'p',
}),
};

public async run(): Promise<OrgAuthShowAccessTokenResult> {
const { flags } = await this.parse(OrgAuthShowAccessToken);

const org = flags['target-org'];
const username = org.getUsername();
try {
// The auth file can have a stale access token. Refresh it before getting the fields
await org.refreshAuth();
} catch (error) {
// Even if this fails, we want to display the information we can read from the auth file
this.warn('Unable to refresh auth for org. Access token may be stale.');
}

// Don't ask for confirmation if --json or --no-prompt is passed
if (!this.jsonEnabled() && !flags['no-prompt']) {
const confirmed = await this.confirm({
message: messages.getMessage('prompt.show-access-token', [username]),
ms: 30_000,
});
if (!confirmed) {
throw new SfError('Show access token confirmation denied or timed out.');
}
} else {
// Note: We don't show this warning if the user has already been prompted
this.warn(messages.getMessage('warning.show-access-token'));
}

const authInfo = await AuthInfo.create({ username });
const { accessToken } = authInfo.getFields(true);

if (!accessToken) {
throw messages.createError('error.noAccessToken', [username]);
}

this.table({
overflow: 'wrap',
data: [{ key: 'Access Token', value: accessToken }],
});

return { accessToken };
}
}
74 changes: 74 additions & 0 deletions src/commands/org/auth/show-sfdx-auth-url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
import { AuthInfo, Messages, SfError } from '@salesforce/core';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@salesforce/plugin-org', 'org.auth.show-sfdx-auth-url');

export type OrgAuthShowSfdxAuthUrlResult = {
sfdxAuthUrl: string;
};

export default class OrgAuthShowSfdxAuthUrl extends SfCommand<OrgAuthShowSfdxAuthUrlResult> {
public static readonly summary = messages.getMessage('summary');
public static readonly description = messages.getMessage('description');
public static readonly examples = messages.getMessages('examples');

public static readonly flags = {
'target-org': Flags.requiredOrg(),
'no-prompt': Flags.boolean({
summary: messages.getMessage('flags.no-prompt.summary'),
char: 'p',
}),
};

public async run(): Promise<OrgAuthShowSfdxAuthUrlResult> {
const { flags } = await this.parse(OrgAuthShowSfdxAuthUrl);

const org = flags['target-org'];
const username = org.getUsername();

if (!this.jsonEnabled() && !flags['no-prompt']) {
const confirmed = await this.confirm({
message: messages.getMessage('prompt.show-sfdx-auth-url', [username]),
ms: 30_000,
});
if (!confirmed) {
throw new SfError('Show SFDX auth URL confirmation denied or timed out.');
}
} else {
this.warn(messages.getMessage('warning.show-sfdx-auth-url'));
}

const authInfo = await AuthInfo.create({ username });
const { refreshToken } = authInfo.getFields(true);

if (!refreshToken) {
throw messages.createError('error.noRefreshToken', [username]);
}

const sfdxAuthUrl = authInfo.getSfdxAuthUrl();

this.table({
overflow: 'wrap',
data: [{ key: 'SFDX Auth URL', value: sfdxAuthUrl }],
});

return { sfdxAuthUrl };
}
}
Loading
Loading