UNPKG

iobroker.vw-connect

Version:
926 lines (900 loc) 213 kB
// @ts-nocheck "use strict"; /* * Created with @iobroker/create-adapter v1.17.0 */ // The adapter-core module gives you access to the core ioBroker functions // you need to create an adapter const utils = require("@iobroker/adapter-core"); const request = require("request"); const crypto = require("crypto"); const { Crypto } = require("@peculiar/webcrypto"); const { v4: uuidv4 } = require("uuid"); const traverse = require("traverse"); const geohash = require("ngeohash"); const { extractKeys } = require("./lib/extractKeys"); class VwWeconnect extends utils.Adapter { /** * @param {Partial<ioBroker.AdapterOptions>} [options={}] */ constructor(options) { super({ ...options, name: "vw-connect", }); this.on("ready", this.onReady.bind(this)); // this.on("objectChange", this.onObjectChange.bind(this)); this.on("stateChange", this.onStateChange.bind(this)); // this.on("message", this.onMessage.bind(this)); this.on("unload", this.onUnload.bind(this)); this.extractKeys = extractKeys; this.jar = request.jar(); this.userAgent = "ioBroker v46"; this.refreshTokenInterval = null; this.vwrefreshTokenInterval = null; this.updateInterval = null; this.fupdateInterval = null; this.refreshTokenTimeout = null; this.homeRegion = {}; this.homeRegionSetter = {}; this.vinArray = []; this.etags = {}; this.statesArray = [ { url: "$homeregion/fs-car/bs/departuretimer/v1/$type/$country/vehicles/$vin/timer", path: "timer", element: "timer", }, { url: "$homeregion/fs-car/bs/climatisation/v1/$type/$country/vehicles/$vin/climater", path: "climater", element: "climater", }, { url: "$homeregion/fs-car/bs/cf/v1/$type/$country/vehicles/$vin/position", path: "position", element: "storedPositionResponse", element2: "position", element3: "findCarResponse", element4: "Position", }, { url: "$homeregion/fs-car/bs/tripstatistics/v1/$type/$country/vehicles/$vin/tripdata/$tripType?type=list", path: "tripdata", element: "tripDataList", }, { url: "$homeregion/fs-car/bs/vsr/v1/$type/$country/vehicles/$vin/status", path: "status", element: "StoredVehicleDataResponse", element2: "vehicleData", }, { url: "$homeregion/fs-car/destinationfeedservice/mydestinations/v1/$type/$country/vehicles/$vin/destinations", path: "destinations", element: "destinations", }, { url: "$homeregion/fs-car/bs/batterycharge/v1/$type/$country/vehicles/$vin/charger", path: "charger", element: "charger", }, { url: "$homeregion/fs-car/bs/rs/v1/$type/$country/vehicles/$vin/status", path: "remoteStandheizung", element: "statusResponse", }, { url: "$homeregion/fs-car/bs/dwap/v1/$type/$country/vehicles/$vin/history", path: "history", }, ]; } /** * Is called when databases are connected and adapter received configuration. */ async onReady() { // Initialize your adapter here this.setState("info.connection", false, true); // Reset the connection indicator during startup this.type = "VW"; this.country = "DE"; this.clientId = "9496332b-ea03-4091-a224-8c746b885068%40apps_vw-dilab_com"; this.xclientId = "38761134-34d0-41f3-9a73-c4be88d7d337"; this.scope = "openid%20profile%20mbb%20email%20cars%20birthdate%20badge%20address%20vin"; this.redirect = "carnet%3A%2F%2Fidentity-kit%2Flogin"; this.xrequest = "de.volkswagen.carnet.eu.eremote"; this.responseType = "id_token%20token%20code"; this.xappversion = "5.1.2"; this.xappname = "eRemote"; if (this.config.type === "id") { this.type = "Id"; this.country = "DE"; this.clientId = "a24fba63-34b3-4d43-b181-942111e6bda8@apps_vw-dilab_com"; this.xclientId = ""; this.scope = "openid profile badge cars dealers birthdate vin"; this.redirect = "weconnect://authenticated"; this.xrequest = "com.volkswagen.weconnect"; this.responseType = "code id_token token"; this.xappversion = ""; this.xappname = ""; } if (this.config.type === "skoda") { this.type = "Skoda"; this.country = "CZ"; this.clientId = "f9a2359a-b776-46d9-bd0c-db1904343117@apps_vw-dilab_com"; this.xclientId = "afb0473b-6d82-42b8-bfea-cead338c46ef"; this.scope = "openid mbb profile"; this.redirect = "skodaconnect://oidc.login/"; this.xrequest = "cz.skodaauto.connect"; this.responseType = "code%20id_token"; this.xappversion = "3.2.6"; this.xappname = "cz.skodaauto.connect"; } if (this.config.type === "skodae") { this.type = "Skoda"; this.country = "CZ"; this.clientId = "f9a2359a-b776-46d9-bd0c-db1904343117@apps_vw-dilab_com"; this.xclientId = "afb0473b-6d82-42b8-bfea-cead338c46ef"; this.scope = "openid mbb profile"; this.redirect = "skodaconnect://oidc.login/"; this.xrequest = "cz.skodaauto.connect"; this.responseType = "code%20id_token"; this.xappversion = "3.2.6"; this.xappname = "cz.skodaauto.connect"; } if (this.config.type === "seat") { this.type = "Seat"; this.country = "ES"; this.clientId = "50f215ac-4444-4230-9fb1-fe15cd1a9bcc@apps_vw-dilab_com"; this.xclientId = "9dcc70f0-8e79-423a-a3fa-4065d99088b4"; this.scope = "openid profile mbb cars birthdate nickname address phone"; this.redirect = "seatconnect://identity-kit/login"; this.xrequest = "cz.skodaauto.connect"; this.responseType = "code%20id_token"; this.xappversion = "1.1.29"; this.xappname = "SEATConnect"; } if (this.config.type === "vwv2") { this.type = "VW"; this.country = "DE"; this.clientId = "9496332b-ea03-4091-a224-8c746b885068@apps_vw-dilab_com"; this.xclientId = "89312f5d-b853-4965-a471-b0859ee468af"; this.scope = "openid profile mbb cars birthdate nickname address phone"; this.redirect = "carnet://identity-kit/login"; this.xrequest = "de.volkswagen.car-net.eu.e-remote"; this.responseType = "id_token%20token%20code"; this.xappversion = "5.6.7"; this.xappname = "We Connect"; } if (this.config.type === "audi") { this.type = "Audi"; this.country = "DE"; this.clientId = "09b6cbec-cd19-4589-82fd-363dfa8c24da@apps_vw-dilab_com"; this.xclientId = "77869e21-e30a-4a92-b016-48ab7d3db1d8"; this.scope = "address profile badge birthdate birthplace nationalIdentifier nationality profession email vin phone nickname name picture mbb gallery openid"; this.redirect = "myaudi:///"; this.xrequest = "de.myaudi.mobile.assistant"; this.responseType = "token%20id_token"; // this.responseType = "code"; this.xappversion = "3.22.0"; this.xappname = "myAudi"; } if (this.config.type === "audidata") { this.type = "Audi"; this.country = "DE"; this.clientId = "ec6198b1-b31e-41ec-9a69-95d42d6497ed@apps_vw-dilab_com"; this.scope = "openid profile address email phone"; this.redirect = "acpp://de.audi.connectplugandplay/oauth2redirect/identitykit"; this.responseType = "code"; } if (this.config.type === "go") { this.type = ""; this.country = ""; this.clientId = "ac42b0fa-3b11-48a0-a941-43a399e7ef84@apps_vw-dilab_com"; this.xclientId = ""; this.scope = "openid%20profile%20address%20email%20phone"; this.redirect = "vwconnect%3A%2F%2Fde.volkswagen.vwconnect%2Foauth2redirect%2Fidentitykit"; this.xrequest = ""; this.responseType = "code"; this.xappversion = ""; this.xappname = ""; } if (this.config.type === "seatelli") { this.type = ""; this.country = ""; this.clientId = "d940d794-5945-48a3-84b1-44222c387800@apps_vw-dilab_com"; this.xclientId = ""; this.scope = "openid profile"; this.redirect = "Seat-elli-hub://opid"; this.xrequest = ""; this.responseType = "code"; this.xappversion = ""; this.xappname = ""; } if (this.config.type === "skodapower") { this.type = ""; this.country = ""; this.clientId = "b84ba8a1-7925-43c9-9963-022587faaac5@apps_vw-dilab_com"; this.xclientId = ""; this.scope = "openid profile"; this.redirect = "skoda-hub://opid"; this.xrequest = ""; this.responseType = "code"; this.xappversion = ""; this.xappname = ""; } if (this.config.interval === 0) { this.log.info("Interval of 0 is not allowed reset to 1"); this.config.interval = 1; } this.tripTypes = []; if (this.config.tripShortTerm == true) { this.tripTypes.push("shortTerm"); } if (this.config.tripLongTerm == true) { this.tripTypes.push("longTerm"); } if (this.config.tripCyclic == true) { this.tripTypes.push("cyclic"); } this.login() .then(() => { this.log.debug("Login successful"); this.setState("info.connection", true, true); this.setObjectNotExists("refresh", { type: "state", common: { name: "Refresh All States", type: "boolean", role: "boolean", write: true, }, native: {}, }); this.getPersonalData() .then(() => { this.getVehicles() .then(() => { if (this.config.type !== "go") { this.vinArray.forEach((vin) => { if (this.config.type === "id") { this.getIdStatus(vin).catch(() => { this.log.error("get id status Failed"); }); } else if (this.config.type === "audidata") { this.getAudiDataStatus(vin).catch(() => { this.log.error("get audi data status Failed"); }); } else if (this.config.type === "skodae") { this.clientId = "7f045eee-7003-4379-9968-9355ed2adb06%40apps_vw-dilab_com"; this.scope = "openid dealers profile email cars address"; this.redirect = "skodaconnect://oidc.login/"; this.login() .then(() => { this.getSkodaEStatus(vin).catch(() => { this.log.error("get skodae status Failed"); }); }) .catch(() => { this.log.error("Failed second skoda login"); }); } else { this.getHomeRegion(vin) .catch(() => { this.log.debug("get home region Failed " + vin); }) .finally(() => { this.getVehicleData(vin).catch(() => { this.log.error("get vehicle data Failed"); }); this.getVehicleRights(vin).catch(() => { this.log.error("get vehicle rights Failed"); }); this.requestStatusUpdate(vin) .finally(() => { this.statesArray.forEach((state) => { if (state.path == "tripdata") { this.tripTypes.forEach((tripType) => { this.getVehicleStatus( vin, state.url, state.path, state.element, state.element2, state.element3, state.element4, tripType ).catch(() => { this.log.debug("error while getting " + state.url); }); }); } else { this.getVehicleStatus(vin, state.url, state.path, state.element, state.element2, state.element3, state.element4).catch(() => { this.log.debug("error while getting " + state.url); }); } }); }) .catch(() => { this.log.error("status update Failed " + vin); }); }) .catch(() => { this.log.error("Error getting home region"); }); } }); } this.updateInterval = setInterval(() => { this.updateStatus(); }, this.config.interval * 60 * 1000); if (this.config.type !== "id" && this.config.type !== "skodae") { if (this.config.forceinterval > 0) { this.fupdateInterval = setInterval(() => { if (this.config.type === "go") { this.getVehicles(); return; } this.vinArray.forEach((vin) => { this.requestStatusUpdate(vin).catch(() => { this.log.error("force status update Failed"); }); }); }, this.config.forceinterval * 60 * 1000); } } if (this.config.type === "seatelli" || this.config.type === "skodapower") { this.getElliData(this.config.type).catch(() => { this.log.error("get elli Failed"); }); } }) .catch(() => { this.log.error("Get Vehicles Failed"); }); }) .catch(() => { this.log.error("get personal data Failed"); }); }) .catch(() => { this.log.error("Login Failed"); }); this.subscribeStates("*"); } login() { return new Promise(async (resolve, reject) => { const nonce = this.getNonce(); const state = uuidv4(); let [code_verifier, codeChallenge] = this.getCodeChallenge(); if (this.config.type === "seatelli" || this.config.type === "skodapower") { [code_verifier, codeChallenge] = this.getCodeChallengev2(); } const method = "GET"; const form = {}; let url = "https://identity.vwgroup.io/oidc/v1/authorize?client_id=" + this.clientId + "&scope=" + this.scope + "&response_type=" + this.responseType + "&redirect_uri=" + this.redirect + "&nonce=" + nonce + "&state=" + state; if ( this.config.type === "vw" || this.config.type === "vwv2" || this.config.type === "go" || this.config.type === "seatelli" || this.config.type === "skodapower" || this.config.type === "audidata" ) { url += "&code_challenge=" + codeChallenge + "&code_challenge_method=S256"; } if (this.config.type === "audi") { url += "&ui_locales=de-DE%20de&prompt=login"; } if (this.config.type === "id" && this.type !== "Wc") { url = await this.receiveLoginUrl().catch(() => { this.log.warn("Failed to get login url"); }); if (!url) { url = "https://login.apps.emea.vwapps.io/authorize?nonce=" + this.randomString(16) + "&redirect_uri=weconnect://authenticated"; } } const loginRequest = request( { method: method, url: url, headers: { "User-Agent": this.userAgent, Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "Accept-Language": "en-US,en;q=0.9", "Accept-Encoding": "gzip, deflate", "x-requested-with": this.xrequest, "upgrade-insecure-requests": 1, }, jar: this.jar, form: form, gzip: true, followAllRedirects: true, }, (err, resp, body) => { if (err || (resp && resp.statusCode >= 400)) { if (this.type === "Wc") { if (err && err.message === "Invalid protocol: wecharge:") { this.log.debug("Found WeCharge connection"); this.getTokens(loginRequest, code_verifier, reject, resolve); } else { this.log.debug("No WeCharge found, cancel login"); resolve(); } return; } if (err && err.message.indexOf("Invalid protocol:") !== -1) { this.log.debug("Found Token"); this.getTokens(loginRequest, code_verifier, reject, resolve); return; } this.log.error("Failed in first login step "); err && this.log.error(err); resp && this.log.error(resp.statusCode.toString()); body && this.log.error(JSON.stringify(body)); err && err.message && this.log.error(err.message); loginRequest && loginRequest.uri && loginRequest.uri.query && this.log.debug(loginRequest.uri.query.toString()); reject(); return; } try { let form = {}; if (body.indexOf("emailPasswordForm") !== -1) { this.log.debug("parseEmailForm"); form = this.extractHidden(body); form["email"] = this.config.user; } else { this.log.error("No Login Form found for type: " + this.type); this.log.debug(JSON.stringify(body)); reject(); return; } request.post( { url: "https://identity.vwgroup.io/signin-service/v1/" + this.clientId + "/login/identifier", headers: { "Content-Type": "application/x-www-form-urlencoded", "User-Agent": this.userAgent, Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "Accept-Language": "en-US,en;q=0.9", "Accept-Encoding": "gzip, deflate", "x-requested-with": this.xrequest, }, form: form, jar: this.jar, gzip: true, followAllRedirects: true, }, (err, resp, body) => { if (err || (resp && resp.statusCode >= 400)) { this.log.error("Failed to get login identifier"); err && this.log.error(err); resp && this.log.error(resp.statusCode.toString()); body && this.log.error(JSON.stringify(body)); reject(); return; } try { if (body.indexOf("credentialsForm") !== -1) { this.log.debug("credentialsForm"); form = this.extractHidden(body); form["password"] = this.config.password; } else { this.log.error("No Login Form found. Please check your E-Mail in the app."); this.log.debug(JSON.stringify(body)); reject(); return; } request.post( { url: "https://identity.vwgroup.io/signin-service/v1/" + this.clientId + "/login/authenticate", headers: { "Content-Type": "application/x-www-form-urlencoded", "User-Agent": this.userAgent, Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "Accept-Language": "en-US,en;q=0.9", "Accept-Encoding": "gzip, deflate", "x-requested-with": this.xrequest, }, form: form, jar: this.jar, gzip: true, followAllRedirects: false, }, (err, resp, body) => { if (err || (resp && resp.statusCode >= 400)) { this.log.error("Failed to get login authenticate"); err && this.log.error(err); resp && this.log.error(resp.statusCode.toString()); body && this.log.error(JSON.stringify(body)); reject(); return; } try { this.log.debug(JSON.stringify(body)); this.log.debug(JSON.stringify(resp.headers)); if (resp.headers.location.split("&").length <= 2 || resp.headers.location.indexOf("/terms-and-conditions?") !== -1) { this.log.warn(resp.headers.location); this.log.warn("No valid userid, please visit this link or logout and login in your app account:"); this.log.warn("https://" + resp.request.host + resp.headers.location); this.log.warn("Try to auto accept new consent"); request.get( { url: "https://" + resp.request.host + resp.headers.location, jar: this.jar, headers: { "User-Agent": this.userAgent, Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "Accept-Language": "en-US,en;q=0.9", "Accept-Encoding": "gzip, deflate", "x-requested-with": this.xrequest, }, followAllRedirects: true, gzip: true, }, (err, resp, body) => { this.log.debug(body); const form = this.extractHidden(body); const url = "https://" + resp.request.host + resp.req.path.split("?")[0]; this.log.debug(JSON.stringify(form)); request.post( { url: url, jar: this.jar, headers: { "Content-Type": "application/x-www-form-urlencoded", "User-Agent": this.userAgent, Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "Accept-Language": "en-US,en;q=0.9", "Accept-Encoding": "gzip, deflate", "x-requested-with": this.xrequest, }, form: form, followAllRedirects: true, gzip: true, }, (err, resp, body) => { if ((err && err.message.indexOf("Invalid protocol:") !== -1) || (resp && resp.statusCode >= 400)) { this.log.warn("Failed to auto accept"); err && this.log.error(err); resp && this.log.error(resp.statusCode.toString()); body && this.log.error(JSON.stringify(body)); reject(); return; } this.log.info("Auto accept succesful. Restart adapter in 10sec"); setTimeout(() => { this.restart(); }, 10 * 1000); } ); } ); reject(); return; } this.config.userid = resp.headers.location.split("&")[2].split("=")[1]; if (!this.stringIsAValidUrl(resp.headers.location)) { if (resp.headers.location.indexOf("&error=") !== -1) { const location = resp.headers.location; this.log.error("Error: " + location.substring(location.indexOf("error="), location.length - 1)); } else { this.log.error("No valid login url, please download the log and visit:"); this.log.error("http://" + resp.request.host + resp.headers.location); } reject(); return; } let getRequest = request.get( { url: resp.headers.location || "", headers: { "User-Agent": this.userAgent, Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "Accept-Language": "en-US,en;q=0.9", "Accept-Encoding": "gzip, deflate", "x-requested-with": this.xrequest, }, jar: this.jar, gzip: true, followAllRedirects: true, }, (err, resp, body) => { if (err) { this.log.debug(err); this.getTokens(getRequest, code_verifier, reject, resolve); } else { this.log.debug(body); this.log.debug("No Token received visiting url and accept the permissions."); const form = this.extractHidden(body); getRequest = request.post( { url: getRequest.uri.href, headers: { "Content-Type": "application/x-www-form-urlencoded", "User-Agent": this.userAgent, Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "Accept-Language": "en-US,en;q=0.9", "Accept-Encoding": "gzip, deflate", "x-requested-with": this.xrequest, referer: getRequest.uri.href, }, form: form, jar: this.jar, gzip: true, followAllRedirects: true, }, (err, resp, body) => { if (err) { this.getTokens(getRequest, code_verifier, reject, resolve); } else { this.log.error("No Token received. Please try to logout and login in the VW app or select type VWv2 in the settings"); try { this.log.debug(JSON.stringify(body)); } catch (err) { this.log.error(err); reject(); } } } ); } } ); } catch (err2) { this.log.error("Login was not successful, please check your login credentials and selected type"); err && this.log.error(err); this.log.error(err2); this.log.error(err2.stack); reject(); } } ); } catch (err) { this.log.error(err); reject(); } } ); } catch (err) { this.log.error(err); reject(); } } ); }); } updateStatus() { if (this.config.type === "go") { this.getVehicles(); return; } else if (this.config.type === "skodae") { this.vinArray.forEach((vin) => { this.getSkodaEStatus(vin).catch(() => { this.log.error("get skodae status Failed"); }); }); } else if (this.config.type === "audidata") { this.vinArray.forEach((vin) => { this.getAudiDataStatus(vin).catch(() => { this.log.error("get audi data status Failed"); }); }); } else if (this.config.type === "id") { this.vinArray.forEach((vin) => { this.getIdStatus(vin).catch(() => { this.log.error("get id status Failed"); this.refreshIDToken().catch(() => {}); }); this.getWcData(); }); return; } else if (this.config.type === "seatelli" || this.config.type === "skodapower") { this.getElliData(this.config.type).catch(() => { this.log.error("get elli Failed"); }); return; } else { this.vinArray.forEach((vin) => { this.statesArray.forEach((state) => { if (state.path == "tripdata") { this.tripTypes.forEach((tripType) => { this.getVehicleStatus(vin, state.url, state.path, state.element, state.element2, null, null, tripType).catch(() => { this.log.debug("error while getting " + state.url); }); }); } else { this.getVehicleStatus(vin, state.url, state.path, state.element, state.element2).catch(() => { this.log.debug("error while getting " + state.url); }); } }); }); } } receiveLoginUrl() { return new Promise((resolve, reject) => { request( { method: "GET", url: "https://login.apps.emea.vwapps.io/authorize?nonce=" + this.randomString(16) + "&redirect_uri=weconnect://authenticated", headers: { Host: "login.apps.emea.vwapps.io", "user-agent": this.userAgent, accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "accept-language": "de-de", }, jar: this.jar, gzip: true, followAllRedirects: false, }, (err, resp, body) => { if (err || (resp && resp.statusCode >= 400)) { this.log.error("Failed in receive login url "); err && this.log.error(err); resp && this.log.error(resp.statusCode.toString()); body && this.log.error(JSON.stringify(body)); reject(); return; } resolve(resp.request.href); } ); }); } replaceVarInUrl(url, vin, tripType) { const curHomeRegion = this.homeRegion[vin]; return url .replace("/$vin", "/" + vin + "") .replace("$homeregion/", curHomeRegion + "/") .replace("/$type/", "/" + this.type + "/") .replace("/$country/", "/" + this.country + "/") .replace("/$tripType", "/" + tripType); } getTokens(getRequest, code_verifier, reject, resolve) { let hash = ""; if (getRequest.uri.hash) { hash = getRequest.uri.hash; } else { hash = getRequest.uri.query; } const hashArray = hash.split("&"); // eslint-disable-next-line no-unused-vars let state; let jwtauth_code; let jwtaccess_token; let jwtid_token; let jwtstate; hashArray.forEach((hash) => { const harray = hash.split("="); if (harray[0] === "#state" || harray[0] === "state") { state = harray[1]; } if (harray[0] === "code") { jwtauth_code = harray[1]; } if (harray[0] === "access_token") { jwtaccess_token = harray[1]; } if (harray[0] === "id_token") { jwtid_token = harray[1]; } if (harray[0] === "#state") { jwtstate = harray[1]; } }); // const state = hashArray[0].substring(hashArray[0].indexOf("=") + 1); // const jwtauth_code = hashArray[1].substring(hashArray[1].indexOf("=") + 1); // const jwtaccess_token = hashArray[2].substring(hashArray[2].indexOf("=") + 1); // const jwtid_token = hashArray[5].substring(hashArray[5].indexOf("=") + 1); let method = "POST"; let body = "auth_code=" + jwtauth_code + "&id_token=" + jwtid_token; let url = "https://tokenrefreshservice.apps.emea.vwapps.io/exchangeAuthCode"; let headers = { // "user-agent": this.userAgent, "X-App-version": this.xappversion, "content-type": "application/x-www-form-urlencoded", "x-app-name": this.xappname, accept: "application/json", }; if (this.config.type === "vw" || this.config.type === "vwv2") { body += "&code_verifier=" + code_verifier; } else { const brand = this.config.type === "skodae" ? "skoda" : this.config.type; body += "&brand=" + brand; } if (this.config.type === "go") { url = "https://dmp.apps.emea.vwapps.io/mobility-platform/token"; body = "code=" + jwtauth_code + "&client_id=" + this.clientId + "&redirect_uri=vwconnect://de.volkswagen.vwconnect/oauth2redirect/identitykit&grant_type=authorization_code&code_verifier=" + code_verifier; } if (this.config.type === "audidata") { url = "https://audi-global-dmp.apps.emea.vwapps.io/mobility-platform/token"; body = "code=" + jwtauth_code + "&client_id=" + this.clientId + "&redirect_uri=acpp://de.audi.connectplugandplay/oauth2redirect/identitykit&grant_type=authorization_code&code_verifier=" + code_verifier; } if (this.config.type === "id") { url = "https://login.apps.emea.vwapps.io/login/v1"; let redirerctUri = "weconnect://authenticated"; body = JSON.stringify({ state: jwtstate, id_token: jwtid_token, redirect_uri: redirerctUri, region: "emea", access_token: jwtaccess_token, authorizationCode: jwtauth_code, }); // @ts-ignore headers = { accept: "*/*", "content-type": "application/json", "x-newrelic-id": "VgAEWV9QDRAEXFlRAAYPUA==", "user-agent": this.userAgent, "accept-language": "de-de", }; if (this.type === "Wc") { method = "GET"; url = "https://wecharge.apps.emea.vwapps.io/user-identity/v1/identity/login?redirect_uri=wecharge://authenticated&code=" + jwtauth_code; redirerctUri = "wecharge://authenticated"; headers["x-api-key"] = "yabajourasW9N8sm+9F/oP=="; } } if (this.config.type === "audi") { this.getVWToken({}, jwtid_token, reject, resolve); return; } if (this.config.type === "seatelli" || this.config.type === "skodapower") { url = "https://api.elli.eco/identity/v1/loginOrSignupWithIdKit"; let brand = "seat"; let redirect = "Seat-elli-hub://opid"; if (this.config.type === "skodapower") { brand = "skoda"; redirect = "skoda-hub://opid"; } body = JSON.stringify({ brand: brand, grant_type: "authorization_code", code: jwtauth_code, redirect_uri: redirect, code_verifier: code_verifier, }); // @ts-ignore headers = { "Content-Type": "application/json", Accept: "application/json", "User-Agent": this.userAgent, "Accept-Language": "de-DE", }; } request( { method: method, url: url, headers: headers, body: body, jar: this.jar, gzip: true, followAl