n8n-nodes-jygse-vw-weconnect 0.1.2 → 0.1.3
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.
|
@@ -141,21 +141,42 @@ class VwWeConnect {
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
exports.VwWeConnect = VwWeConnect;
|
|
144
|
-
// VW OAuth2 Configuration
|
|
145
|
-
const VW_CLIENT_ID = '
|
|
146
|
-
const VW_SCOPE = 'openid profile
|
|
144
|
+
// VW OAuth2 Configuration (Updated January 2026)
|
|
145
|
+
const VW_CLIENT_ID = 'a24fba63-34b3-4d43-b181-942111e6bda8@apps_vw-dilab_com';
|
|
146
|
+
const VW_SCOPE = 'openid profile badge cars dealers birthdate vin';
|
|
147
147
|
const VW_REDIRECT_URI = 'weconnect://authenticated';
|
|
148
|
+
const VW_RESPONSE_TYPE = 'code id_token token';
|
|
149
|
+
// Generate PKCE code verifier and challenge
|
|
150
|
+
function generateCodeVerifier() {
|
|
151
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
|
|
152
|
+
let result = '';
|
|
153
|
+
for (let i = 0; i < 64; i++) {
|
|
154
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
155
|
+
}
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
async function generateCodeChallenge(verifier) {
|
|
159
|
+
// Simple base64url encoding of SHA256 hash
|
|
160
|
+
// Since we can't use crypto directly, we'll use a simplified approach
|
|
161
|
+
// For now, use plain verifier (S256 would be better but requires crypto)
|
|
162
|
+
return verifier;
|
|
163
|
+
}
|
|
148
164
|
async function vwLogin(context, email, password) {
|
|
149
165
|
try {
|
|
166
|
+
// Generate PKCE values
|
|
167
|
+
const codeVerifier = generateCodeVerifier();
|
|
168
|
+
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
150
169
|
// Step 1: Get authorization page and extract form data
|
|
151
170
|
const authorizeUrl = 'https://identity.vwgroup.io/oidc/v1/authorize';
|
|
152
171
|
const authorizeParams = new URLSearchParams({
|
|
153
172
|
client_id: VW_CLIENT_ID,
|
|
154
173
|
scope: VW_SCOPE,
|
|
155
|
-
response_type:
|
|
174
|
+
response_type: VW_RESPONSE_TYPE,
|
|
156
175
|
redirect_uri: VW_REDIRECT_URI,
|
|
157
176
|
nonce: generateNonce(),
|
|
158
177
|
state: generateNonce(),
|
|
178
|
+
code_challenge: codeChallenge,
|
|
179
|
+
code_challenge_method: 'plain',
|
|
159
180
|
});
|
|
160
181
|
const authorizeResponse = await context.helpers.httpRequest({
|
|
161
182
|
method: 'GET',
|
|
@@ -280,17 +301,35 @@ async function vwLogin(context, email, password) {
|
|
|
280
301
|
redirectUrl = redirectMatch[1];
|
|
281
302
|
}
|
|
282
303
|
}
|
|
283
|
-
// Follow redirects to get the auth code
|
|
304
|
+
// Follow redirects to get the auth code, id_token, and access_token
|
|
284
305
|
let authCode = '';
|
|
306
|
+
let idToken = '';
|
|
307
|
+
let accessToken = '';
|
|
285
308
|
let maxRedirects = 10;
|
|
286
309
|
while (maxRedirects > 0 && redirectUrl && !authCode) {
|
|
310
|
+
// Extract tokens from URL fragment or query params
|
|
311
|
+
// The response_type 'code id_token token' returns all three
|
|
287
312
|
if (redirectUrl.includes('code=')) {
|
|
288
|
-
const codeMatch = redirectUrl.match(/code=([
|
|
313
|
+
const codeMatch = redirectUrl.match(/code=([^&#]+)/);
|
|
289
314
|
if (codeMatch) {
|
|
290
315
|
authCode = codeMatch[1];
|
|
291
|
-
break;
|
|
292
316
|
}
|
|
293
317
|
}
|
|
318
|
+
if (redirectUrl.includes('id_token=')) {
|
|
319
|
+
const idTokenMatch = redirectUrl.match(/id_token=([^&#]+)/);
|
|
320
|
+
if (idTokenMatch) {
|
|
321
|
+
idToken = idTokenMatch[1];
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (redirectUrl.includes('access_token=')) {
|
|
325
|
+
const accessTokenMatch = redirectUrl.match(/access_token=([^&#]+)/);
|
|
326
|
+
if (accessTokenMatch) {
|
|
327
|
+
accessToken = accessTokenMatch[1];
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
if (authCode) {
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
294
333
|
const followResponse = await context.helpers.httpRequest({
|
|
295
334
|
method: 'GET',
|
|
296
335
|
url: redirectUrl.startsWith('http') ? redirectUrl : `https://identity.vwgroup.io${redirectUrl}`,
|
|
@@ -320,21 +359,48 @@ async function vwLogin(context, email, password) {
|
|
|
320
359
|
throw new Error('Could not obtain authorization code. Please check your credentials.');
|
|
321
360
|
}
|
|
322
361
|
// Step 4: Exchange auth code for tokens
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
362
|
+
// Try the new CARIAD login endpoint first
|
|
363
|
+
let tokenResponse;
|
|
364
|
+
try {
|
|
365
|
+
const cariadResponse = await context.helpers.httpRequest({
|
|
366
|
+
method: 'POST',
|
|
367
|
+
url: 'https://emea.bff.cariad.digital/user-login/login/v1',
|
|
368
|
+
headers: {
|
|
369
|
+
'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36',
|
|
370
|
+
'Accept': 'application/json',
|
|
371
|
+
'Content-Type': 'application/json',
|
|
372
|
+
},
|
|
373
|
+
body: {
|
|
374
|
+
state: authorizeParams.get('state'),
|
|
375
|
+
id_token: idToken,
|
|
376
|
+
redirect_uri: VW_REDIRECT_URI,
|
|
377
|
+
region: 'emea',
|
|
378
|
+
access_token: accessToken,
|
|
379
|
+
authorizationCode: authCode,
|
|
380
|
+
code_verifier: codeVerifier,
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
tokenResponse = cariadResponse;
|
|
384
|
+
}
|
|
385
|
+
catch {
|
|
386
|
+
// Fallback to old token exchange endpoint
|
|
387
|
+
tokenResponse = await context.helpers.httpRequest({
|
|
388
|
+
method: 'POST',
|
|
389
|
+
url: 'https://tokenrefreshservice.apps.emea.vwapps.io/exchangeAuthCode',
|
|
390
|
+
headers: {
|
|
391
|
+
'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36',
|
|
392
|
+
'Accept': 'application/json',
|
|
393
|
+
'Content-Type': 'application/json',
|
|
394
|
+
'X-Client-Id': VW_CLIENT_ID,
|
|
395
|
+
},
|
|
396
|
+
body: {
|
|
397
|
+
auth_code: authCode,
|
|
398
|
+
id_token: idToken || '',
|
|
399
|
+
brand: 'vw',
|
|
400
|
+
code_verifier: codeVerifier,
|
|
401
|
+
},
|
|
402
|
+
});
|
|
403
|
+
}
|
|
338
404
|
return {
|
|
339
405
|
accessToken: tokenResponse.access_token,
|
|
340
406
|
refreshToken: tokenResponse.refresh_token,
|
package/package.json
CHANGED