n8n-nodes-jygse-vw-weconnect 0.1.16 → 0.2.1
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,17 +141,15 @@ class VwWeConnect {
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
exports.VwWeConnect = VwWeConnect;
|
|
144
|
-
// VW OAuth2 Configuration (Updated January 2026 - from
|
|
144
|
+
// VW OAuth2 Configuration (Updated January 2026 - from ioBroker.vw-connect)
|
|
145
145
|
const VW_CLIENT_ID = 'a24fba63-34b3-4d43-b181-942111e6bda8@apps_vw-dilab_com';
|
|
146
|
-
const VW_SCOPE = 'openid profile badge cars dealers vin';
|
|
146
|
+
const VW_SCOPE = 'openid profile badge cars dealers birthdate vin';
|
|
147
147
|
const VW_REDIRECT_URI = 'weconnect://authenticated';
|
|
148
148
|
const VW_RESPONSE_TYPE = 'code id_token token';
|
|
149
|
-
// WeConnect App
|
|
150
|
-
|
|
151
|
-
const VW_USER_AGENT = 'Volkswagen/3.51.1-android/14';
|
|
149
|
+
// WeConnect App headers (from ioBroker.vw-connect v0.7.15)
|
|
150
|
+
const VW_USER_AGENT = 'Mozilla/5.0 (Linux; Android 14; SM-G960F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36';
|
|
152
151
|
const VW_APP_PACKAGE = 'com.volkswagen.weconnect';
|
|
153
|
-
const VW_ACCEPT_LANGUAGE = '
|
|
154
|
-
const VW_NEWRELIC_ID = 'VgAEWV9QDRAEXFlRAAYPUA==';
|
|
152
|
+
const VW_ACCEPT_LANGUAGE = 'en-US,en;q=0.9';
|
|
155
153
|
function generateTraceId() {
|
|
156
154
|
// Generate UUID v4 format
|
|
157
155
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
@@ -177,37 +175,39 @@ async function generateCodeChallenge(verifier) {
|
|
|
177
175
|
}
|
|
178
176
|
async function vwLogin(context, email, password) {
|
|
179
177
|
try {
|
|
180
|
-
const traceId = generateTraceId();
|
|
181
178
|
const nonce = generateNonce();
|
|
182
|
-
|
|
183
|
-
const
|
|
179
|
+
const state = generateTraceId(); // Use UUID as state
|
|
180
|
+
const traceId = generateTraceId(); // For weconnect-trace-id header
|
|
181
|
+
const codeVerifier = generateCodeVerifier();
|
|
182
|
+
// Browser-like headers (from ioBroker.vw-connect v0.7.15)
|
|
183
|
+
const browserHeaders = {
|
|
184
184
|
'User-Agent': VW_USER_AGENT,
|
|
185
|
-
'Accept': '
|
|
185
|
+
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
|
|
186
186
|
'Accept-Language': VW_ACCEPT_LANGUAGE,
|
|
187
|
-
'
|
|
188
|
-
'
|
|
189
|
-
'
|
|
190
|
-
'Pragma': 'no-cache',
|
|
191
|
-
'x-newrelic-id': VW_NEWRELIC_ID,
|
|
192
|
-
'x-android-package-name': VW_APP_PACKAGE,
|
|
193
|
-
'weconnect-trace-id': traceId,
|
|
187
|
+
'Accept-Encoding': 'gzip, deflate, br',
|
|
188
|
+
'x-requested-with': VW_APP_PACKAGE,
|
|
189
|
+
'upgrade-insecure-requests': '1',
|
|
194
190
|
};
|
|
195
|
-
// Step 1:
|
|
196
|
-
|
|
197
|
-
const authorizeUrl = 'https://emea.bff.cariad.digital/user-login/v1/authorize';
|
|
191
|
+
// Step 1: Go directly to identity.vwgroup.io (like ioBroker adapter)
|
|
192
|
+
const authorizeUrl = 'https://identity.vwgroup.io/oidc/v1/authorize';
|
|
198
193
|
const authorizeParams = new URLSearchParams({
|
|
194
|
+
client_id: VW_CLIENT_ID,
|
|
195
|
+
scope: VW_SCOPE,
|
|
196
|
+
response_type: VW_RESPONSE_TYPE,
|
|
199
197
|
redirect_uri: VW_REDIRECT_URI,
|
|
200
198
|
nonce: nonce,
|
|
199
|
+
state: state,
|
|
201
200
|
});
|
|
202
|
-
// Use
|
|
201
|
+
// Use browser-like headers for initial request
|
|
202
|
+
// Let n8n follow redirects automatically to reach the login page
|
|
203
203
|
const authorizeResponse = await context.helpers.httpRequest({
|
|
204
204
|
method: 'GET',
|
|
205
205
|
url: `${authorizeUrl}?${authorizeParams.toString()}`,
|
|
206
|
-
headers:
|
|
206
|
+
headers: browserHeaders,
|
|
207
207
|
encoding: 'text',
|
|
208
208
|
returnFullResponse: true,
|
|
209
209
|
ignoreHttpStatusErrors: true,
|
|
210
|
-
|
|
210
|
+
// Don't skip redirects - let it follow to the login page
|
|
211
211
|
});
|
|
212
212
|
// Extract response body and check for redirect
|
|
213
213
|
let htmlContent;
|
|
@@ -243,17 +243,8 @@ async function vwLogin(context, email, password) {
|
|
|
243
243
|
}
|
|
244
244
|
// Debug: If we got an error page (status 400/500 or "Oops" in content), throw with details
|
|
245
245
|
if (httpStatusCode >= 400 || htmlContent.includes('Oops!, something went wrong')) {
|
|
246
|
-
// Include all response headers for debugging
|
|
247
|
-
let headersInfo = 'none';
|
|
248
|
-
if (authorizeResponse && typeof authorizeResponse === 'object') {
|
|
249
|
-
const respObj = authorizeResponse;
|
|
250
|
-
const respHeaders = respObj.headers;
|
|
251
|
-
if (respHeaders) {
|
|
252
|
-
headersInfo = Object.keys(respHeaders).join(', ');
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
246
|
const preview = htmlContent.substring(0, 600);
|
|
256
|
-
throw new Error(`
|
|
247
|
+
throw new Error(`VW Identity Error (HTTP ${httpStatusCode}). URL: ${authorizeUrl}. Body: ${preview}`);
|
|
257
248
|
}
|
|
258
249
|
// Follow redirects manually to capture the state parameter
|
|
259
250
|
let maxInitialRedirects = 5;
|
|
@@ -272,7 +263,7 @@ async function vwLogin(context, email, password) {
|
|
|
272
263
|
const followResponse = await context.helpers.httpRequest({
|
|
273
264
|
method: 'GET',
|
|
274
265
|
url: followUrl,
|
|
275
|
-
headers:
|
|
266
|
+
headers: browserHeaders,
|
|
276
267
|
encoding: 'text',
|
|
277
268
|
returnFullResponse: true,
|
|
278
269
|
ignoreHttpStatusErrors: true,
|
|
@@ -555,7 +546,7 @@ async function vwLogin(context, email, password) {
|
|
|
555
546
|
const followResponse = await context.helpers.httpRequest({
|
|
556
547
|
method: 'GET',
|
|
557
548
|
url: redirectUrl.startsWith('http') ? redirectUrl : `https://identity.vwgroup.io${redirectUrl}`,
|
|
558
|
-
headers:
|
|
549
|
+
headers: browserHeaders,
|
|
559
550
|
encoding: 'text',
|
|
560
551
|
returnFullResponse: true,
|
|
561
552
|
ignoreHttpStatusErrors: true,
|
package/package.json
CHANGED