Skip to content
Draft
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
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ EXAMPLES
$ sf org list auth
```

_See code: [src/commands/org/list/auth.ts](https://github.com/salesforcecli/plugin-auth/blob/4.2.1/src/commands/org/list/auth.ts)_
_See code: [src/commands/org/list/auth.ts](https://github.com/salesforcecli/plugin-auth/blob/4.2.2-cb.0/src/commands/org/list/auth.ts)_

## `sf org login access-token`

Expand Down Expand Up @@ -161,7 +161,7 @@ FLAG DESCRIPTIONS
To specify a sandbox, set --instance-url to "https://<MyDomainName>--<SandboxName>.sandbox.my.salesforce.com".
```

_See code: [src/commands/org/login/access-token.ts](https://github.com/salesforcecli/plugin-auth/blob/4.2.1/src/commands/org/login/access-token.ts)_
_See code: [src/commands/org/login/access-token.ts](https://github.com/salesforcecli/plugin-auth/blob/4.2.2-cb.0/src/commands/org/login/access-token.ts)_

## `sf org login jwt`

Expand Down Expand Up @@ -252,7 +252,7 @@ FLAG DESCRIPTIONS
To specify a sandbox, set --instance-url to "https://<MyDomainName>--<SandboxName>.sandbox.my.salesforce.com".
```

_See code: [src/commands/org/login/jwt.ts](https://github.com/salesforcecli/plugin-auth/blob/4.2.1/src/commands/org/login/jwt.ts)_
_See code: [src/commands/org/login/jwt.ts](https://github.com/salesforcecli/plugin-auth/blob/4.2.2-cb.0/src/commands/org/login/jwt.ts)_

## `sf org login sfdx-url`

Expand Down Expand Up @@ -322,7 +322,7 @@ EXAMPLES
$ echo url | sf org login sfdx-url --sfdx-url-stdin
```

_See code: [src/commands/org/login/sfdx-url.ts](https://github.com/salesforcecli/plugin-auth/blob/4.2.1/src/commands/org/login/sfdx-url.ts)_
_See code: [src/commands/org/login/sfdx-url.ts](https://github.com/salesforcecli/plugin-auth/blob/4.2.2-cb.0/src/commands/org/login/sfdx-url.ts)_

## `sf org login web`

Expand Down Expand Up @@ -427,7 +427,7 @@ FLAG DESCRIPTIONS
To specify a sandbox, set --instance-url to "https://<MyDomainName>--<SandboxName>.sandbox.my.salesforce.com".
```

_See code: [src/commands/org/login/web.ts](https://github.com/salesforcecli/plugin-auth/blob/4.2.1/src/commands/org/login/web.ts)_
_See code: [src/commands/org/login/web.ts](https://github.com/salesforcecli/plugin-auth/blob/4.2.2-cb.0/src/commands/org/login/web.ts)_

## `sf org logout`

Expand Down Expand Up @@ -493,6 +493,6 @@ FLAG DESCRIPTIONS
All orgs includes Dev Hubs, sandboxes, DE orgs, and expired, deleted, and unknown-status scratch orgs.
```

_See code: [src/commands/org/logout.ts](https://github.com/salesforcecli/plugin-auth/blob/4.2.1/src/commands/org/logout.ts)_
_See code: [src/commands/org/logout.ts](https://github.com/salesforcecli/plugin-auth/blob/4.2.2-cb.0/src/commands/org/logout.ts)_

<!-- commandsstop -->
4 changes: 4 additions & 0 deletions messages/web.login.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,7 @@ Unable to open the browser you specified (%s).
# error.cannotOpenBrowser.actions

- Ensure that %s is installed on your computer. Or specify a different browser using the --browser flag.

# verificationCode

- Your verification code is %s. Enter this in the browser window that just opened. SECURITY NOTE: Enter this PIN only if you initiated this login.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@salesforce/plugin-auth",
"description": "plugin for sf auth commands",
"version": "4.2.1",
"version": "4.2.2-cb.0",
"author": "Salesforce",
"bugs": "https://github.com/forcedotcom/cli/issues",
"enableO11y": true,
Expand Down
17 changes: 17 additions & 0 deletions src/commands/org/login/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,20 @@
* limitations under the License.
*/

import { createHash } from 'node:crypto';
import open, { apps, AppName } from 'open';
import { Flags, SfCommand, loglevel } from '@salesforce/sf-plugins-core';
import { AuthFields, AuthInfo, Logger, Messages, OAuth2Config, SfError, WebOAuthServer } from '@salesforce/core';
import { Env } from '@salesforce/kit';
import common from '../../../common.js';

export const CODE_BUILDER_STATE_ENV_VAR = 'CODE_BUILDER_STATE';

export const getVerificationCode = (codeBuilderState: string): string => {
const hash = createHash('sha256').update(codeBuilderState, 'utf8').digest('hex');
return hash.substring(0, 4);
};

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@salesforce/plugin-auth', 'web.login');
const commonMessages = Messages.loadMessages('@salesforce/plugin-auth', 'messages');
Expand Down Expand Up @@ -112,6 +120,15 @@ export default class LoginWeb extends SfCommand<AuthFields> {
throw new SfError(messages.getMessage('error.headlessWebAuth'));
}

// Display verification code for Code Builder mode if env is set
const env = new Env();
const codeBuilderState = env.getString(CODE_BUILDER_STATE_ENV_VAR);
if (codeBuilderState) {
const verificationCode = getVerificationCode(codeBuilderState);

this.log(messages.getMessage('verificationCode', [verificationCode]));
}

if (await common.shouldExitCommand(flags['no-prompt'])) return {};

// Add ca/eca to already existing auth info.
Expand Down
57 changes: 55 additions & 2 deletions test/commands/org/login/login.web.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,21 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */

import { Config } from '@oclif/core';
import { AuthFields, AuthInfo, SfError } from '@salesforce/core';
import { AuthFields, AuthInfo, SfError, Messages } from '@salesforce/core';
import { MockTestOrgData, TestContext } from '@salesforce/core/testSetup';
import { StubbedType, stubInterface, stubMethod } from '@salesforce/ts-sinon';
import { assert, expect } from 'chai';
import { Env } from '@salesforce/kit';
import { SfCommand, Ux } from '@salesforce/sf-plugins-core';
import LoginWeb, { ExecuteLoginFlowParams } from '../../../../src/commands/org/login/web.js';
import LoginWeb, {
ExecuteLoginFlowParams,
CODE_BUILDER_STATE_ENV_VAR,
getVerificationCode,
} from '../../../../src/commands/org/login/web.js';

describe('org:login:web', () => {
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@salesforce/plugin-auth', 'web.login');
const $$ = new TestContext();
const testData = new MockTestOrgData();
const config = stubInterface<Config>($$.SANDBOX, {
Expand Down Expand Up @@ -302,4 +308,51 @@ describe('org:login:web', () => {
expect(callArgs.clientApp?.username).to.equal('test@example.com');
expect(callArgs.scopes).to.be.undefined;
});

it('should display verification code when CODE_BUILDER_STATE env var is set', async () => {
const codeBuilderState = 'CODE_BUILDER_STATE';
const envStub = $$.SANDBOX.stub(Env.prototype, 'getString');
envStub.withArgs(CODE_BUILDER_STATE_ENV_VAR).returns(codeBuilderState);
envStub.returns(''); // Default for other calls

$$.SANDBOX.stub(Env.prototype, 'getBoolean').returns(false); // Prevent container mode checks

const logStub = stubMethod($$.SANDBOX, SfCommand.prototype, 'log');

const login = await createNewLoginCommand([], false, undefined);
await login.run();

// Verify that log was called with the verification code message
const verificationCode = getVerificationCode(codeBuilderState);
const calls = logStub.getCalls();
const verificationCodeCall = calls.find(
(call) => typeof call.args[0] === 'string' && call.args[0].includes(verificationCode)
);
expect(verificationCodeCall).to.exist;
expect(verificationCode).to.match(/^[0-9a-f]{4}$/);
expect(verificationCodeCall?.args[0]).to.include(messages.getMessage('verificationCode', [verificationCode]));
});

it('should not display verification code when CODE_BUILDER_STATE env var is not set', async () => {
const envStub = stubMethod($$.SANDBOX, Env.prototype, 'getString');
envStub.withArgs('CODE_BUILDER_STATE').returns(undefined);
envStub.returns('');

$$.SANDBOX.stub(Env.prototype, 'getBoolean').returns(false); // Prevent container mode checks

const logStub = $$.SANDBOX.stub(SfCommand.prototype, 'log');
const logSuccessStub = $$.SANDBOX.stub(SfCommand.prototype, 'logSuccess');

const login = await createNewLoginCommand([], false, undefined);
await login.run();

// Verify that log was NOT called for verification code
expect(logStub.callCount).to.equal(0);
const calls = logSuccessStub.getCalls();
const verificationCodeCall = calls.find(
(call) => call.args[0]?.includes('verification code') || call.args[0]?.includes('Enter this')
);
expect(verificationCodeCall).to.not.exist;
expect(logSuccessStub.callCount).to.equal(1);
});
});