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
160 changes: 157 additions & 3 deletions docs/guide/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,22 @@ Most CLI operations require an Account Manager API Client. This is configured in

### Authentication Methods

The CLI supports four authentication methods:
The CLI supports five authentication methods:

| Method | When Used | Role Configuration |
| ---------------------------------- | ---------------------------------------------------------------------------------------------- | ----------------------------------------- |
| **User Authentication** | When `--user-auth` is passed, or when only a client ID is provided (no secret) | Roles configured on your **user account** |
| **Client Credentials** | When both `--client-id` and `--client-secret` are provided | Roles configured on the **API client** |
| **JWT Bearer** | When `--jwt-cert` and `--jwt-key` are provided (certificate-based authentication) | Roles configured on the **API client** |
| **Stateful User Authentication** | After running `b2c auth login` — browser-based login, token stored and reused | Roles configured on your **user account** |
| **Stateful Client Authentication** | After running `b2c auth client` — client credentials login, token stored and reused | Roles configured on the **API client** |

**User Authentication** opens a browser for interactive login and uses roles assigned to your user account. This is ideal for development and manual operations. Use `--user-auth` as a shorthand for `--auth-methods implicit` on any OAuth command.

**Client Credentials** uses the API client's secret for non-interactive authentication. This is ideal for CI/CD pipelines and automation.

