Skip to content

Commit 44b67f0

Browse files
committed
feat: embed default public client ID for zero-config platform commands
Sandbox, Account Manager, and SLAS commands now work without requiring a pre-configured client ID. The CLI falls back to a built-in public client for implicit OAuth flows (browser-based login) when no client ID is configured.
1 parent a7face3 commit 44b67f0

File tree

14 files changed

+187
-51
lines changed

14 files changed

+187
-51
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@salesforce/b2c-cli': minor
3+
'@salesforce/b2c-tooling-sdk': minor
4+
---
5+
6+
Embed a default public client ID for implicit OAuth flows. Account Manager, Sandbox, and SLAS commands now work without requiring a pre-configured client ID — the CLI will automatically use a built-in public client for browser-based authentication.

docs/cli/account-manager.md

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,27 @@ These flags are available on all Account Manager commands:
1616

1717
## Authentication
1818

19-
Account Manager commands require an API client or can be executed through an implicit workflow that seamlessly handles user authentication and associated flows.
19+
Account Manager commands work out of the box using the CLI's built-in public client, which authenticates via browser login (implicit flow). No API client configuration is required for interactive use.
2020

21-
### Required Configuration
22-
23-
| Flag | Environment Variable | Description |
24-
|------|---------------------|-------------|
25-
| `--client-id` | `SFCC_CLIENT_ID` | OAuth client ID for Account Manager |
26-
| `--client-secret` | `SFCC_CLIENT_SECRET` | OAuth client secret for Account Manager |
21+
For automation or CI/CD, you can provide your own API client credentials.
2722

2823
### Required Roles
2924

3025
| Auth Method | Role | Configured On |
3126
|-------------|------|---------------|
27+
| Built-in client (default) | Uses your user account's roles | Your user account |
3228
| Client Credentials | `User Administrator` or higher | The API client |
3329

34-
User authentication is handled via the implicit flow, utilizing the access rights granted to the user.
35-
3630
### Configuration
3731

3832
```bash
39-
# Set Account Manager host
40-
export SFCC_ACCOUNT_MANAGER_HOST=account.demandware.com
33+
# No configuration needed — opens browser for login
34+
b2c am users list
4135

42-
# Set OAuth credentials
36+
# Client Credentials (for automation)
4337
export SFCC_CLIENT_ID=my-client-id
4438
export SFCC_CLIENT_SECRET=my-client-secret
39+
b2c am users list
4540
```
4641

4742
---

docs/cli/sandbox.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,30 +37,30 @@ These flags are available on all sandbox commands:
3737

3838
## Authentication
3939

40-
Sandbox commands require an Account Manager API Client.
40+
Sandbox commands work out of the box using the CLI's built-in public client, which authenticates via browser login (implicit flow). No API client configuration is required for interactive use.
41+
42+
For automation or CI/CD, you can provide your own API client credentials.
4143

4244
### Required Roles
4345

4446
| Auth Method | Role | Configured On |
4547
|-------------|------|---------------|
48+
| Built-in client (default) | `Sandbox API User` | Your user account |
4649
| User Authentication | `Sandbox API User` | Your user account |
4750
| Client Credentials | `Sandbox API User` | The API client |
4851

49-
**User Authentication**: Used when only `--client-id` is provided. Opens a browser for login. The `Sandbox API User` role must be assigned to your user account in Account Manager.
50-
51-
**Client Credentials**: Used when both `--client-id` and `--client-secret` are provided. The `Sandbox API User` role must be assigned to the API client.
52-
53-
### Tenant Filter
54-
55-
The API client's roles must have a tenant filter configured for the realm(s) you wish to manage. In Account Manager, under each role (e.g., `Sandbox API User`), add the realm IDs you need to access to the **Tenant Filter**.
52+
The `Sandbox API User` role must have a **tenant filter** configured for the realm(s) you wish to manage.
5653

5754
### Configuration
5855

5956
```bash
60-
# User Authentication (opens browser)
57+
# No configuration needed — opens browser for login
58+
b2c sandbox list
59+
60+
# Or provide your own client ID
6161
b2c sandbox list --client-id xxx
6262

63-
# Client Credentials
63+
# Client Credentials (for automation)
6464
export SFCC_CLIENT_ID=my-client
6565
export SFCC_CLIENT_SECRET=my-secret
6666
b2c sandbox list

docs/cli/slas.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,30 @@ These flags are available on all SLAS commands:
1616

1717
## Authentication
1818

19-
SLAS commands require an Account Manager API Client.
19+
SLAS commands work out of the box using the CLI's built-in public client, which authenticates via browser login (implicit flow). No API client configuration is required for interactive use.
20+
21+
For automation or CI/CD, you can provide your own API client credentials.
2022

2123
### Required Roles
2224

2325
| Auth Method | Role | Configured On |
2426
|-------------|------|---------------|
27+
| Built-in client (default) | `SLAS Organization Administrator` | Your user account |
2528
| User Authentication | `SLAS Organization Administrator` | Your user account |
2629
| Client Credentials | `Sandbox API User` | The API client |
2730

28-
**User Authentication**: Used when only `--client-id` is provided. Opens a browser for login. Roles must be assigned to your user account in Account Manager.
29-
30-
**Client Credentials**: Used when both `--client-id` and `--client-secret` are provided. Roles must be assigned to the API client.
31-
32-
### Tenant Filter
33-
34-
The API client's roles must have a tenant filter configured for the organization you wish to manage. In Account Manager, under each role (e.g., `Sandbox API User`, `SLAS Organization Administrator`), add the organization IDs you need to access to the **Tenant Filter**.
31+
The role must have a **tenant filter** configured for the organization you wish to manage.
3532

3633
### Configuration
3734

3835
```bash
39-
# User Authentication (opens browser)
36+
# No configuration needed — opens browser for login
37+
b2c slas client list --tenant-id abcd_123
38+
39+
# Or provide your own client ID
4040
b2c slas client list --tenant-id abcd_123 --client-id xxx
4141

42-
# Client Credentials
42+
# Client Credentials (for automation)
4343
export SFCC_CLIENT_ID=my-client
4444
export SFCC_CLIENT_SECRET=my-secret
4545
b2c slas client list --tenant-id abcd_123

docs/guide/authentication.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,15 @@ The CLI uses different authentication mechanisms depending on the operation:
1616
| [Code](/cli/code) list, activate, delete | OAuth + OCAPI | [API Client](#account-manager-api-client) + [OCAPI](#ocapi-configuration) |
1717
| [Jobs](/cli/jobs), [Sites](/cli/sites) | OAuth + OCAPI | [API Client](#account-manager-api-client) + [OCAPI](#ocapi-configuration) |
1818
| SCAPI commands ([schemas](/cli/scapi-schemas), [custom-apis](/cli/custom-apis), [eCDN](/cli/ecdn)) | OAuth + SCAPI scopes | [API Client](#account-manager-api-client) + [SCAPI Scopes](#scapi-authentication) |
19-
| [SLAS](/cli/slas) client management | OAuth | [API Client](#account-manager-api-client) with appropriate roles |
20-
| [Sandbox](/cli/sandbox) management | OAuth | [API Client](#account-manager-api-client) with `Sandbox API User` role |
19+
| [SLAS](/cli/slas) client management | OAuth | None (uses built-in client) or [API Client](#account-manager-api-client) |
20+
| [Sandbox](/cli/sandbox) management | OAuth | None (uses built-in client) or [API Client](#account-manager-api-client) |
21+
| [Account Manager](/cli/account-manager) | OAuth | None (uses built-in client) or [API Client](#account-manager-api-client) |
2122
| [MRT](/cli/mrt) commands | MRT API Key | [MRT API Key](#managed-runtime-api-key) |
2223

24+
::: tip Zero-Config for Platform Commands
25+
Sandbox, SLAS, and Account Manager commands work out of the box without any client configuration. The CLI includes a built-in public client that authenticates via browser login (implicit flow). You only need to configure an API client if you want to use client credentials for automation/CI or need specific scopes.
26+
:::
27+
2328
::: tip
2429
Each CLI command page documents its specific authentication requirements. See the [CLI Reference](/cli/) for details.
2530
:::

docs/guide/configuration.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,10 @@ When using the `--cloud-origin` flag to specify a different MRT endpoint, the CL
300300

301301
By default, the CLI automatically detects available credentials and tries authentication methods in this order: `client-credentials`, then `implicit`. You can override this behavior to control which methods are used.
302302

303+
::: tip Default Public Client
304+
For platform-level commands (Sandbox, SLAS, and Account Manager), the CLI includes a built-in public client ID. If no `--client-id` is configured, these commands automatically use the built-in client with the implicit flow, opening a browser for authentication. This means you can use these commands with zero configuration.
305+
:::
306+
303307
### Available Auth Methods
304308

305309
- `client-credentials` - OAuth 2.0 client credentials flow (requires client ID and secret). Used for SCAPI/OCAPI and WebDAV.

packages/b2c-cli/src/utils/slas/client.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import {Command, ux} from '@oclif/core';
77
import cliui from 'cliui';
88
import {OAuthCommand} from '@salesforce/b2c-tooling-sdk/cli';
9-
import {createSlasClient, getApiErrorMessage, type SlasClient, type SlasComponents} from '@salesforce/b2c-tooling-sdk';
9+
import {createSlasClient, getApiErrorMessage, DEFAULT_PUBLIC_CLIENT_ID, type SlasClient, type SlasComponents} from '@salesforce/b2c-tooling-sdk';
1010
import {t} from '../../i18n/index.js';
1111

1212
export type Client = SlasComponents['schemas']['Client'];
@@ -100,6 +100,10 @@ export function formatApiError(error: unknown, response: Response): string {
100100
* Provides common flags and helper methods.
101101
*/
102102
export abstract class SlasClientCommand<T extends typeof Command> extends OAuthCommand<T> {
103+
protected override getDefaultClientId(): string {
104+
return DEFAULT_PUBLIC_CLIENT_ID;
105+
}
106+
103107
/**
104108
* Ensure tenant exists, creating it if necessary.
105109
* This is required before creating SLAS clients.

packages/b2c-tooling-sdk/src/cli/am-command.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {OAuthCommand} from './oauth-command.js';
88
import {createAccountManagerClient} from '../clients/am-api.js';
99
import type {AccountManagerClient} from '../clients/am-api.js';
1010
import type {AuthMethod} from './config.js';
11+
import {DEFAULT_PUBLIC_CLIENT_ID} from '../defaults.js';
1112

1213
/**
1314
* Base command for Account Manager operations.
@@ -32,6 +33,10 @@ import type {AuthMethod} from './config.js';
3233
* }
3334
*/
3435
export abstract class AmCommand<T extends typeof Command> extends OAuthCommand<T> {
36+
protected override getDefaultClientId(): string {
37+
return DEFAULT_PUBLIC_CLIENT_ID;
38+
}
39+
3540
/**
3641
* Override default auth methods to prioritize implicit flow for Account Manager.
3742
* Gets the default methods from parent class, then ensures 'implicit' is first.

packages/b2c-tooling-sdk/src/cli/oauth-command.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,19 +102,32 @@ export abstract class OAuthCommand<T extends typeof Command> extends BaseCommand
102102
return DEFAULT_OAUTH_AUTH_METHODS;
103103
}
104104

105+
/**
106+
* Returns a default client ID for implicit OAuth flows when no client ID is configured.
107+
* Returns undefined by default. Subclasses (AmCommand, OdsCommand, etc.) override this
108+
* to return DEFAULT_PUBLIC_CLIENT_ID for platform-level commands that support public client tokens.
109+
*/
110+
protected getDefaultClientId(): string | undefined {
111+
return undefined;
112+
}
113+
105114
/**
106115
* Gets an OAuth auth strategy based on allowed auth methods and available credentials.
107116
*
108117
* Iterates through allowed methods (in priority order) and returns the first
109118
* strategy for which the required credentials are available.
110119
*
120+
* For the implicit flow, falls back to getDefaultClientId() when no client ID
121+
* is explicitly configured.
122+
*
111123
* @throws Error if no allowed method has the required credentials configured
112124
*/
113125
protected getOAuthStrategy(): OAuthStrategy | ImplicitOAuthStrategy {
114126
const config = this.resolvedConfig.values;
115127
const accountManagerHost = this.accountManagerHost;
116128
// Use getDefaultAuthMethods() to get default array, allowing subclasses to override
117129
const allowedMethods = config.authMethods || this.getDefaultAuthMethods();
130+
const defaultClientId = this.getDefaultClientId();
118131

119132
for (const method of allowedMethods) {
120133
switch (method) {
@@ -129,15 +142,20 @@ export abstract class OAuthCommand<T extends typeof Command> extends BaseCommand
129142
}
130143
break;
131144

132-
case 'implicit':
133-
if (config.clientId) {
145+
case 'implicit': {
146+
const effectiveClientId = config.clientId ?? defaultClientId;
147+
if (effectiveClientId) {
148+
if (!config.clientId && defaultClientId) {
149+
this.logger.debug('Using default B2C CLI public client for authentication');
150+
}
134151
return new ImplicitOAuthStrategy({
135-
clientId: config.clientId,
152+
clientId: effectiveClientId,
136153
scopes: config.scopes,
137154
accountManagerHost,
138155
});
139156
}
140157
break;
158+
}
141159

142160
// 'basic' and 'api-key' are not applicable for OAuth strategies
143161
// They would be handled by different command bases (e.g., InstanceCommand, MRTCommand)
@@ -157,10 +175,11 @@ export abstract class OAuthCommand<T extends typeof Command> extends BaseCommand
157175

158176
/**
159177
* Check if OAuth credentials are available.
160-
* Returns true if clientId is configured (with or without clientSecret).
178+
* Returns true if clientId is configured (with or without clientSecret),
179+
* or if a default client ID is available for implicit flows.
161180
*/
162181
protected hasOAuthCredentials(): boolean {
163-
return this.resolvedConfig.hasOAuthConfig();
182+
return this.resolvedConfig.hasOAuthConfig() || this.getDefaultClientId() !== undefined;
164183
}
165184

166185
/**

packages/b2c-tooling-sdk/src/cli/ods-command.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {OAuthCommand} from './oauth-command.js';
88
import {loadConfig, extractOdsFlags} from './config.js';
99
import type {ResolvedB2CConfig} from '../config/index.js';
1010
import {createOdsClient, type OdsClient} from '../clients/ods.js';
11-
import {DEFAULT_ODS_HOST} from '../defaults.js';
11+
import {DEFAULT_ODS_HOST, DEFAULT_PUBLIC_CLIENT_ID} from '../defaults.js';
1212
import {isUuid, parseFriendlySandboxId, SandboxNotFoundError} from '../operations/ods/sandbox-lookup.js';
1313

1414
/**
@@ -33,6 +33,10 @@ import {isUuid, parseFriendlySandboxId, SandboxNotFoundError} from '../operation
3333
* }
3434
*/
3535
export abstract class OdsCommand<T extends typeof Command> extends OAuthCommand<T> {
36+
protected override getDefaultClientId(): string {
37+
return DEFAULT_PUBLIC_CLIENT_ID;
38+
}
39+
3640
static baseFlags = {
3741
...OAuthCommand.baseFlags,
3842
'sandbox-api-host': Flags.string({

0 commit comments

Comments
 (0)