@salesforce/b2c-tooling-sdk 1.21.3 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/guides/enrichment.json +294 -0
- package/data/guides/index.json +376 -16
- package/data/help/index.json +6 -1
- package/data/job-steps/index.json +1 -1
- package/data/job-steps/job-steps.json +1 -1
- package/data/script-api/index.json +49 -5
- package/data/tooling/index.json +2 -2
- package/data/xsd/commercefeaturestate.xsd +1 -0
- package/data/xsd/index.json +2 -1
- package/data/xsd/redirecturl.xsd +2 -0
- package/dist/esm/auth/index.d.ts +6 -3
- package/dist/esm/auth/index.js +4 -2
- package/dist/esm/auth/index.js.map +1 -1
- package/dist/esm/auth/oauth-implicit.d.ts +19 -0
- package/dist/esm/auth/oauth-implicit.js +103 -10
- package/dist/esm/auth/oauth-implicit.js.map +1 -1
- package/dist/esm/auth/oauth-pkce-fallback.d.ts +68 -0
- package/dist/esm/auth/oauth-pkce-fallback.js +128 -0
- package/dist/esm/auth/oauth-pkce-fallback.js.map +1 -0
- package/dist/esm/auth/oauth-pkce.d.ts +94 -0
- package/dist/esm/auth/oauth-pkce.js +579 -0
- package/dist/esm/auth/oauth-pkce.js.map +1 -0
- package/dist/esm/auth/resolve.d.ts +4 -3
- package/dist/esm/auth/resolve.js +17 -2
- package/dist/esm/auth/resolve.js.map +1 -1
- package/dist/esm/auth/session-store.d.ts +99 -0
- package/dist/esm/auth/session-store.js +242 -0
- package/dist/esm/auth/session-store.js.map +1 -0
- package/dist/esm/auth/stateful-oauth-strategy.d.ts +20 -24
- package/dist/esm/auth/stateful-oauth-strategy.js +16 -114
- package/dist/esm/auth/stateful-oauth-strategy.js.map +1 -1
- package/dist/esm/auth/types.d.ts +20 -4
- package/dist/esm/auth/types.js +1 -1
- package/dist/esm/auth/types.js.map +1 -1
- package/dist/esm/cli/am-command.d.ts +2 -2
- package/dist/esm/cli/am-command.js +13 -4
- package/dist/esm/cli/am-command.js.map +1 -1
- package/dist/esm/cli/base-command.js +3 -3
- package/dist/esm/cli/base-command.js.map +1 -1
- package/dist/esm/cli/config.js +3 -1
- package/dist/esm/cli/config.js.map +1 -1
- package/dist/esm/cli/lifecycle.d.ts +1 -1
- package/dist/esm/cli/lifecycle.js.map +1 -1
- package/dist/esm/cli/oauth-command.d.ts +12 -11
- package/dist/esm/cli/oauth-command.js +73 -41
- package/dist/esm/cli/oauth-command.js.map +1 -1
- package/dist/esm/cli/ods-command.d.ts +1 -1
- package/dist/esm/cli/ods-command.js +5 -3
- package/dist/esm/cli/ods-command.js.map +1 -1
- package/dist/esm/clients/ods.generated.d.ts +16 -0
- package/dist/esm/config/dw-json.d.ts +10 -0
- package/dist/esm/config/dw-json.js.map +1 -1
- package/dist/esm/config/index.d.ts +1 -0
- package/dist/esm/config/index.js +2 -0
- package/dist/esm/config/index.js.map +1 -1
- package/dist/esm/config/mapping.d.ts +13 -0
- package/dist/esm/config/mapping.js +66 -3
- package/dist/esm/config/mapping.js.map +1 -1
- package/dist/esm/config/redaction.d.ts +39 -0
- package/dist/esm/config/redaction.js +51 -0
- package/dist/esm/config/redaction.js.map +1 -0
- package/dist/esm/config/resolver.js +1 -0
- package/dist/esm/config/resolver.js.map +1 -1
- package/dist/esm/config/sources/env-source.js +2 -0
- package/dist/esm/config/sources/env-source.js.map +1 -1
- package/dist/esm/config/sources/package-json-source.js +1 -0
- package/dist/esm/config/sources/package-json-source.js.map +1 -1
- package/dist/esm/config/types.d.ts +14 -4
- package/dist/esm/defaults.d.ts +23 -4
- package/dist/esm/defaults.js +36 -4
- package/dist/esm/defaults.js.map +1 -1
- package/dist/esm/docs/content-cache.d.ts +1 -1
- package/dist/esm/docs/content-cache.js +1 -1
- package/dist/esm/docs/index.d.ts +1 -1
- package/dist/esm/docs/index.js.map +1 -1
- package/dist/esm/docs/types.d.ts +29 -0
- package/dist/esm/index.d.ts +6 -4
- package/dist/esm/index.js +3 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/instance/index.js +3 -3
- package/dist/esm/instance/index.js.map +1 -1
- package/dist/esm/operations/cap/index.d.ts +2 -2
- package/dist/esm/operations/cap/index.js +1 -1
- package/dist/esm/operations/cap/index.js.map +1 -1
- package/dist/esm/operations/cap/install.d.ts +17 -0
- package/dist/esm/operations/cap/install.js +29 -0
- package/dist/esm/operations/cap/install.js.map +1 -1
- package/dist/esm/operations/cap/package.js +36 -0
- package/dist/esm/operations/cap/package.js.map +1 -1
- package/dist/esm/operations/cap/validate.d.ts +9 -0
- package/dist/esm/operations/cap/validate.js +29 -0
- package/dist/esm/operations/cap/validate.js.map +1 -1
- package/dist/esm/operations/content/export.js +7 -3
- package/dist/esm/operations/content/export.js.map +1 -1
- package/dist/esm/operations/content/library.d.ts +26 -0
- package/dist/esm/operations/content/library.js +83 -2
- package/dist/esm/operations/content/library.js.map +1 -1
- package/dist/esm/operations/content/types.d.ts +10 -1
- package/dist/esm/operations/jobs/import-set.d.ts +170 -0
- package/dist/esm/operations/jobs/import-set.js +538 -0
- package/dist/esm/operations/jobs/import-set.js.map +1 -0
- package/dist/esm/operations/jobs/index.d.ts +3 -0
- package/dist/esm/operations/jobs/index.js +3 -0
- package/dist/esm/operations/jobs/index.js.map +1 -1
- package/dist/esm/operations/jobs/run.js +0 -11
- package/dist/esm/operations/jobs/run.js.map +1 -1
- package/dist/esm/operations/jobs/site-archive.js +13 -75
- package/dist/esm/operations/jobs/site-archive.js.map +1 -1
- package/dist/esm/operations/ods/index.d.ts +4 -0
- package/dist/esm/operations/ods/index.js +2 -0
- package/dist/esm/operations/ods/index.js.map +1 -1
- package/dist/esm/operations/ods/sandbox-settings.d.ts +51 -0
- package/dist/esm/operations/ods/sandbox-settings.js +63 -0
- package/dist/esm/operations/ods/sandbox-settings.js.map +1 -0
- package/dist/esm/operations/ods/wait-for-clones.d.ts +97 -0
- package/dist/esm/operations/ods/wait-for-clones.js +145 -0
- package/dist/esm/operations/ods/wait-for-clones.js.map +1 -0
- package/package.json +1 -1
- package/specs/ods-api-v1.json +43 -0
- package/dist/esm/auth/stateful-store.d.ts +0 -49
- package/dist/esm/auth/stateful-store.js +0 -166
- package/dist/esm/auth/stateful-store.js.map +0 -1
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025, Salesforce, Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2
|
|
4
|
+
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
7
|
+
import { createServer } from 'node:http';
|
|
8
|
+
import { URL } from 'node:url';
|
|
9
|
+
import { dispatchFetch } from './dispatch-fetch.js';
|
|
10
|
+
import { getLogger } from '../logging/logger.js';
|
|
11
|
+
import { decodeJWT } from './oauth.js';
|
|
12
|
+
import { DEFAULT_ACCOUNT_MANAGER_HOST } from '../defaults.js';
|
|
13
|
+
import { findAuthSession, saveAuthSession } from './session-store.js';
|
|
14
|
+
const DEFAULT_LOCAL_PORT = 8080;
|
|
15
|
+
const ACCESS_TOKEN_CACHE = new Map();
|
|
16
|
+
const PENDING_AUTH = new Map();
|
|
17
|
+
/**
|
|
18
|
+
* Thrown when the Authorization Code + PKCE flow fails in a way that indicates
|
|
19
|
+
* the Account Manager client is not registered for this grant (e.g. an old
|
|
20
|
+
* implicit-only public client, or a missing/mismatched redirect URI) rather
|
|
21
|
+
* than a transient or user-driven failure.
|
|
22
|
+
*
|
|
23
|
+
* {@link PkceWithImplicitFallbackStrategy} keys its automatic fallback off this
|
|
24
|
+
* type so it retries with the legacy implicit flow ONLY for grant/registration
|
|
25
|
+
* failures — never for user-cancel, state mismatch, or a port-in-use error.
|
|
26
|
+
*
|
|
27
|
+
* @remarks Part of the implicit→PKCE migration safety net. Remove together with
|
|
28
|
+
* the fallback strategy once all public clients are PKCE-capable.
|
|
29
|
+
*/
|
|
30
|
+
export class PkceGrantUnsupportedError extends Error {
|
|
31
|
+
/** The OAuth 2.0 `error` code from the authorize redirect or token response, when available. */
|
|
32
|
+
oauthError;
|
|
33
|
+
/** The OAuth stage at which the failure occurred. */
|
|
34
|
+
stage;
|
|
35
|
+
constructor(message, stage, oauthError) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = 'PkceGrantUnsupportedError';
|
|
38
|
+
this.stage = stage;
|
|
39
|
+
this.oauthError = oauthError;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* OAuth 2.0 `error` codes that genuinely indicate the client is not registered
|
|
44
|
+
* as a PKCE-capable public client — the only failures the implicit fallback can
|
|
45
|
+
* legitimately rescue. Implicit shares the same authorize endpoint and redirect
|
|
46
|
+
* URI but returns the token on the redirect with NO token-endpoint call and NO
|
|
47
|
+
* client authentication, so it rescues clients that support implicit but not
|
|
48
|
+
* the Authorization Code grant:
|
|
49
|
+
*
|
|
50
|
+
* - `invalid_client` — at the token exchange, Account Manager demands client
|
|
51
|
+
* authentication (e.g. "Parameter client_assertion_type is missing"), i.e. the
|
|
52
|
+
* client is confidential/implicit-only, NOT a public/PKCE client. This is the
|
|
53
|
+
* primary real-world migration case for legacy implicit clients.
|
|
54
|
+
* - `unauthorized_client` — client is not permitted to use this grant type.
|
|
55
|
+
* - `unsupported_response_type` — authorize endpoint rejects `response_type=code`.
|
|
56
|
+
* - `unsupported_grant_type` — token endpoint rejects `authorization_code`.
|
|
57
|
+
*
|
|
58
|
+
* Every other error is a real failure that would fail identically under
|
|
59
|
+
* implicit and MUST NOT trigger the fallback, e.g. `invalid_scope` (bad
|
|
60
|
+
* scopes), `access_denied` (user cancelled consent), `invalid_grant`
|
|
61
|
+
* (expired/replayed code or PKCE verifier mismatch), `invalid_request`.
|
|
62
|
+
*/
|
|
63
|
+
const PKCE_GRANT_UNSUPPORTED_OAUTH_ERRORS = new Set([
|
|
64
|
+
'invalid_client',
|
|
65
|
+
'unauthorized_client',
|
|
66
|
+
'unsupported_response_type',
|
|
67
|
+
'unsupported_grant_type',
|
|
68
|
+
]);
|
|
69
|
+
/**
|
|
70
|
+
* Returns true only when an OAuth `error` code indicates the client cannot use
|
|
71
|
+
* the Authorization Code (PKCE) grant — the narrow set of failures the implicit
|
|
72
|
+
* fallback should rescue. Unknown/absent codes return false so ambiguous
|
|
73
|
+
* failures surface directly instead of silently downgrading to implicit.
|
|
74
|
+
*/
|
|
75
|
+
function isPkceGrantUnsupportedError(oauthError) {
|
|
76
|
+
return oauthError !== undefined && PKCE_GRANT_UNSUPPORTED_OAUTH_ERRORS.has(oauthError);
|
|
77
|
+
}
|
|
78
|
+
function base64url(buf) {
|
|
79
|
+
return buf.toString('base64').replace(/=+$/, '').replaceAll('+', '-').replaceAll('/', '_');
|
|
80
|
+
}
|
|
81
|
+
function generatePkcePair() {
|
|
82
|
+
const verifier = base64url(randomBytes(32));
|
|
83
|
+
const challenge = base64url(createHash('sha256').update(verifier).digest());
|
|
84
|
+
return { verifier, challenge };
|
|
85
|
+
}
|
|
86
|
+
function parseOAuthErrorBody(text) {
|
|
87
|
+
try {
|
|
88
|
+
const parsed = JSON.parse(text);
|
|
89
|
+
return {
|
|
90
|
+
error: typeof parsed.error === 'string' ? parsed.error : undefined,
|
|
91
|
+
errorDescription: typeof parsed.error_description === 'string' ? parsed.error_description : undefined,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return {};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function openBrowserDefault(url) {
|
|
99
|
+
try {
|
|
100
|
+
const open = await import('open');
|
|
101
|
+
await open.default(url);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
getLogger().debug('Could not automatically open browser');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* OAuth 2.0 Authorization Code Flow with PKCE.
|
|
109
|
+
*
|
|
110
|
+
* Used for public clients (no client secret). Replaces the legacy implicit flow,
|
|
111
|
+
* which is deprecated for public clients per OAuth 2.1.
|
|
112
|
+
*
|
|
113
|
+
* Flow:
|
|
114
|
+
* 1. Generate PKCE verifier + S256 challenge.
|
|
115
|
+
* 2. Open browser to `/dwsso/oauth2/authorize?response_type=code&code_challenge=...`.
|
|
116
|
+
* 3. Capture redirect with `?code=...` on a localhost listener.
|
|
117
|
+
* 4. POST `grant_type=authorization_code` + `code_verifier` to `/dwsso/oauth2/access_token`.
|
|
118
|
+
*
|
|
119
|
+
* Tokens may include a refresh_token (depends on client registration in Account Manager).
|
|
120
|
+
*/
|
|
121
|
+
export class PkceOAuthStrategy {
|
|
122
|
+
config;
|
|
123
|
+
accountManagerHost;
|
|
124
|
+
localPort;
|
|
125
|
+
redirectUri;
|
|
126
|
+
persistSession;
|
|
127
|
+
_hasHadSuccess = false;
|
|
128
|
+
_refreshToken = null;
|
|
129
|
+
_sub = '';
|
|
130
|
+
_hydrated = false;
|
|
131
|
+
constructor(config) {
|
|
132
|
+
this.config = config;
|
|
133
|
+
this.accountManagerHost = config.accountManagerHost || DEFAULT_ACCOUNT_MANAGER_HOST;
|
|
134
|
+
this.localPort = config.localPort || parseInt(process.env.SFCC_OAUTH_LOCAL_PORT || '', 10) || DEFAULT_LOCAL_PORT;
|
|
135
|
+
this.redirectUri = config.redirectUri || process.env.SFCC_REDIRECT_URI || `http://localhost:${this.localPort}`;
|
|
136
|
+
this.persistSession = config.persistSession !== false;
|
|
137
|
+
getLogger().debug({
|
|
138
|
+
clientId: this.config.clientId,
|
|
139
|
+
accountManagerHost: this.accountManagerHost,
|
|
140
|
+
port: this.localPort,
|
|
141
|
+
redirectUri: this.redirectUri,
|
|
142
|
+
persistSession: this.persistSession,
|
|
143
|
+
}, '[Auth] PkceOAuthStrategy initialized');
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Load any persisted session for this clientId. Idempotent.
|
|
147
|
+
*/
|
|
148
|
+
hydrate() {
|
|
149
|
+
if (!this.persistSession || this._hydrated)
|
|
150
|
+
return;
|
|
151
|
+
this._hydrated = true;
|
|
152
|
+
try {
|
|
153
|
+
const stored = findAuthSession(this.config.clientId);
|
|
154
|
+
if (!stored || stored.flow !== 'pkce')
|
|
155
|
+
return;
|
|
156
|
+
this._sub = stored.sub ?? '';
|
|
157
|
+
this._refreshToken = stored.refreshToken ?? null;
|
|
158
|
+
if (!ACCESS_TOKEN_CACHE.has(this.config.clientId) && stored.accessToken) {
|
|
159
|
+
const expires = stored.expiresAt ? new Date(stored.expiresAt) : new Date(0);
|
|
160
|
+
ACCESS_TOKEN_CACHE.set(this.config.clientId, {
|
|
161
|
+
accessToken: stored.accessToken,
|
|
162
|
+
expires,
|
|
163
|
+
scopes: stored.scopes ?? [],
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
getLogger().debug({ clientId: this.config.clientId, sub: this._sub, hasRefresh: this._refreshToken !== null }, '[Auth] Hydrated PKCE session from store');
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
getLogger().debug({ err: error }, '[Auth] PKCE store hydration failed');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async fetch(url, init = {}) {
|
|
173
|
+
const logger = getLogger();
|
|
174
|
+
const method = init.method || 'GET';
|
|
175
|
+
const token = await this.getAccessToken();
|
|
176
|
+
const headers = new Headers(init.headers);
|
|
177
|
+
headers.set('Authorization', `Bearer ${token}`);
|
|
178
|
+
headers.set('x-dw-client-id', this.config.clientId);
|
|
179
|
+
let res = await dispatchFetch(url, { ...init, headers });
|
|
180
|
+
logger.debug({ method, url, status: res.status }, '[Auth] Response');
|
|
181
|
+
if (res.status !== 401) {
|
|
182
|
+
this._hasHadSuccess = true;
|
|
183
|
+
}
|
|
184
|
+
if (res.status === 401 && this._hasHadSuccess) {
|
|
185
|
+
logger.debug('[Auth] Received 401, invalidating PKCE token and retrying');
|
|
186
|
+
this.invalidateToken();
|
|
187
|
+
const newToken = await this.getAccessToken();
|
|
188
|
+
headers.set('Authorization', `Bearer ${newToken}`);
|
|
189
|
+
res = await dispatchFetch(url, { ...init, headers });
|
|
190
|
+
logger.debug({ method, url, status: res.status }, '[Auth] Retry response');
|
|
191
|
+
}
|
|
192
|
+
return res;
|
|
193
|
+
}
|
|
194
|
+
async getAuthorizationHeader() {
|
|
195
|
+
const token = await this.getAccessToken();
|
|
196
|
+
return `Bearer ${token}`;
|
|
197
|
+
}
|
|
198
|
+
async getJWT() {
|
|
199
|
+
const token = await this.getAccessToken();
|
|
200
|
+
return decodeJWT(token);
|
|
201
|
+
}
|
|
202
|
+
async getTokenResponse() {
|
|
203
|
+
this.hydrate();
|
|
204
|
+
const cached = ACCESS_TOKEN_CACHE.get(this.config.clientId);
|
|
205
|
+
if (cached && this.isCachedTokenUsable(cached)) {
|
|
206
|
+
return cached;
|
|
207
|
+
}
|
|
208
|
+
if (this._refreshToken) {
|
|
209
|
+
const refreshed = await this.tryRefresh();
|
|
210
|
+
if (refreshed)
|
|
211
|
+
return refreshed;
|
|
212
|
+
}
|
|
213
|
+
const tokenResponse = await this.runFlow();
|
|
214
|
+
ACCESS_TOKEN_CACHE.set(this.config.clientId, tokenResponse);
|
|
215
|
+
return tokenResponse;
|
|
216
|
+
}
|
|
217
|
+
invalidateToken() {
|
|
218
|
+
// Only drop the cached access token. The refresh token is preserved so the
|
|
219
|
+
// next getAccessToken() can silently mint a new access token via
|
|
220
|
+
// tryRefresh() instead of re-opening the browser. tryRefresh() forgets the
|
|
221
|
+
// refresh token on its own when the exchange genuinely fails (revoked /
|
|
222
|
+
// expired), which is the only case where we fall back to the browser flow.
|
|
223
|
+
ACCESS_TOKEN_CACHE.delete(this.config.clientId);
|
|
224
|
+
}
|
|
225
|
+
isCachedTokenUsable(cached) {
|
|
226
|
+
const requiredScopes = this.config.scopes || [];
|
|
227
|
+
const hasAllScopes = requiredScopes.every((scope) => cached.scopes.includes(scope));
|
|
228
|
+
return hasAllScopes && Date.now() <= cached.expires.getTime();
|
|
229
|
+
}
|
|
230
|
+
async getAccessToken() {
|
|
231
|
+
this.hydrate();
|
|
232
|
+
const clientId = this.config.clientId;
|
|
233
|
+
const cached = ACCESS_TOKEN_CACHE.get(clientId);
|
|
234
|
+
if (cached && this.isCachedTokenUsable(cached)) {
|
|
235
|
+
return cached.accessToken;
|
|
236
|
+
}
|
|
237
|
+
if (cached) {
|
|
238
|
+
ACCESS_TOKEN_CACHE.delete(clientId);
|
|
239
|
+
}
|
|
240
|
+
const pending = PENDING_AUTH.get(clientId);
|
|
241
|
+
if (pending) {
|
|
242
|
+
const tokenResponse = await pending;
|
|
243
|
+
return tokenResponse.accessToken;
|
|
244
|
+
}
|
|
245
|
+
const authPromise = (async () => {
|
|
246
|
+
if (this._refreshToken) {
|
|
247
|
+
const refreshed = await this.tryRefresh();
|
|
248
|
+
if (refreshed)
|
|
249
|
+
return refreshed;
|
|
250
|
+
}
|
|
251
|
+
return this.runFlow();
|
|
252
|
+
})();
|
|
253
|
+
PENDING_AUTH.set(clientId, authPromise);
|
|
254
|
+
try {
|
|
255
|
+
const tokenResponse = await authPromise;
|
|
256
|
+
ACCESS_TOKEN_CACHE.set(clientId, tokenResponse);
|
|
257
|
+
return tokenResponse.accessToken;
|
|
258
|
+
}
|
|
259
|
+
finally {
|
|
260
|
+
PENDING_AUTH.delete(clientId);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Exchange a stored refresh_token for a new access token. Returns null if no
|
|
265
|
+
* refresh token is available or the exchange fails (e.g. revoked / expired).
|
|
266
|
+
* On failure, the refresh token is forgotten so the next request triggers
|
|
267
|
+
* the browser flow.
|
|
268
|
+
*/
|
|
269
|
+
async tryRefresh() {
|
|
270
|
+
const logger = getLogger();
|
|
271
|
+
if (!this._refreshToken)
|
|
272
|
+
return null;
|
|
273
|
+
const tokenUrl = `https://${this.accountManagerHost}/dwsso/oauth2/access_token`;
|
|
274
|
+
const body = new URLSearchParams({
|
|
275
|
+
grant_type: 'refresh_token',
|
|
276
|
+
refresh_token: this._refreshToken,
|
|
277
|
+
client_id: this.config.clientId,
|
|
278
|
+
});
|
|
279
|
+
if (this.config.scopes && this.config.scopes.length > 0) {
|
|
280
|
+
body.set('scope', this.config.scopes.join(' '));
|
|
281
|
+
}
|
|
282
|
+
logger.debug({ method: 'POST', url: tokenUrl }, '[Auth REQ] POST /dwsso/oauth2/access_token (refresh_token)');
|
|
283
|
+
// refresh_token is a secret; trace only the non-sensitive parameters.
|
|
284
|
+
logger.trace({
|
|
285
|
+
method: 'POST',
|
|
286
|
+
url: tokenUrl,
|
|
287
|
+
body: { grant_type: 'refresh_token', client_id: this.config.clientId, scope: this.config.scopes?.join(' ') },
|
|
288
|
+
}, '[Auth REQ BODY] POST /dwsso/oauth2/access_token (refresh_token)');
|
|
289
|
+
let response;
|
|
290
|
+
try {
|
|
291
|
+
response = await dispatchFetch(tokenUrl, {
|
|
292
|
+
method: 'POST',
|
|
293
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
294
|
+
body: body.toString(),
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
catch (error) {
|
|
298
|
+
logger.debug({ err: error }, '[Auth] PKCE refresh request failed');
|
|
299
|
+
this._refreshToken = null;
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
logger.debug({ url: tokenUrl, status: response.status }, `[Auth RESP] POST /dwsso/oauth2/access_token ${response.status}`);
|
|
303
|
+
if (!response.ok) {
|
|
304
|
+
const text = await response.text();
|
|
305
|
+
const oauthError = parseOAuthErrorBody(text);
|
|
306
|
+
logger.trace({ url: tokenUrl, status: response.status, body: oauthError }, '[Auth RESP BODY] POST /dwsso/oauth2/access_token (refresh_token)');
|
|
307
|
+
logger.debug({ status: response.status, oauthError: oauthError.error }, '[Auth] PKCE refresh failed; falling back to browser flow');
|
|
308
|
+
this._refreshToken = null;
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
let parsed;
|
|
312
|
+
try {
|
|
313
|
+
parsed = (await response.json());
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
logger.debug({ err: error }, '[Auth] PKCE refresh returned non-JSON response');
|
|
317
|
+
this._refreshToken = null;
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
if (typeof parsed.access_token !== 'string' || parsed.access_token.length === 0) {
|
|
321
|
+
logger.debug('[Auth] PKCE refresh response did not contain an access token');
|
|
322
|
+
this._refreshToken = null;
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
const expiresIn = typeof parsed.expires_in === 'number' ? parsed.expires_in : 0;
|
|
326
|
+
const expires = new Date(Date.now() + expiresIn * 1000);
|
|
327
|
+
const scopes = typeof parsed.scope === 'string' ? parsed.scope.split(' ') : (this.config.scopes ?? []);
|
|
328
|
+
const tokenResponse = {
|
|
329
|
+
accessToken: parsed.access_token,
|
|
330
|
+
expires,
|
|
331
|
+
scopes,
|
|
332
|
+
};
|
|
333
|
+
if (typeof parsed.refresh_token === 'string' && parsed.refresh_token.length > 0) {
|
|
334
|
+
this._refreshToken = parsed.refresh_token;
|
|
335
|
+
}
|
|
336
|
+
try {
|
|
337
|
+
logger.trace({ jwt: decodeJWT(parsed.access_token).payload }, '[Auth] Refreshed PKCE access token JWT payload');
|
|
338
|
+
}
|
|
339
|
+
catch {
|
|
340
|
+
// access token is not a JWT; nothing to trace
|
|
341
|
+
}
|
|
342
|
+
this.persistTokens(tokenResponse);
|
|
343
|
+
logger.debug({ clientId: this.config.clientId }, '[Auth] PKCE token refreshed silently');
|
|
344
|
+
return tokenResponse;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Persist the current token + refresh token. No-op when `persistSession`
|
|
348
|
+
* is disabled. Updates `_sub` from the JWT when available so the persisted
|
|
349
|
+
* record carries the authenticated user identity for diagnostics.
|
|
350
|
+
*/
|
|
351
|
+
persistTokens(tokenResponse) {
|
|
352
|
+
if (!this.persistSession)
|
|
353
|
+
return;
|
|
354
|
+
let sub = this._sub;
|
|
355
|
+
try {
|
|
356
|
+
const decoded = decodeJWT(tokenResponse.accessToken);
|
|
357
|
+
if (typeof decoded.payload.sub === 'string' && decoded.payload.sub.length > 0) {
|
|
358
|
+
sub = decoded.payload.sub;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
catch {
|
|
362
|
+
// ignore — token may not be a JWT, fall back to existing _sub
|
|
363
|
+
}
|
|
364
|
+
this._sub = sub;
|
|
365
|
+
const record = {
|
|
366
|
+
clientId: this.config.clientId,
|
|
367
|
+
flow: 'pkce',
|
|
368
|
+
accessToken: tokenResponse.accessToken,
|
|
369
|
+
refreshToken: this._refreshToken,
|
|
370
|
+
sub,
|
|
371
|
+
expiresAt: tokenResponse.expires.toISOString(),
|
|
372
|
+
scopes: tokenResponse.scopes,
|
|
373
|
+
accountManagerHost: this.accountManagerHost,
|
|
374
|
+
};
|
|
375
|
+
try {
|
|
376
|
+
saveAuthSession(record);
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
getLogger().debug({ err: error }, '[Auth] Failed to persist PKCE session');
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
async runFlow() {
|
|
383
|
+
const logger = getLogger();
|
|
384
|
+
logger.trace({ clientId: this.config.clientId, scopes: this.config.scopes, redirectUri: this.redirectUri }, '[Auth] Starting Authorization Code + PKCE flow');
|
|
385
|
+
const { verifier, challenge } = generatePkcePair();
|
|
386
|
+
const state = base64url(randomBytes(16));
|
|
387
|
+
// Verifier is a secret; trace only the derived challenge and state.
|
|
388
|
+
logger.trace({ codeChallenge: challenge, codeChallengeMethod: 'S256', state }, '[Auth] Generated PKCE challenge');
|
|
389
|
+
const params = new URLSearchParams({
|
|
390
|
+
client_id: this.config.clientId,
|
|
391
|
+
redirect_uri: this.redirectUri,
|
|
392
|
+
response_type: 'code',
|
|
393
|
+
code_challenge: challenge,
|
|
394
|
+
code_challenge_method: 'S256',
|
|
395
|
+
state,
|
|
396
|
+
});
|
|
397
|
+
if (this.config.scopes && this.config.scopes.length > 0) {
|
|
398
|
+
params.set('scope', this.config.scopes.join(' '));
|
|
399
|
+
}
|
|
400
|
+
const authorizeUrl = `https://${this.accountManagerHost}/dwsso/oauth2/authorize?${params.toString()}`;
|
|
401
|
+
logger.info({ url: authorizeUrl }, `Login URL: ${authorizeUrl}`);
|
|
402
|
+
logger.info('If the URL does not open automatically, copy/paste it into a browser on this machine.');
|
|
403
|
+
const code = await this.waitForAuthCode(state, async () => {
|
|
404
|
+
if (this.config.openBrowser) {
|
|
405
|
+
await this.config.openBrowser(authorizeUrl);
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
await openBrowserDefault(authorizeUrl);
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
logger.debug({ codePrefix: code.slice(0, 8) }, '[Auth] Got authorization code, exchanging for token');
|
|
412
|
+
const tokenUrl = `https://${this.accountManagerHost}/dwsso/oauth2/access_token`;
|
|
413
|
+
const tokenBody = new URLSearchParams({
|
|
414
|
+
grant_type: 'authorization_code',
|
|
415
|
+
code,
|
|
416
|
+
redirect_uri: this.redirectUri,
|
|
417
|
+
client_id: this.config.clientId,
|
|
418
|
+
code_verifier: verifier,
|
|
419
|
+
});
|
|
420
|
+
logger.debug({ method: 'POST', url: tokenUrl }, '[Auth REQ] POST /dwsso/oauth2/access_token (authorization_code)');
|
|
421
|
+
// Redact the single-use code and PKCE verifier from the traced body.
|
|
422
|
+
logger.trace({
|
|
423
|
+
method: 'POST',
|
|
424
|
+
url: tokenUrl,
|
|
425
|
+
body: { grant_type: 'authorization_code', redirect_uri: this.redirectUri, client_id: this.config.clientId },
|
|
426
|
+
}, '[Auth REQ BODY] POST /dwsso/oauth2/access_token');
|
|
427
|
+
const tokenRes = await dispatchFetch(tokenUrl, {
|
|
428
|
+
method: 'POST',
|
|
429
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
430
|
+
body: tokenBody.toString(),
|
|
431
|
+
});
|
|
432
|
+
const rawText = await tokenRes.text();
|
|
433
|
+
logger.debug({ url: tokenUrl, status: tokenRes.status }, `[Auth RESP] POST /dwsso/oauth2/access_token ${tokenRes.status}`);
|
|
434
|
+
if (!tokenRes.ok) {
|
|
435
|
+
// Distinguish "this client can't do the code grant" (which the implicit
|
|
436
|
+
// fallback can rescue) from real errors that would fail identically under
|
|
437
|
+
// implicit — e.g. invalid_scope, invalid_grant. Only the former is typed
|
|
438
|
+
// as PkceGrantUnsupportedError; everything else is a plain Error so the
|
|
439
|
+
// fallback wrapper propagates it instead of silently downgrading.
|
|
440
|
+
const errorBody = parseOAuthErrorBody(rawText);
|
|
441
|
+
const oauthError = errorBody.error;
|
|
442
|
+
logger.trace({ url: tokenUrl, status: tokenRes.status, body: errorBody }, '[Auth RESP BODY] POST /dwsso/oauth2/access_token');
|
|
443
|
+
const detail = errorBody.errorDescription ?? errorBody.error;
|
|
444
|
+
const message = `PKCE token exchange failed (${tokenRes.status})${detail ? `: ${detail}` : ''}`;
|
|
445
|
+
if (isPkceGrantUnsupportedError(oauthError)) {
|
|
446
|
+
throw new PkceGrantUnsupportedError(message, 'token', oauthError);
|
|
447
|
+
}
|
|
448
|
+
throw new Error(message);
|
|
449
|
+
}
|
|
450
|
+
let parsed;
|
|
451
|
+
try {
|
|
452
|
+
parsed = JSON.parse(rawText);
|
|
453
|
+
}
|
|
454
|
+
catch {
|
|
455
|
+
// Do not echo an untrusted response body: a malformed success response
|
|
456
|
+
// can still contain live token material.
|
|
457
|
+
throw new Error('PKCE token exchange returned a non-JSON response');
|
|
458
|
+
}
|
|
459
|
+
if (typeof parsed.access_token !== 'string' || parsed.access_token.length === 0) {
|
|
460
|
+
throw new Error('PKCE token exchange response did not contain an access token');
|
|
461
|
+
}
|
|
462
|
+
// Never log the raw token response: it contains both the access token and
|
|
463
|
+
// the long-lived refresh token, and an opaque string bypasses pino's
|
|
464
|
+
// field-based redaction. JWT claims are traced below after decoding.
|
|
465
|
+
logger.trace({
|
|
466
|
+
url: tokenUrl,
|
|
467
|
+
status: tokenRes.status,
|
|
468
|
+
body: {
|
|
469
|
+
expires_in: parsed.expires_in,
|
|
470
|
+
scope: parsed.scope,
|
|
471
|
+
hasAccessToken: typeof parsed.access_token === 'string' && parsed.access_token.length > 0,
|
|
472
|
+
hasRefreshToken: typeof parsed.refresh_token === 'string' && parsed.refresh_token.length > 0,
|
|
473
|
+
},
|
|
474
|
+
}, '[Auth RESP BODY] POST /dwsso/oauth2/access_token');
|
|
475
|
+
const expiresIn = typeof parsed.expires_in === 'number' ? parsed.expires_in : 0;
|
|
476
|
+
const expires = new Date(Date.now() + expiresIn * 1000);
|
|
477
|
+
const scopes = typeof parsed.scope === 'string' ? parsed.scope.split(' ') : (this.config.scopes ?? []);
|
|
478
|
+
const tokenResponse = {
|
|
479
|
+
accessToken: parsed.access_token,
|
|
480
|
+
expires,
|
|
481
|
+
scopes,
|
|
482
|
+
};
|
|
483
|
+
if (typeof parsed.refresh_token === 'string' && parsed.refresh_token.length > 0) {
|
|
484
|
+
this._refreshToken = parsed.refresh_token;
|
|
485
|
+
}
|
|
486
|
+
logger.trace({ scopes, expires, hasRefreshToken: !!parsed.refresh_token }, '[Auth] PKCE token exchange succeeded');
|
|
487
|
+
try {
|
|
488
|
+
logger.trace({ jwt: decodeJWT(parsed.access_token).payload }, '[Auth] PKCE access token JWT payload');
|
|
489
|
+
}
|
|
490
|
+
catch {
|
|
491
|
+
// access token is not a JWT; nothing to trace
|
|
492
|
+
}
|
|
493
|
+
this.persistTokens(tokenResponse);
|
|
494
|
+
return tokenResponse;
|
|
495
|
+
}
|
|
496
|
+
waitForAuthCode(expectedState, openBrowser) {
|
|
497
|
+
const logger = getLogger();
|
|
498
|
+
return new Promise((resolve, reject) => {
|
|
499
|
+
const sockets = new Set();
|
|
500
|
+
let settled = false;
|
|
501
|
+
const settleAfterClose = (settle) => {
|
|
502
|
+
if (settled)
|
|
503
|
+
return;
|
|
504
|
+
settled = true;
|
|
505
|
+
const forceCloseTimer = setTimeout(() => {
|
|
506
|
+
for (const socket of sockets)
|
|
507
|
+
socket.destroy();
|
|
508
|
+
}, 100);
|
|
509
|
+
server.close(() => {
|
|
510
|
+
clearTimeout(forceCloseTimer);
|
|
511
|
+
for (const socket of sockets)
|
|
512
|
+
socket.destroy();
|
|
513
|
+
settle();
|
|
514
|
+
});
|
|
515
|
+
};
|
|
516
|
+
const server = createServer((req, res) => {
|
|
517
|
+
const requestUrl = new URL(req.url || '/', `http://localhost:${this.localPort}`);
|
|
518
|
+
const code = requestUrl.searchParams.get('code');
|
|
519
|
+
const state = requestUrl.searchParams.get('state') ?? '';
|
|
520
|
+
const error = requestUrl.searchParams.get('error');
|
|
521
|
+
const errorDescription = requestUrl.searchParams.get('error_description');
|
|
522
|
+
if (error) {
|
|
523
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
524
|
+
res.end(`Authentication failed: ${errorDescription ?? error}`);
|
|
525
|
+
// Only a grant/registration error (e.g. unsupported_response_type,
|
|
526
|
+
// unauthorized_client) means the client can't do the code grant — the
|
|
527
|
+
// implicit fallback can rescue that. A user-driven error like
|
|
528
|
+
// access_denied (cancelled consent) MUST NOT fall back, so type it
|
|
529
|
+
// only for the grant-unsupported set; otherwise reject plainly.
|
|
530
|
+
const message = `OAuth error: ${errorDescription ?? error}`;
|
|
531
|
+
const authError = isPkceGrantUnsupportedError(error)
|
|
532
|
+
? new PkceGrantUnsupportedError(message, 'authorize', error)
|
|
533
|
+
: new Error(message);
|
|
534
|
+
settleAfterClose(() => reject(authError));
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
if (!code) {
|
|
538
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
539
|
+
res.end('Waiting for authorization code...');
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
if (state !== expectedState) {
|
|
543
|
+
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
|
544
|
+
res.end('State mismatch.');
|
|
545
|
+
settleAfterClose(() => reject(new Error('OAuth state mismatch — aborting')));
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
549
|
+
res.end('Authentication successful! You may close this browser window and return to your terminal.');
|
|
550
|
+
settleAfterClose(() => resolve(code));
|
|
551
|
+
});
|
|
552
|
+
server.on('connection', (socket) => {
|
|
553
|
+
sockets.add(socket);
|
|
554
|
+
socket.on('close', () => sockets.delete(socket));
|
|
555
|
+
});
|
|
556
|
+
server.listen(this.localPort, async () => {
|
|
557
|
+
logger.debug({ port: this.localPort }, `[Auth] PKCE redirect server listening on port ${this.localPort}`);
|
|
558
|
+
logger.info('Waiting for user to authenticate...');
|
|
559
|
+
try {
|
|
560
|
+
await openBrowser();
|
|
561
|
+
}
|
|
562
|
+
catch (error) {
|
|
563
|
+
const browserError = error instanceof Error ? error : new Error(String(error));
|
|
564
|
+
settleAfterClose(() => reject(browserError));
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
server.on('error', (err) => {
|
|
568
|
+
const hint = 'code' in err && err.code === 'EADDRINUSE'
|
|
569
|
+
? ` Port ${this.localPort} is in use; set SFCC_OAUTH_LOCAL_PORT or pass localPort to use a different port.`
|
|
570
|
+
: '';
|
|
571
|
+
if (!settled) {
|
|
572
|
+
settled = true;
|
|
573
|
+
reject(new Error(`Failed to start OAuth redirect server: ${err.message}.${hint}`));
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
//# sourceMappingURL=oauth-pkce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-pkce.js","sourceRoot":"","sources":["../../../src/auth/oauth-pkce.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,7 +29,8 @@ export interface ResolveAuthStrategyOptions {
|
|
|
29
29
|
/**
|
|
30
30
|
* Allowed authentication methods in priority order.
|
|
31
31
|
* The first method with available credentials will be used.
|
|
32
|
-
* Defaults to
|
|
32
|
+
* Defaults to {@link ALL_AUTH_METHODS}, where PKCE-based `user` auth is
|
|
33
|
+
* preferred over the deprecated `implicit` flow.
|
|
33
34
|
*
|
|
34
35
|
* Note: the `'jwt'` method is defined in the {@link AuthMethod} type but is
|
|
35
36
|
* not automatically resolvable here, because JWT auth requires file paths
|
|
@@ -67,7 +68,7 @@ export interface AvailableAuthMethods {
|
|
|
67
68
|
* clientSecret: 'my-secret',
|
|
68
69
|
* });
|
|
69
70
|
*
|
|
70
|
-
* console.log(result.available); // ['client-credentials', 'implicit']
|
|
71
|
+
* console.log(result.available); // ['client-credentials', 'user', 'implicit']
|
|
71
72
|
* ```
|
|
72
73
|
*/
|
|
73
74
|
export declare function checkAvailableAuthMethods(credentials: AuthCredentials, allowedMethods?: AuthMethod[]): AvailableAuthMethods;
|
|
@@ -86,7 +87,7 @@ export declare function checkAvailableAuthMethods(credentials: AuthCredentials,
|
|
|
86
87
|
* ```typescript
|
|
87
88
|
* import { resolveAuthStrategy } from '@salesforce/b2c-tooling-sdk';
|
|
88
89
|
*
|
|
89
|
-
* // Will use client-credentials if secret is available, otherwise
|
|
90
|
+
* // Will use client-credentials if secret is available, otherwise PKCE user auth
|
|
90
91
|
* const strategy = resolveAuthStrategy({
|
|
91
92
|
* clientId: 'my-client-id',
|
|
92
93
|
* clientSecret: process.env.CLIENT_SECRET, // may be undefined
|