**JWT Bearer** uses a public/private certificate pair for secure authentication without storing client secrets. This is ideal for production environments and CI/CD where you want stronger security. See [JWT Authentication](#jwt-authentication-certificate-based) for details.

**Stateful User Auth** uses `b2c auth login` to open a browser for interactive login once, then stores the session on disk. Subsequent commands automatically use the stored token when it is present and valid, without re-opening the browser. Clear the session with `b2c auth logout`. See [Auth Commands](/cli/auth#b2c-auth-login) for details.

**Stateful Client Auth** uses `b2c auth client` to authenticate once with client credentials (or user/password), store the session, and reuse it across subsequent commands without passing credentials each time. Mirrors the [sfcc-ci](https://github.com/SalesforceCommerceCloud/sfcc-ci) `client:auth` workflow. Use `--renew` to enable automatic token renewal via `b2c auth client renew`. See [Auth Commands](/cli/auth#b2c-auth-client) for details.
Expand All @@ -75,9 +78,14 @@ For Account Manager operations that require user-level roles (organization and A
- **Password**: A strong client secret (save this securely for Client Credentials auth)
5. Configure the **Token Endpoint Auth Method**:
- `client_secret_basic` for client credentials flow
- `private_key_jwt` for JWT Bearer authentication (certificate-based)

::: tip Certificate-Based Authentication
For enhanced security, use JWT Bearer authentication instead of client secrets. This requires uploading a certificate to the API client and using the `--jwt-cert` and `--jwt-key` flags. See [JWT Authentication](#jwt-authentication-certificate-based) for setup instructions.
:::

::: warning
The B2C CLI only supports `client_secret_basic` for the Token Endpoint Auth Method. `client_secret_post` and `private_key_jwt` aren't currently supported.
For client credentials with secrets, only `client_secret_basic` is supported. `client_secret_post` isn't currently supported.
:::

### Assigning Roles
Expand Down Expand Up @@ -150,12 +158,158 @@ For **User Authentication** (implicit flow), configure redirect URLs in your API
| `http://localhost:8080` | Required for B2C CLI user authentication |
| `https://admin.dx.commercecloud.salesforce.com/oauth2-redirect.html` | Optional - enables ODS Swagger interface with same client |

**Note:** Redirect URLs are not required for API clients using only Client Credentials authentication.
**Note:** Redirect URLs are not required for API clients using only Client Credentials or JWT Bearer authentication.

::: tip Running Behind a Proxy
If you're running the CLI behind a proxy where `localhost:8080` isn't reachable by the browser, set `SFCC_REDIRECT_URI` to the proxy URL (e.g., `https://proxy.example.com:8080`). The proxy should forward traffic to the CLI's local server. You can also change the local server port with `SFCC_OAUTH_LOCAL_PORT`. Make sure to add your proxy URL to the API client's redirect URLs in Account Manager.
:::

## JWT Authentication (Certificate-Based)

JWT Bearer authentication (RFC 7523) provides a more secure alternative to client secrets by using public/private certificate pairs. This is ideal for production environments and CI/CD pipelines where you want to avoid storing sensitive secrets.

### How It Works

1. You generate a certificate pair (public certificate + private key)
2. You register the **public certificate** in Account Manager
3. The CLI uses the **private key** to sign JWT tokens for authentication
4. Account Manager verifies the signature using your registered certificate

### Benefits

- **More secure**: Private key never leaves your machine
- **No secrets to leak**: No client secret to store or compromise
- **Better for CI/CD**: Certificates can be rotated without updating secrets across pipelines
- **Industry standard**: Implements OAuth 2.0 JWT Bearer (RFC 7523)

### Setup Instructions

#### Step 1: Generate Certificate Pair

Generate an RSA certificate pair using OpenSSL:

```bash
openssl req -x509 -newkey rsa:4096 \
-keyout key.pem \
-out cert.pem \
-days 365 \
-nodes \
-subj "/CN=B2C CLI"
```

This creates two files:
- `cert.pem` - Public certificate (upload to Account Manager)
- `key.pem` - Private key (keep secure on your machine)

::: tip Encrypted Keys
For additional security, generate an encrypted private key by omitting `-nodes` and adding a passphrase when prompted. You'll provide the passphrase via `--jwt-passphrase` when using the CLI.
:::

#### Step 2: Register Certificate in Account Manager

1. Log in to [Account Manager](https://account.demandware.com)
2. Navigate to **API Client** and select your client
3. Set **Token Endpoint Auth Method** to `private_key_jwt`
4. Upload `cert.pem` in the **Certificates** section
5. Save changes

::: tip Multiple Certificates per Client
You can register **multiple certificates** for the same API client. This is useful for:
- **Team collaboration**: Each developer generates their own key pair and registers their certificate
- **Key rotation**: Add a new certificate before removing the old one (zero downtime)
- **Multi-environment**: Different certificates for CI/CD, staging, production

Account Manager will verify JWT signatures against all registered certificates, so each team member can authenticate with their own private key while sharing the same client ID.
:::

#### Step 3: Configure CLI

You can provide JWT credentials via CLI flags, environment variables, or configuration files.

**Using CLI flags:**

```bash
b2c code list \
--client-id your-client-id \
--jwt-cert ./cert.pem \
--jwt-key ./key.pem
```

**Using environment variables:**

```bash
export SFCC_CLIENT_ID=your-client-id
export SFCC_JWT_CERT=/path/to/cert.pem
export SFCC_JWT_KEY=/path/to/key.pem

b2c code list
```

**Using dw.json:**

```json
{
"hostname": "your-instance.demandware.net",
"client-id": "your-client-id",
"jwt-cert-path": "./cert.pem",
"jwt-key-path": "./key.pem"
}
```

**For encrypted keys:**

```bash
b2c code list \
--client-id your-client-id \
--jwt-cert ./cert.pem \
--jwt-key ./key.pem \
--jwt-passphrase "your-passphrase"

# Or via environment variable
export SFCC_JWT_PASSPHRASE=your-passphrase
```

### Authentication Priority

JWT authentication is tried **after** client credentials (if client secret is available) but **before** implicit flow:

1. `client-credentials` - Uses client secret if available
2. `jwt` - Uses JWT certificate if configured (no client secret)
3. `implicit` - Opens browser for user authentication

To force JWT authentication even when a client secret is configured:

```bash
b2c code list --auth-methods jwt
```

### Troubleshooting

**"JWT certificate file not found"**
- Verify the certificate path is correct
- Use absolute paths or paths relative to current directory

**"Invalid JWT private key"**
- Check that the key file is in PEM format
- If encrypted, ensure you provide the correct passphrase via `--jwt-passphrase`

**"JWT authentication failed (401)"**
- Verify the certificate is registered in Account Manager
- Ensure the Token Endpoint Auth Method is set to `private_key_jwt`
- Check that the client ID matches the API client with the registered certificate

**"Invalid certificate format"**
- The certificate must be in PEM format (starts with `-----BEGIN CERTIFICATE-----`)
- Regenerate the certificate using the OpenSSL command above

### Security Best Practices

- **Keep private keys secure**: Never commit `key.pem` to version control
- **Add to .gitignore**: Include `*.pem` and `*.key` in your `.gitignore`
- **Use encrypted keys in production**: Generate keys with passphrases for production use
- **Rotate certificates regularly**: Generate new certificates periodically (every 90-365 days)
- **Store passphrases securely**: Use secret managers for passphrases in CI/CD

## OCAPI Configuration

For operations that interact with B2C Commerce instances (code deployment, jobs, sites), you need to configure OCAPI permissions on each instance.
Expand Down
40 changes: 37 additions & 3 deletions docs/guide/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ For detailed setup instructions including Account Manager API client creation, r

OAuth is required for API operations (code list/activate/delete, jobs, sites, SCAPI commands, SLAS, ODS) and can also be used for WebDAV file operations when basic auth credentials are not provided.

#### Client Credentials (Recommended)
#### Client Credentials

OAuth client credentials is the recommended method for production and CI/CD use:
OAuth client credentials uses a client ID and secret for non-interactive authentication:

```bash
b2c code deploy \
Expand All @@ -27,6 +27,20 @@ b2c code deploy \
--client-secret your-client-secret
```

#### JWT Bearer

JWT Bearer uses certificate-based authentication for enhanced security without storing client secrets:

```bash
b2c code deploy \
--server abcd-123.dx.commercecloud.salesforce.com \
--client-id your-client-id \
--jwt-cert ./cert.pem \
--jwt-key ./key.pem
```

See [JWT Authentication](./authentication#jwt-authentication-certificate-based) for setup instructions.

#### Implicit Flow

For development without a client secret, use implicit flow which opens a browser for authentication:
Expand Down Expand Up @@ -65,6 +79,9 @@ You can configure the CLI using environment variables:
| `SFCC_CODE_VERSION` | Code version for deployments |
| `SFCC_CLIENT_ID` | OAuth client ID |
| `SFCC_CLIENT_SECRET` | OAuth client secret |
| `SFCC_JWT_CERT` | Path to JWT certificate file (cert.pem) for JWT Bearer auth |
| `SFCC_JWT_KEY` | Path to JWT private key file (key.pem) for JWT Bearer auth |
| `SFCC_JWT_PASSPHRASE` | Passphrase for encrypted JWT private key |
| `SFCC_OAUTH_SCOPES` | OAuth scopes to request |
| `SFCC_AUTH_METHODS` | Comma-separated list of allowed auth methods |
| `SFCC_SHORTCODE` | SCAPI short code |
Expand Down Expand Up @@ -124,6 +141,18 @@ Both camelCase and kebab-case are accepted for all field names in `dw.json`. For
}
```

Or with JWT Bearer authentication:

```json
{
"hostname": "abcd-123.dx.commercecloud.salesforce.com",
"code-version": "version1",
"client-id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"jwt-cert-path": "./cert.pem",
"jwt-key-path": "./key.pem"
}
```

### Multiple Instances

For projects that work with multiple instances, use the `configs` array:
Expand Down Expand Up @@ -219,6 +248,9 @@ For the full command reference with all flags, see [Setup Commands](/cli/setup).
| `code-version` | Code version for deployments |
| `client-id` | OAuth client ID |
| `client-secret` | OAuth client secret |
| `jwt-cert-path` | Path to JWT certificate file (cert.pem) for JWT Bearer authentication. Also accepts `jwtCertPath`. |
| `jwt-key-path` | Path to JWT private key file (key.pem) for JWT Bearer authentication. Also accepts `jwtKeyPath`. |
| `jwt-passphrase` | Passphrase for encrypted JWT private key. Also accepts `jwtPassphrase`. |
| `username` | Basic auth username (WebDAV) |
| `password` | Basic auth access key (WebDAV) |
| `oauth-scopes` | OAuth scopes (array of strings) |
Expand Down Expand Up @@ -324,7 +356,8 @@ Plugins can add custom configuration sources like secret managers or environment

To prevent mixing credentials from different sources, certain fields are treated as atomic groups:

- **OAuth**: `clientId` and `clientSecret`
- **OAuth Client Credentials**: `clientId` and `clientSecret`
- **OAuth JWT Bearer**: `clientId`, `jwtCertPath`, `jwtKeyPath`, and `jwtPassphrase`
- **Basic Auth**: `username` and `password`

If any field in a group is set by a higher-priority source, all fields in that group from lower-priority sources are ignored. This ensures credential pairs always come from the same source.
Expand Down Expand Up @@ -368,6 +401,7 @@ For platform-level commands (Sandbox, SLAS, and Account Manager), the CLI includ
### Available Auth Methods

- `client-credentials` - OAuth 2.0 client credentials flow (requires client ID and secret). Used for SCAPI/OCAPI and WebDAV.
- `jwt` - OAuth 2.0 JWT Bearer flow (requires client ID, certificate, and private key). Used for SCAPI/OCAPI and WebDAV. More secure than client credentials.
- `implicit` - OAuth 2.0 implicit flow (requires client ID only, opens browser for login). Used for SCAPI/OCAPI and WebDAV.
- `basic` - Basic authentication with username and access key. Used for WebDAV operations only.
- `api-key` - API key authentication. Used for MRT commands only.
Expand Down
3 changes: 3 additions & 0 deletions packages/b2c-tooling-sdk/src/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*
* - {@link BasicAuthStrategy} - Username/password authentication for WebDAV operations
* - {@link OAuthStrategy} - OAuth 2.0 client credentials for OCAPI and platform APIs
* - {@link JwtOAuthStrategy} - OAuth 2.0 JWT Bearer (certificate-based authentication)
* - {@link ImplicitOAuthStrategy} - Interactive browser-based OAuth for CLI/desktop apps
* - {@link ApiKeyStrategy} - API key authentication for MRT services
*
Expand Down Expand Up @@ -80,6 +81,8 @@ export {OAuthStrategy, decodeJWT} from './oauth.js';
export type {OAuthConfig} from './oauth.js';
export {ImplicitOAuthStrategy} from './oauth-implicit.js';
export type {ImplicitOAuthConfig} from './oauth-implicit.js';
export {JwtOAuthStrategy} from './oauth-jwt.js';
export type {JwtOAuthConfig} from './oauth-jwt.js';
export {ApiKeyStrategy} from './api-key.js';
export {StatefulOAuthStrategy} from './stateful-oauth-strategy.js';
export type {StatefulOAuthStrategyOptions} from './stateful-oauth-strategy.js';
Expand Down
Loading
Loading