Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

daikin-controller-cloud

Package Overview
Dependencies
Maintainers
1
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

daikin-controller-cloud - npm Package Compare versions

Comparing version 0.1.3 to 0.2.0

3

example/example.js

@@ -7,2 +7,5 @@ /**

*
* For an example on how to use the automatic Username/Password Login
* please refer to tokensaver.js
*
* The tokens will be stored in a tokenset.json file in the example

@@ -9,0 +12,0 @@ * directory and this file is also loaded on startup.

75

example/tokensaver.js
/**
* Example Script to use the Daikin-Controller-Cloud library
*
* This example will open a Proxy Server when no tokens are provided
* to allow a Login with the Daikin Cloud to get the needed tokens.
* This example will open a Proxy Server or use Username/Password
* login if data are provided when no tokens are provided to allow
* a Login with the Daikin Cloud to get the needed tokens.
*

@@ -18,3 +19,3 @@ * The tokens will be stored in a tokenset.json file in the example

async function main() {

@@ -33,38 +34,48 @@ /**

};
let tokenSet;
// Set outputfile for tokenset.json
const tokenFile = path.join(process.cwd(), 'tokenset.json');
options.logger('Writing tokenset to: ' + tokenFile);
// Initialize Daikin Cloud Instance
const daikinCloud = new DaikinCloud(tokenSet, options);
// Event that will be triggered on new or updated tokens, save into file
daikinCloud.on('token_update', tokenSet => {
console.log(`UPDATED tokens, use for future and wrote to tokenset.json`);
fs.writeFileSync(tokenFile, JSON.stringify(tokenSet));
});
await daikinCloud.initProxyServer();
console.log(`Please visit http://${options.proxyOwnIp}:${options.proxyWebPort} and Login to Daikin Cloud please.`);
// wait for user Login and getting the tokens
const resultTokenSet = await daikinCloud.waitForTokenFromProxy();
console.log('Retrieved tokens. Saved to ' + tokenFile);
//console.log(`Retrieved tokens, use for future: ${JSON.stringify(resultTokenSet)}`);
// stop Proxy server (and wait 1s before we do that to make sure
// the success page can be displayed correctly because waitForTokenFromProxy
// will resolve before the last request is sent to the browser!
await new Promise(resolve => setTimeout(resolve, 1000));
await daikinCloud.stopProxyServer();
const tokenFile = path.join(process.cwd(), 'tokenset.json');
options.logger('Writing tokenset to: ' + tokenFile);
// Initialize Daikin Cloud Instance
const daikinCloud = new DaikinCloud(tokenSet, options);
// Event that will be triggered on new or updated tokens, save into file
daikinCloud.on('token_update', tokenSet => {
console.log(`UPDATED tokens, use for future and wrote to tokenset.json`);
fs.writeFileSync(tokenFile, JSON.stringify(tokenSet));
});
let args = process.argv.slice(2);
if (args.length === 2 && args[0].includes('@')) {
console.log(`Using provided Login credentials (${args[0]}/${args[1]}) for a direct Login`)
const resultTokenSet = await daikinCloud.login(args[0], args[1]);
console.log('Retrieved tokens. Saved to ' + tokenFile);
} else {
if (args.length && !args[0].includes('@')) {
console.log('Ignore provided parameters because first parameter do not seem to be an email address');
console.log();
}
await daikinCloud.initProxyServer();
console.log(`Please visit http://${options.proxyOwnIp}:${options.proxyWebPort} and Login to Daikin Cloud please.`);
// wait for user Login and getting the tokens
const resultTokenSet = await daikinCloud.waitForTokenFromProxy();
console.log('Retrieved tokens. Saved to ' + tokenFile);
//console.log(`Retrieved tokens, use for future: ${JSON.stringify(resultTokenSet)}`);
// stop Proxy server (and wait 1s before we do that to make sure
// the success page can be displayed correctly because waitForTokenFromProxy
// will resolve before the last request is sent to the browser!
await new Promise(resolve => setTimeout(resolve, 1000));
await daikinCloud.stopProxyServer();
}
process.exit();
}
(async () => {
await main();
})();
})();

@@ -63,3 +63,3 @@ const EventEmitter = require('events');

// id_token_signed_response_alg (default "RS256")
token_endpoint_auth_method: 'none' // (default "client_secret_basic")
token_endpoint_auth_method: 'none' // (default 'client_secret_basic')
});

@@ -292,4 +292,204 @@

}
/**
* Returns the Tokens using mail authentication
* @emits DaikinCloudController#token_update
* @param {string} userName Mail address oassociated with the account
* @param {string} password Password of the account
* @returns {Promise<any>} Instance of openid-client.TokenSet with tokens
* @public
*/
async login(userName, password) {
Proxy = Proxy || require('./lib/proxy');
// Initiate proxy without starting it
if (!this.proxy) {
const proxyOptions = {
proxyOwnIp: this.options.proxyOwnIp,
proxyListenBind: this.options.proxyListenBind,
proxyPort: this.options.proxyPort,
proxyWebPort: this.options.proxyWebPort,
proxyDataDir: this.options.proxyDataDir,
logLevel: this.options.logLevel,
logger: this.options.logger
};
this.proxy = new Proxy(this.openIdClient, proxyOptions);
}
let cookies;
let location;
let login_token;
// Extract csrf state cookies
let csrfStateCookie;
try {
const response = await got(this.proxy._generateInitialUrl(), {
followRedirect: false
});
let cookies = response.headers['set-cookie'];
csrfStateCookie = cookies[1].split(';')[0].trim() + '; '
+ cookies[2].split(';')[0].trim();
location = response.headers['location'];
} catch (err) {
err.message = 'Error trying to reach initial URL: ' + err.message;
throw err;
}
// Extract SAML Context
let samlContext;
try {
const response = await got(location, { followRedirect: false })
location = response.headers['location'];
let regex = /samlContext=([^&]+)/g;
let match = regex.exec(location);
samlContext = match[1];
} catch (err) {
err.message = 'Error trying to follow redirect: ' + err.message;
throw err;
}
// Extract API version
let version;
try {
const body = await got('https://cdns.gigya.com/js/gigya.js', {
searchParams: {'apiKey': '3_xRB3jaQ62bVjqXU1omaEsPDVYC0Twi1zfq1zHPu_5HFT0zWkDvZJS97Yw1loJnTm'}
}).text();
let regex = /"(\d+-\d-\d+)"/g
let match = regex.exec(body);
version = match[1];
} catch (err) {
err.message = 'Error trying to extract API version: ' + err.message;
throw err;
}
// Extract the cookies used for the Single Sign On
let ssoCookies;
try {
const response = await got('https://cdc.daikin.eu/accounts.webSdkBootstrap', {
searchParams: {
'apiKey': '3_xRB3jaQ62bVjqXU1omaEsPDVYC0Twi1zfq1zHPu_5HFT0zWkDvZJS97Yw1loJnTm',
'sdk': 'js_latest',
'format': 'json'}
});
ssoCookies = response.headers['set-cookie'];
} catch (err) {
err.message = 'Error trying to extract SSO cookies: ' + err.message;
throw err;
}
// Login
cookies = ssoCookies[0].split(';')[0].trim() + '; '
+ ssoCookies[2].split(';')[0].trim() + '; '
+ 'hasGmid=ver4; '
+ 'gig_bootstrap_3_xRB3jaQ62bVjqXU1omaEsPDVYC0Twi1zfq1zHPu_5HFT0zWkDvZJS97Yw1loJnTm=cdc_ver4; '
+ 'gig_canary_3_QebFXhxEWDc8JhJdBWmvUd1e0AaWJCISbqe4QIHrk_KzNVJFJ4xsJ2UZbl8OIIFY=false; '
+ 'gig_canary_ver_3_QebFXhxEWDc8JhJdBWmvUd1e0AaWJCISbqe4QIHrk_KzNVJFJ4xsJ2UZbl8OIIFY=' + version + '; '
+ 'apiDomain_3_QebFXhxEWDc8JhJdBWmvUd1e0AaWJCISbqe4QIHrk_KzNVJFJ4xsJ2UZbl8OIIFY=cdc.daikin.eu; ';
try {
const json = await got('https://cdc.daikin.eu/accounts.login', {
'headers': {
'content-type': 'application/x-www-form-urlencoded',
'cookie': cookies},
searchParams: {
'loginID': userName,
'password': password,
'sessionExpiration':'31536000',
'targetEnv':'jssdk',
'include': 'profile,',
'loginMode': 'standard',
'riskContext': '{"b0":7527,"b2":4,"b5":1',
'APIKey': '3_xRB3jaQ62bVjqXU1omaEsPDVYC0Twi1zfq1zHPu_5HFT0zWkDvZJS97Yw1loJnTm',
'sdk': 'js_latest',
'authMode': 'cookie',
'pageURL': 'https://my.daikin.eu/content/daikinid-cdc-saml/en/login.html?samlContext=' + samlContext,
'sdkBuild': '12208',
'format': 'json'},
'method': 'POST',
}).json();
if (json && json.errorCode === 0 && json.sessionInfo && json.sessionInfo.login_token) {
login_token = json.sessionInfo.login_token;
} else {
throw new Error(json.errorDetails || `Unknown Login error: ${JSON.stringify(json)}`);
}
} catch (err) {
err.message = 'Login failed: ' + err.message;
throw err;
}
let samlResponse;
let relayState;
cookies = cookies +
+ 'glt_3_xRB3jaQ62bVjqXU1omaEsPDVYC0Twi1zfq1zHPu_5HFT0zWkDvZJS97Yw1loJnTm=' + login_token + '; '
+ 'gig_loginToken_3_QebFXhxEWDc8JhJdBWmvUd1e0AaWJCISbqe4QIHrk_KzNVJFJ4xsJ2UZbl8OIIFY=' + login_token + '; '
+ 'gig_loginToken_3_QebFXhxEWDc8JhJdBWmvUd1e0AaWJCISbqe4QIHrk_KzNVJFJ4xsJ2UZbl8OIIFY_exp=' + (Date.now() + 3600000) + '; '
+ 'gig_loginToken_3_QebFXhxEWDc8JhJdBWmvUd1e0AaWJCISbqe4QIHrk_KzNVJFJ4xsJ2UZbl8OIIFY_visited=%2C3_xRB3jaQ62bVjqXU1omaEsPDVYC0Twi1zfq1zHPu_5HFT0zWkDvZJS97Yw1loJnTm;';
try {
const body = await got('https://cdc.daikin.eu/saml/v2.0/3_xRB3jaQ62bVjqXU1omaEsPDVYC0Twi1zfq1zHPu_5HFT0zWkDvZJS97Yw1loJnTm/idp/sso/continue', {
searchParams: {
'samlContext': samlContext,
'loginToken': login_token},
headers: {
'cookie': cookies
}
}).text();
let regex = /value="([^"]+=*)"/g;
let matches = regex.exec(body);
samlResponse = matches[1];
matches = regex.exec(body);
relayState = matches[1];
} catch (err) {
err.message = 'Authentication on SAML Identity Provider failed: ' + err.message;
throw err;
}
// Fetch the daikinunified URL
let daikinunified;
const params = new URLSearchParams({
'SAMLResponse': samlResponse,
'RelayState': relayState
});
try {
const response = await got.post('https://daikin-unicloud-prod.auth.eu-west-1.amazoncognito.com/saml2/idpresponse', {
headers: {
'content-type': 'application/x-www-form-urlencoded',
'cookie': csrfStateCookie
},
body: params.toString(),
followRedirect: false
});
daikinunified = response.headers['location'];
if (!daikinunified.startsWith('daikinunified://')) {
throw new Error(`Invalid final Authentication redirect. Location is ${daikinunified}`);
}
} catch (err) {
err.message = 'Impossible to retrieve SAML Identity Provider\'s response: ' + err.message;
throw err;
}
this.tokenSet = await this.proxy._retrieveTokens(daikinunified);
/**
* Inform the using application about changed Tokens (in this case it are new received tokens)
* to store on application side
*
* @event DaikinCloudController#token_update
* @property {TokenSet} Instance of openid-client-TokenSet with updated tokens
**/
this.emit('token_update', this.tokenSet);
return this.tokenSet;
}
}
module.exports = DaikinCloudController;
module.exports = DaikinCloudController;
{
"name": "daikin-controller-cloud",
"version": "0.1.3",
"version": "0.2.0",
"description": "Interact with Daikin Cloud devices and retrieve Tokens",

@@ -20,4 +20,4 @@ "author": "Apollon77 <iobroker@fischer-ka.de>",

"devDependencies": {
"@alcalzone/release-script": "^2.2.0",
"pkg": "^5.3.0"
"@alcalzone/release-script": "^2.2.1",
"pkg": "^5.3.1"
},

@@ -24,0 +24,0 @@ "repository": {

@@ -25,5 +25,2 @@ # daikin-controller-cloud

## Example:
See example folder, check the settings (add your own IP at minimum!) and start it with `node example.js`.
## Using tokensaver.js

@@ -37,8 +34,7 @@

Or, more conveniently, use one of the binaries supplied in this repository.
TODO: add auto-binaries
Or, more conveniently, use one of the binaries (Linux, macOS and Windows) supplied with the [Releases](https://github.com/Apollon77/daikin-controller-cloud/releases).
## Code-Usage example
See example folder, check the settings (add your own IP at minimum!) and start it with `node example.js`.
TODO, for now: see example
## Issue reporting and enhancements

@@ -58,10 +54,14 @@ * Create Issues here in Github

### 0.2.0 (2021-07-30)
* (csu333) Add direct login method using email/password as second option beside proxy
* (csu333) Add direct login also to tokensaver.js
### 0.1.3 (2021-07-16)
* Added tokensaver.js
* Added script to auto-generate binaries based on tokensaver.js
* (gigatexel ) Added tokensaver.js
* (gigatexel/Apollon77) Added script to auto-generate binaries based on tokensaver.js
### 0.1.1 (2021-03-29)
* Initial release version
* (Apollon77) Initial release version
### 0.0.x
* Initial version
* (Apollon77) Initial version
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc