n8n-nodes-jygse-vw-weconnect 0.1.10 → 0.1.11

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.
@@ -147,8 +147,10 @@ const VW_SCOPE = 'openid profile badge cars dealers vin';
147
147
  const VW_REDIRECT_URI = 'weconnect://authenticated';
148
148
  const VW_RESPONSE_TYPE = 'code id_token token';
149
149
  // WeConnect App User-Agent and headers (critical for authentication)
150
- const VW_USER_AGENT = 'Volkswagen/3.60.0-android/14';
150
+ // Using exact version from WeConnect-python
151
+ const VW_USER_AGENT = 'Volkswagen/3.51.1-android/14';
151
152
  const VW_APP_PACKAGE = 'com.volkswagen.weconnect';
153
+ const VW_ACCEPT_LANGUAGE = 'de-de';
152
154
  function generateTraceId() {
153
155
  // Generate UUID v4 format
154
156
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
@@ -174,32 +176,28 @@ async function generateCodeChallenge(verifier) {
174
176
  }
175
177
  async function vwLogin(context, email, password) {
176
178
  try {
177
- // Generate PKCE values
178
- const codeVerifier = generateCodeVerifier();
179
- const codeChallenge = await generateCodeChallenge(codeVerifier);
180
- const stateParam = generateNonce();
181
- // Step 1: Get authorization page via CARIAD BFF (WeConnect-python approach)
179
+ const traceId = generateTraceId();
180
+ const nonce = generateNonce();
181
+ // Common headers used for all requests (matching WeConnect-python exactly)
182
+ const commonHeaders = {
183
+ 'User-Agent': VW_USER_AGENT,
184
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
185
+ 'Accept-Language': VW_ACCEPT_LANGUAGE,
186
+ 'Cache-Control': 'no-cache',
187
+ 'x-android-package-name': VW_APP_PACKAGE,
188
+ 'weconnect-trace-id': traceId,
189
+ };
190
+ // Step 1: Get authorization page via CARIAD BFF
191
+ // WeConnect-python only sends redirect_uri and nonce to this endpoint
182
192
  const authorizeUrl = 'https://emea.bff.cariad.digital/user-login/v1/authorize';
183
193
  const authorizeParams = new URLSearchParams({
184
- client_id: VW_CLIENT_ID,
185
- scope: VW_SCOPE,
186
- response_type: VW_RESPONSE_TYPE,
187
194
  redirect_uri: VW_REDIRECT_URI,
188
- nonce: generateNonce(),
189
- state: stateParam,
190
- code_challenge: codeChallenge,
191
- code_challenge_method: 'plain',
195
+ nonce: nonce,
192
196
  });
193
- const traceId = generateTraceId();
194
197
  const authorizeResponse = await context.helpers.httpRequest({
195
198
  method: 'GET',
196
199
  url: `${authorizeUrl}?${authorizeParams.toString()}`,
197
- headers: {
198
- 'User-Agent': VW_USER_AGENT,
199
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
200
- 'x-android-package-name': VW_APP_PACKAGE,
201
- 'weconnect-trace-id': traceId,
202
- },
200
+ headers: commonHeaders,
203
201
  encoding: 'text',
204
202
  returnFullResponse: true,
205
203
  ignoreHttpStatusErrors: true,
@@ -252,10 +250,7 @@ async function vwLogin(context, email, password) {
252
250
  const followResponse = await context.helpers.httpRequest({
253
251
  method: 'GET',
254
252
  url: followUrl,
255
- headers: {
256
- 'User-Agent': VW_USER_AGENT,
257
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
258
- },
253
+ headers: commonHeaders,
259
254
  encoding: 'text',
260
255
  returnFullResponse: true,
261
256
  ignoreHttpStatusErrors: true,
@@ -458,8 +453,7 @@ async function vwLogin(context, email, password) {
458
453
  method: 'POST',
459
454
  url: `https://identity.vwgroup.io/u/login?state=${encodeURIComponent(stateToken)}`,
460
455
  headers: {
461
- 'User-Agent': VW_USER_AGENT,
462
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
456
+ ...commonHeaders,
463
457
  'Content-Type': 'application/x-www-form-urlencoded',
464
458
  'Origin': 'https://identity.vwgroup.io',
465
459
  'Referer': `https://identity.vwgroup.io/u/login?state=${encodeURIComponent(stateToken)}`,
@@ -537,9 +531,7 @@ async function vwLogin(context, email, password) {
537
531
  const followResponse = await context.helpers.httpRequest({
538
532
  method: 'GET',
539
533
  url: redirectUrl.startsWith('http') ? redirectUrl : `https://identity.vwgroup.io${redirectUrl}`,
540
- headers: {
541
- 'User-Agent': VW_USER_AGENT,
542
- },
534
+ headers: commonHeaders,
543
535
  encoding: 'text',
544
536
  returnFullResponse: true,
545
537
  ignoreHttpStatusErrors: true,
@@ -572,10 +564,10 @@ async function vwLogin(context, email, password) {
572
564
  maxRedirects--;
573
565
  }
574
566
  if (!authCode) {
575
- throw new Error(`Could not obtain authorization code. Last redirect: ${redirectUrl || 'none'}. Please check your credentials.`);
567
+ throw new Error(`Could not obtain authorization code. Last redirect: ${redirectUrl || 'none'}. Auth HTML preview: ${authHtml.substring(0, 500)}`);
576
568
  }
577
- // Step 4: Exchange auth code for tokens
578
- // Try the new CARIAD login endpoint first
569
+ // Step 4: Exchange auth code for tokens via CARIAD login endpoint
570
+ // The state parameter should come from the authorize response, not our generated one
579
571
  let tokenResponse;
580
572
  try {
581
573
  const cariadResponse = await context.helpers.httpRequest({
@@ -584,16 +576,18 @@ async function vwLogin(context, email, password) {
584
576
  headers: {
585
577
  'User-Agent': VW_USER_AGENT,
586
578
  'Accept': 'application/json',
579
+ 'Accept-Language': VW_ACCEPT_LANGUAGE,
587
580
  'Content-Type': 'application/json',
581
+ 'x-android-package-name': VW_APP_PACKAGE,
582
+ 'weconnect-trace-id': traceId,
588
583
  },
589
584
  body: {
590
- state: authorizeParams.get('state'),
585
+ state: stateToken,
591
586
  id_token: idToken,
592
587
  redirect_uri: VW_REDIRECT_URI,
593
588
  region: 'emea',
594
589
  access_token: accessToken,
595
590
  authorizationCode: authCode,
596
- code_verifier: codeVerifier,
597
591
  },
598
592
  });
599
593
  tokenResponse = cariadResponse;
@@ -606,6 +600,7 @@ async function vwLogin(context, email, password) {
606
600
  headers: {
607
601
  'User-Agent': VW_USER_AGENT,
608
602
  'Accept': 'application/json',
603
+ 'Accept-Language': VW_ACCEPT_LANGUAGE,
609
604
  'Content-Type': 'application/json',
610
605
  'X-Client-Id': VW_CLIENT_ID,
611
606
  },
@@ -613,7 +608,6 @@ async function vwLogin(context, email, password) {
613
608
  auth_code: authCode,
614
609
  id_token: idToken || '',
615
610
  brand: 'vw',
616
- code_verifier: codeVerifier,
617
611
  },
618
612
  });
619
613
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-jygse-vw-weconnect",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "n8n community node for VW We Connect - Control your Volkswagen T6.1 and other VW vehicles",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",