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

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,11 @@ 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 v0.60.9
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';
154
+ const VW_NEWRELIC_ID = 'VgAEWV9QDRAEXFlRAAYPUA==';
152
155
  function generateTraceId() {
153
156
  // Generate UUID v4 format
154
157
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
@@ -174,32 +177,32 @@ async function generateCodeChallenge(verifier) {
174
177
  }
175
178
  async function vwLogin(context, email, password) {
176
179
  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)
180
+ const traceId = generateTraceId();
181
+ const nonce = generateNonce();
182
+ // Common headers used for all requests (matching WeConnect-python v0.60.9 exactly)
183
+ const commonHeaders = {
184
+ 'User-Agent': VW_USER_AGENT,
185
+ 'Accept': '*/*',
186
+ 'Accept-Language': VW_ACCEPT_LANGUAGE,
187
+ 'Content-Type': 'application/json',
188
+ 'content-version': '1',
189
+ 'Cache-Control': 'no-cache',
190
+ 'Pragma': 'no-cache',
191
+ 'x-newrelic-id': VW_NEWRELIC_ID,
192
+ 'x-android-package-name': VW_APP_PACKAGE,
193
+ 'weconnect-trace-id': traceId,
194
+ };
195
+ // Step 1: Get authorization page via CARIAD BFF
196
+ // WeConnect-python only sends redirect_uri and nonce to this endpoint
182
197
  const authorizeUrl = 'https://emea.bff.cariad.digital/user-login/v1/authorize';
183
198
  const authorizeParams = new URLSearchParams({
184
- client_id: VW_CLIENT_ID,
185
- scope: VW_SCOPE,
186
- response_type: VW_RESPONSE_TYPE,
187
199
  redirect_uri: VW_REDIRECT_URI,
188
- nonce: generateNonce(),
189
- state: stateParam,
190
- code_challenge: codeChallenge,
191
- code_challenge_method: 'plain',
200
+ nonce: nonce,
192
201
  });
193
- const traceId = generateTraceId();
194
202
  const authorizeResponse = await context.helpers.httpRequest({
195
203
  method: 'GET',
196
204
  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
- },
205
+ headers: commonHeaders,
203
206
  encoding: 'text',
204
207
  returnFullResponse: true,
205
208
  ignoreHttpStatusErrors: true,
@@ -252,10 +255,7 @@ async function vwLogin(context, email, password) {
252
255
  const followResponse = await context.helpers.httpRequest({
253
256
  method: 'GET',
254
257
  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
- },
258
+ headers: commonHeaders,
259
259
  encoding: 'text',
260
260
  returnFullResponse: true,
261
261
  ignoreHttpStatusErrors: true,
@@ -458,8 +458,7 @@ async function vwLogin(context, email, password) {
458
458
  method: 'POST',
459
459
  url: `https://identity.vwgroup.io/u/login?state=${encodeURIComponent(stateToken)}`,
460
460
  headers: {
461
- 'User-Agent': VW_USER_AGENT,
462
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
461
+ ...commonHeaders,
463
462
  'Content-Type': 'application/x-www-form-urlencoded',
464
463
  'Origin': 'https://identity.vwgroup.io',
465
464
  'Referer': `https://identity.vwgroup.io/u/login?state=${encodeURIComponent(stateToken)}`,
@@ -537,9 +536,7 @@ async function vwLogin(context, email, password) {
537
536
  const followResponse = await context.helpers.httpRequest({
538
537
  method: 'GET',
539
538
  url: redirectUrl.startsWith('http') ? redirectUrl : `https://identity.vwgroup.io${redirectUrl}`,
540
- headers: {
541
- 'User-Agent': VW_USER_AGENT,
542
- },
539
+ headers: commonHeaders,
543
540
  encoding: 'text',
544
541
  returnFullResponse: true,
545
542
  ignoreHttpStatusErrors: true,
@@ -572,10 +569,10 @@ async function vwLogin(context, email, password) {
572
569
  maxRedirects--;
573
570
  }
574
571
  if (!authCode) {
575
- throw new Error(`Could not obtain authorization code. Last redirect: ${redirectUrl || 'none'}. Please check your credentials.`);
572
+ throw new Error(`Could not obtain authorization code. Last redirect: ${redirectUrl || 'none'}. Auth HTML preview: ${authHtml.substring(0, 500)}`);
576
573
  }
577
- // Step 4: Exchange auth code for tokens
578
- // Try the new CARIAD login endpoint first
574
+ // Step 4: Exchange auth code for tokens via CARIAD login endpoint
575
+ // The state parameter should come from the authorize response, not our generated one
579
576
  let tokenResponse;
580
577
  try {
581
578
  const cariadResponse = await context.helpers.httpRequest({
@@ -584,16 +581,18 @@ async function vwLogin(context, email, password) {
584
581
  headers: {
585
582
  'User-Agent': VW_USER_AGENT,
586
583
  'Accept': 'application/json',
584
+ 'Accept-Language': VW_ACCEPT_LANGUAGE,
587
585
  'Content-Type': 'application/json',
586
+ 'x-android-package-name': VW_APP_PACKAGE,
587
+ 'weconnect-trace-id': traceId,
588
588
  },
589
589
  body: {
590
- state: authorizeParams.get('state'),
590
+ state: stateToken,
591
591
  id_token: idToken,
592
592
  redirect_uri: VW_REDIRECT_URI,
593
593
  region: 'emea',
594
594
  access_token: accessToken,
595
595
  authorizationCode: authCode,
596
- code_verifier: codeVerifier,
597
596
  },
598
597
  });
599
598
  tokenResponse = cariadResponse;
@@ -606,6 +605,7 @@ async function vwLogin(context, email, password) {
606
605
  headers: {
607
606
  'User-Agent': VW_USER_AGENT,
608
607
  'Accept': 'application/json',
608
+ 'Accept-Language': VW_ACCEPT_LANGUAGE,
609
609
  'Content-Type': 'application/json',
610
610
  'X-Client-Id': VW_CLIENT_ID,
611
611
  },
@@ -613,7 +613,6 @@ async function vwLogin(context, email, password) {
613
613
  auth_code: authCode,
614
614
  id_token: idToken || '',
615
615
  brand: 'vw',
616
- code_verifier: codeVerifier,
617
616
  },
618
617
  });
619
618
  }
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.12",
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",