alexa-cookie2 4.1.2 → 4.2.0
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.
- package/LICENSE +1 -1
- package/README.md +8 -0
- package/alexa-cookie.js +75 -63
- package/example/example.js +3 -2
- package/lib/proxy.js +3 -3
- package/package.json +4 -4
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
The MIT License (MIT)
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2018-
|
|
3
|
+
Copyright (c) 2018-2023 Apollon77 <ingo@fischer-ka.de>
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -49,6 +49,14 @@ Partly based on [Amazon Alexa Remote Control](http://blog.loetzimmer.de/2017/10/
|
|
|
49
49
|
Thank you for that work.
|
|
50
50
|
|
|
51
51
|
## Changelog:
|
|
52
|
+
### 4.2.0 (2023-08-08)
|
|
53
|
+
* (Hive) Adds the ability to alter the close proxy message
|
|
54
|
+
|
|
55
|
+
### 4.1.3 (2022-08-03)
|
|
56
|
+
* (Apollon77) Fix device registration and token exchange in other regions
|
|
57
|
+
* (Apollon77) Use the chosen App name also for refreshing of tokens
|
|
58
|
+
* (Apollon77) General updates
|
|
59
|
+
|
|
52
60
|
### 4.1.2 (2022-07-19)
|
|
53
61
|
* (Apollon77) Prevent crash case
|
|
54
62
|
|
package/alexa-cookie.js
CHANGED
|
@@ -16,10 +16,11 @@ const defaultAmazonPage = 'amazon.de';
|
|
|
16
16
|
const defaultUserAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36';
|
|
17
17
|
const defaultUserAgentLinux = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36';
|
|
18
18
|
//const defaultUserAgentMacOs = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36';
|
|
19
|
+
const defaultProxyCloseWindowHTML = '<b>Amazon Alexa Cookie successfully retrieved. You can close the browser.</b>';
|
|
19
20
|
const defaultAcceptLanguage = 'de-DE';
|
|
20
21
|
|
|
21
|
-
const apiCallVersion = '2.2.
|
|
22
|
-
const apiCallUserAgent = 'AmazonWebView/Amazon Alexa/2.2.
|
|
22
|
+
const apiCallVersion = '2.2.485407.0';
|
|
23
|
+
const apiCallUserAgent = 'AmazonWebView/Amazon Alexa/2.2.485407.0/iOS/15.5/iPhone';
|
|
23
24
|
const defaultAppName = 'ioBroker Alexa2';
|
|
24
25
|
|
|
25
26
|
const csrfOptions = [
|
|
@@ -46,23 +47,23 @@ function AlexaCookie() {
|
|
|
46
47
|
if (cookie && cookie.length === 3) {
|
|
47
48
|
if (cookie[1] === 'ap-fid' && cookie[2] === '""') continue;
|
|
48
49
|
if (cookies[cookie[1]] && cookies[cookie[1]] !== cookie[2]) {
|
|
49
|
-
_options.logger && _options.logger(
|
|
50
|
+
_options.logger && _options.logger(`Alexa-Cookie: Update Cookie ${cookie[1]} = ${cookie[2]}`);
|
|
50
51
|
} else if (!cookies[cookie[1]]) {
|
|
51
|
-
_options.logger && _options.logger(
|
|
52
|
+
_options.logger && _options.logger(`Alexa-Cookie: Add Cookie ${cookie[1]} = ${cookie[2]}`);
|
|
52
53
|
}
|
|
53
54
|
cookies[cookie[1]] = cookie[2];
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
Cookie = '';
|
|
57
58
|
for (const name of Object.keys(cookies)) {
|
|
58
|
-
Cookie += name
|
|
59
|
+
Cookie += `${name}=${cookies[name]}; `;
|
|
59
60
|
}
|
|
60
61
|
Cookie = Cookie.replace(/[; ]*$/, '');
|
|
61
62
|
return Cookie;
|
|
62
63
|
};
|
|
63
64
|
|
|
64
65
|
const request = (options, info, callback) => {
|
|
65
|
-
_options.logger && _options.logger(
|
|
66
|
+
_options.logger && _options.logger(`Alexa-Cookie: Sending Request with ${JSON.stringify(options)}`);
|
|
66
67
|
if (typeof info === 'function') {
|
|
67
68
|
callback = info;
|
|
68
69
|
info = {
|
|
@@ -84,7 +85,7 @@ function AlexaCookie() {
|
|
|
84
85
|
info.requests.push({options: options, response: res});
|
|
85
86
|
|
|
86
87
|
if (options.followRedirects !== false && res.statusCode >= 300 && res.statusCode < 400) {
|
|
87
|
-
_options.logger && _options.logger(
|
|
88
|
+
_options.logger && _options.logger(`Alexa-Cookie: Response (${res.statusCode})${res.headers.location ? ` - Redirect to ${res.headers.location}` : ''}`);
|
|
88
89
|
//options.url = res.headers.location;
|
|
89
90
|
const u = url.parse(res.headers.location);
|
|
90
91
|
if (u.host) options.host = u.host;
|
|
@@ -96,7 +97,7 @@ function AlexaCookie() {
|
|
|
96
97
|
res.socket && res.socket.end();
|
|
97
98
|
return request(options, info, callback);
|
|
98
99
|
} else {
|
|
99
|
-
_options.logger && _options.logger(
|
|
100
|
+
_options.logger && _options.logger(`Alexa-Cookie: Response (${res.statusCode})`);
|
|
100
101
|
res.on('data', (chunk) => {
|
|
101
102
|
body += chunk;
|
|
102
103
|
});
|
|
@@ -140,18 +141,18 @@ function AlexaCookie() {
|
|
|
140
141
|
_options.amazonPage = _options.amazonPage || defaultAmazonPage;
|
|
141
142
|
if (_options.formerRegistrationData && _options.formerRegistrationData.amazonPage) _options.amazonPage = _options.formerRegistrationData.amazonPage;
|
|
142
143
|
|
|
143
|
-
_options.logger && _options.logger(
|
|
144
|
+
_options.logger && _options.logger(`Alexa-Cookie: Use as Login-Amazon-URL: ${_options.amazonPage}`);
|
|
144
145
|
|
|
145
146
|
_options.baseAmazonPage = _options.baseAmazonPage || 'amazon.com';
|
|
146
|
-
_options.logger && _options.logger(
|
|
147
|
+
_options.logger && _options.logger(`Alexa-Cookie: Use as Base-Amazon-URL: ${_options.baseAmazonPage}`);
|
|
147
148
|
|
|
148
149
|
_options.deviceAppName = _options.deviceAppName || defaultAppName;
|
|
149
|
-
_options.logger && _options.logger(
|
|
150
|
+
_options.logger && _options.logger(`Alexa-Cookie: Use as Device-App-Name: ${_options.deviceAppName}`);
|
|
150
151
|
|
|
151
152
|
if (!_options.baseAmazonPageHandle && _options.baseAmazonPageHandle !== '') {
|
|
152
153
|
const amazonDomain = _options.baseAmazonPage.substr(_options.baseAmazonPage.lastIndexOf('.') + 1);
|
|
153
154
|
if (amazonDomain === 'jp') {
|
|
154
|
-
_options.baseAmazonPageHandle =
|
|
155
|
+
_options.baseAmazonPageHandle = `_${amazonDomain}`;
|
|
155
156
|
}
|
|
156
157
|
else if (amazonDomain !== 'com') {
|
|
157
158
|
//_options.baseAmazonPageHandle = '_' + amazonDomain;
|
|
@@ -174,11 +175,14 @@ function AlexaCookie() {
|
|
|
174
175
|
_options.userAgent = defaultUserAgentLinux;
|
|
175
176
|
}
|
|
176
177
|
}
|
|
177
|
-
_options.logger && _options.logger(
|
|
178
|
+
_options.logger && _options.logger(`Alexa-Cookie: Use as User-Agent: ${_options.userAgent}`);
|
|
178
179
|
|
|
179
180
|
_options.acceptLanguage = _options.acceptLanguage || defaultAcceptLanguage;
|
|
180
|
-
_options.logger && _options.logger('Alexa-Cookie: Use as Accept-Language: ' + _options.acceptLanguage);
|
|
181
181
|
|
|
182
|
+
_options.logger && _options.logger(`Alexa-Cookie: Use as Accept-Language: ${_options.acceptLanguage}`);
|
|
183
|
+
|
|
184
|
+
_options.proxyCloseWindowHTML = _options.proxyCloseWindowHTML || defaultProxyCloseWindowHTML;
|
|
185
|
+
|
|
182
186
|
if (_options.setupProxy && !_options.proxyOwnIp) {
|
|
183
187
|
_options.logger && _options.logger('Alexa-Cookie: Own-IP Setting missing for Proxy. Disabling!');
|
|
184
188
|
_options.setupProxy = false;
|
|
@@ -187,7 +191,7 @@ function AlexaCookie() {
|
|
|
187
191
|
_options.setupProxy = true;
|
|
188
192
|
_options.proxyPort = _options.proxyPort || 0;
|
|
189
193
|
_options.proxyListenBind = _options.proxyListenBind || '0.0.0.0';
|
|
190
|
-
_options.logger && _options.logger(
|
|
194
|
+
_options.logger && _options.logger(`Alexa-Cookie: Proxy-Mode enabled if needed: ${_options.proxyOwnIp}:${_options.proxyPort} to listen on ${_options.proxyListenBind}`);
|
|
191
195
|
} else {
|
|
192
196
|
_options.setupProxy = false;
|
|
193
197
|
_options.logger && _options.logger('Alexa-Cookie: Proxy mode disabled');
|
|
@@ -205,26 +209,26 @@ function AlexaCookie() {
|
|
|
205
209
|
function csrfTry() {
|
|
206
210
|
const path = csrfUrls.shift();
|
|
207
211
|
const options = {
|
|
208
|
-
'host':
|
|
212
|
+
'host': `alexa.${_options.amazonPage}`,
|
|
209
213
|
'path': path,
|
|
210
214
|
'method': 'GET',
|
|
211
215
|
'headers': {
|
|
212
216
|
'DNT': '1',
|
|
213
217
|
'User-Agent': _options.userAgent,
|
|
214
218
|
'Connection': 'keep-alive',
|
|
215
|
-
'Referer':
|
|
219
|
+
'Referer': `https://alexa.${_options.amazonPage}/spa/index.html`,
|
|
216
220
|
'Cookie': cookie,
|
|
217
221
|
'Accept': '*/*',
|
|
218
|
-
'Origin':
|
|
222
|
+
'Origin': `https://alexa.${_options.amazonPage}`
|
|
219
223
|
}
|
|
220
224
|
};
|
|
221
225
|
|
|
222
|
-
_options.logger && _options.logger(
|
|
226
|
+
_options.logger && _options.logger(`Alexa-Cookie: Step 4: get CSRF via ${path}`);
|
|
223
227
|
request(options, (error, response) => {
|
|
224
228
|
cookie = addCookies(cookie, response ? response.headers : null);
|
|
225
229
|
const ar = /csrf=([^;]+)/.exec(cookie);
|
|
226
230
|
const csrf = ar ? ar[1] : undefined;
|
|
227
|
-
_options.logger && _options.logger(
|
|
231
|
+
_options.logger && _options.logger(`Alexa-Cookie: Result: csrf=${csrf}, Cookie=${cookie}`);
|
|
228
232
|
if (!csrf && csrfUrls.length) {
|
|
229
233
|
csrfTry();
|
|
230
234
|
return;
|
|
@@ -268,7 +272,7 @@ function AlexaCookie() {
|
|
|
268
272
|
if (!_options.proxyOnly) {
|
|
269
273
|
// get first cookie and write redirection target into referer
|
|
270
274
|
const options = {
|
|
271
|
-
host:
|
|
275
|
+
host: `alexa.${_options.amazonPage}`,
|
|
272
276
|
path: '',
|
|
273
277
|
method: 'GET',
|
|
274
278
|
headers: {
|
|
@@ -291,7 +295,7 @@ function AlexaCookie() {
|
|
|
291
295
|
// login empty to generate session
|
|
292
296
|
Cookie = addCookies(Cookie, response.headers);
|
|
293
297
|
const options = {
|
|
294
|
-
host:
|
|
298
|
+
host: `www.${_options.amazonPage}`,
|
|
295
299
|
path: '/ap/signin',
|
|
296
300
|
method: 'POST',
|
|
297
301
|
headers: {
|
|
@@ -301,7 +305,7 @@ function AlexaCookie() {
|
|
|
301
305
|
'Accept-Language': _options.acceptLanguage,
|
|
302
306
|
'Connection': 'keep-alive',
|
|
303
307
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
304
|
-
'Referer':
|
|
308
|
+
'Referer': `https://${lastRequestOptions.host}${lastRequestOptions.path}`,
|
|
305
309
|
'Cookie': Cookie,
|
|
306
310
|
'Accept': '*/*'
|
|
307
311
|
},
|
|
@@ -317,7 +321,7 @@ function AlexaCookie() {
|
|
|
317
321
|
|
|
318
322
|
// login with filled out form
|
|
319
323
|
// !!! referer now contains session in URL
|
|
320
|
-
options.host =
|
|
324
|
+
options.host = `www.${_options.amazonPage}`;
|
|
321
325
|
options.path = '/ap/signin';
|
|
322
326
|
options.method = 'POST';
|
|
323
327
|
options.headers.Cookie = Cookie = addCookies(Cookie, response.headers);
|
|
@@ -401,7 +405,7 @@ function AlexaCookie() {
|
|
|
401
405
|
};
|
|
402
406
|
|
|
403
407
|
const handleTokenRegistration = (_options, loginData, callback) => {
|
|
404
|
-
_options.logger && _options.logger(
|
|
408
|
+
_options.logger && _options.logger(`Handle token registration Start: ${JSON.stringify(loginData)}`);
|
|
405
409
|
|
|
406
410
|
loginData.deviceAppName = _options.deviceAppName;
|
|
407
411
|
|
|
@@ -437,7 +441,7 @@ function AlexaCookie() {
|
|
|
437
441
|
"Name": "session-id-time"
|
|
438
442
|
}*/
|
|
439
443
|
],
|
|
440
|
-
'domain':
|
|
444
|
+
'domain': `.${_options.baseAmazonPage}`
|
|
441
445
|
},
|
|
442
446
|
'registration_data': {
|
|
443
447
|
'domain': 'Device',
|
|
@@ -483,7 +487,7 @@ function AlexaCookie() {
|
|
|
483
487
|
}
|
|
484
488
|
|
|
485
489
|
const options = {
|
|
486
|
-
host:
|
|
490
|
+
host: `api.${_options.baseAmazonPage}`,
|
|
487
491
|
path: '/auth/register',
|
|
488
492
|
method: 'POST',
|
|
489
493
|
headers: {
|
|
@@ -494,7 +498,7 @@ function AlexaCookie() {
|
|
|
494
498
|
'Content-Type': 'application/json',
|
|
495
499
|
'Cookie': loginData.loginCookie,
|
|
496
500
|
'Accept': 'application/json',
|
|
497
|
-
'x-amzn-identity-auth-domain':
|
|
501
|
+
'x-amzn-identity-auth-domain': `api.${_options.baseAmazonPage}`
|
|
498
502
|
},
|
|
499
503
|
body: JSON.stringify(registerData)
|
|
500
504
|
};
|
|
@@ -508,11 +512,11 @@ function AlexaCookie() {
|
|
|
508
512
|
try {
|
|
509
513
|
if (typeof body !== 'object') body = JSON.parse(body);
|
|
510
514
|
} catch (err) {
|
|
511
|
-
_options.logger && _options.logger(
|
|
515
|
+
_options.logger && _options.logger(`Register App Response: ${JSON.stringify(body)}`);
|
|
512
516
|
callback && callback(err, null);
|
|
513
517
|
return;
|
|
514
518
|
}
|
|
515
|
-
_options.logger && _options.logger(
|
|
519
|
+
_options.logger && _options.logger(`Register App Response: ${JSON.stringify(body)}`);
|
|
516
520
|
|
|
517
521
|
if (!body.response || !body.response.success || !body.response.success.tokens || !body.response.success.tokens.bearer) {
|
|
518
522
|
callback && callback(new Error('No tokens in Register response'), null);
|
|
@@ -523,13 +527,21 @@ function AlexaCookie() {
|
|
|
523
527
|
loginData.tokenDate = Date.now();
|
|
524
528
|
loginData.macDms = body.response.success.tokens.mac_dms;
|
|
525
529
|
|
|
530
|
+
if (body.response.success.tokens.website_cookies && Array.isArray(body.response.success.tokens.website_cookies)) {
|
|
531
|
+
const newCookies = [];
|
|
532
|
+
body.response.success.tokens.website_cookies.forEach(cookie => {
|
|
533
|
+
newCookies.push(`${cookie.Name}=${cookie.Value};`);
|
|
534
|
+
});
|
|
535
|
+
Cookie = addCookies(Cookie, {'set-cookie': newCookies});
|
|
536
|
+
}
|
|
537
|
+
|
|
526
538
|
/*
|
|
527
539
|
Get Amazon Marketplace Country
|
|
528
540
|
*/
|
|
529
541
|
|
|
530
542
|
const options = {
|
|
531
|
-
host:
|
|
532
|
-
path:
|
|
543
|
+
host: `alexa.${_options.baseAmazonPage}`,
|
|
544
|
+
path: `/api/users/me?platform=ios&version=${apiCallVersion}`,
|
|
533
545
|
method: 'GET',
|
|
534
546
|
headers: {
|
|
535
547
|
'User-Agent': apiCallUserAgent,
|
|
@@ -547,11 +559,11 @@ function AlexaCookie() {
|
|
|
547
559
|
try {
|
|
548
560
|
if (typeof body !== 'object') body = JSON.parse(body);
|
|
549
561
|
} catch (err) {
|
|
550
|
-
_options.logger && _options.logger(
|
|
562
|
+
_options.logger && _options.logger(`Get User data Response: ${JSON.stringify(body)}`);
|
|
551
563
|
callback && callback(err, null);
|
|
552
564
|
return;
|
|
553
565
|
}
|
|
554
|
-
_options.logger && _options.logger(
|
|
566
|
+
_options.logger && _options.logger(`Get User data Response: ${JSON.stringify(body)}`);
|
|
555
567
|
|
|
556
568
|
Cookie = addCookies(Cookie, response.headers);
|
|
557
569
|
|
|
@@ -564,7 +576,7 @@ function AlexaCookie() {
|
|
|
564
576
|
callback && callback(error, null);
|
|
565
577
|
return;
|
|
566
578
|
} else if (error && (!_options.formerRegistrationData || !_options.formerRegistrationData.amazonPage) && _options.amazonPage) {
|
|
567
|
-
_options.logger && _options.logger(
|
|
579
|
+
_options.logger && _options.logger(`Continue with externally set amazonPage: ${_options.amazonPage}`);
|
|
568
580
|
} else if (error) {
|
|
569
581
|
_options.logger && _options.logger('Ignore error while getting user data and amazonPage because previously set amazonPage is available');
|
|
570
582
|
}
|
|
@@ -579,7 +591,7 @@ function AlexaCookie() {
|
|
|
579
591
|
loginData.localCookie = localCookie;
|
|
580
592
|
getCSRFFromCookies(loginData.localCookie, _options, (err, resData) => {
|
|
581
593
|
if (err) {
|
|
582
|
-
callback && callback(new Error(
|
|
594
|
+
callback && callback(new Error(`Error getting csrf for ${loginData.amazonPage}`), null);
|
|
583
595
|
return;
|
|
584
596
|
}
|
|
585
597
|
loginData.localCookie = resData.cookie;
|
|
@@ -587,7 +599,7 @@ function AlexaCookie() {
|
|
|
587
599
|
delete loginData.accessToken;
|
|
588
600
|
delete loginData.authorization_code;
|
|
589
601
|
delete loginData.verifier;
|
|
590
|
-
_options.logger && _options.logger(
|
|
602
|
+
_options.logger && _options.logger(`Final Registration Result: ${JSON.stringify(loginData)}`);
|
|
591
603
|
callback && callback(null, loginData);
|
|
592
604
|
});
|
|
593
605
|
});
|
|
@@ -604,19 +616,19 @@ function AlexaCookie() {
|
|
|
604
616
|
const exchangeParams = {
|
|
605
617
|
'di.os.name': 'iOS',
|
|
606
618
|
'app_version': apiCallVersion,
|
|
607
|
-
'domain':
|
|
619
|
+
'domain': `.${amazonPage}`,
|
|
608
620
|
'source_token': refreshToken,
|
|
609
621
|
'requested_token_type': 'auth_cookies',
|
|
610
622
|
'source_token_type': 'refresh_token',
|
|
611
623
|
'di.hw.version': 'iPhone',
|
|
612
|
-
'di.sdk.version': '6.
|
|
613
|
-
'cookies': Buffer.from(
|
|
614
|
-
'app_name':
|
|
615
|
-
'di.os.version': '
|
|
624
|
+
'di.sdk.version': '6.12.3',
|
|
625
|
+
'cookies': Buffer.from(`{„cookies“:{".${amazonPage}":[]}}`).toString('base64'),
|
|
626
|
+
'app_name': _options.deviceAppName || defaultAppName,
|
|
627
|
+
'di.os.version': '15.5'
|
|
616
628
|
};
|
|
617
629
|
const options = {
|
|
618
|
-
host:
|
|
619
|
-
path: '/ap/exchangetoken',
|
|
630
|
+
host: `www.${amazonPage}`,
|
|
631
|
+
path: '/ap/exchangetoken/cookies',
|
|
620
632
|
method: 'POST',
|
|
621
633
|
headers: {
|
|
622
634
|
'User-Agent': apiCallUserAgent,
|
|
@@ -630,7 +642,7 @@ function AlexaCookie() {
|
|
|
630
642
|
encodeURIComponent: encodeURIComponent
|
|
631
643
|
})
|
|
632
644
|
};
|
|
633
|
-
_options.logger && _options.logger(
|
|
645
|
+
_options.logger && _options.logger(`Alexa-Cookie: Exchange tokens for ${amazonPage}`);
|
|
634
646
|
_options.logger && _options.logger(JSON.stringify(options));
|
|
635
647
|
|
|
636
648
|
request(options, (error, response, body) => {
|
|
@@ -641,35 +653,35 @@ function AlexaCookie() {
|
|
|
641
653
|
try {
|
|
642
654
|
if (typeof body !== 'object') body = JSON.parse(body);
|
|
643
655
|
} catch (err) {
|
|
644
|
-
_options.logger && _options.logger(
|
|
656
|
+
_options.logger && _options.logger(`Exchange Token Response: ${JSON.stringify(body)}`);
|
|
645
657
|
callback && callback(err, null);
|
|
646
658
|
return;
|
|
647
659
|
}
|
|
648
|
-
_options.logger && _options.logger(
|
|
660
|
+
_options.logger && _options.logger(`Exchange Token Response: ${JSON.stringify(body)}`);
|
|
649
661
|
|
|
650
662
|
if (!body.response || !body.response.tokens || !body.response.tokens.cookies) {
|
|
651
663
|
callback && callback(new Error('No cookies in Exchange response'), null);
|
|
652
664
|
return;
|
|
653
665
|
}
|
|
654
|
-
if (!body.response.tokens.cookies[
|
|
655
|
-
callback && callback(new Error(
|
|
666
|
+
if (!body.response.tokens.cookies[`.${amazonPage}`]) {
|
|
667
|
+
callback && callback(new Error(`No cookies for ${amazonPage} in Exchange response`), null);
|
|
656
668
|
return;
|
|
657
669
|
}
|
|
658
670
|
|
|
659
671
|
Cookie = addCookies(Cookie, response.headers);
|
|
660
672
|
const cookies = cookieTools.parse(Cookie);
|
|
661
|
-
body.response.tokens.cookies[
|
|
673
|
+
body.response.tokens.cookies[`.${amazonPage}`].forEach((cookie) => {
|
|
662
674
|
if (cookies[cookie.Name] && cookies[cookie.Name] !== cookie.Value) {
|
|
663
|
-
_options.logger && _options.logger(
|
|
675
|
+
_options.logger && _options.logger(`Alexa-Cookie: Update Cookie ${cookie.Name} = ${cookie.Value}`);
|
|
664
676
|
} else if (!cookies[cookie.Name]) {
|
|
665
|
-
_options.logger && _options.logger(
|
|
677
|
+
_options.logger && _options.logger(`Alexa-Cookie: Add Cookie ${cookie.Name} = ${cookie.Value}`);
|
|
666
678
|
}
|
|
667
679
|
cookies[cookie.Name] = cookie.Value;
|
|
668
680
|
|
|
669
681
|
});
|
|
670
682
|
let localCookie = '';
|
|
671
683
|
for (const name of Object.keys(cookies)) {
|
|
672
|
-
localCookie += name
|
|
684
|
+
localCookie += `${name}=${cookies[name]}; `;
|
|
673
685
|
}
|
|
674
686
|
localCookie = localCookie.replace(/[; ]*$/, '');
|
|
675
687
|
|
|
@@ -695,9 +707,9 @@ function AlexaCookie() {
|
|
|
695
707
|
initConfig();
|
|
696
708
|
|
|
697
709
|
const refreshData = {
|
|
698
|
-
'app_name':
|
|
710
|
+
'app_name': _options.deviceAppName || defaultAppName,
|
|
699
711
|
'app_version': apiCallVersion,
|
|
700
|
-
'di.sdk.version': '6.
|
|
712
|
+
'di.sdk.version': '6.12.3',
|
|
701
713
|
'source_token': _options.formerRegistrationData.refreshToken,
|
|
702
714
|
'package_name': 'com.amazon.echo',
|
|
703
715
|
'di.hw.version': 'iPhone',
|
|
@@ -705,12 +717,12 @@ function AlexaCookie() {
|
|
|
705
717
|
'requested_token_type': 'access_token',
|
|
706
718
|
'source_token_type': 'refresh_token',
|
|
707
719
|
'di.os.name': 'iOS',
|
|
708
|
-
'di.os.version': '
|
|
709
|
-
'current_version': '6.
|
|
720
|
+
'di.os.version': '15.5',
|
|
721
|
+
'current_version': '6.12.3'
|
|
710
722
|
};
|
|
711
723
|
|
|
712
724
|
const options = {
|
|
713
|
-
host:
|
|
725
|
+
host: `api.${_options.baseAmazonPage}`,
|
|
714
726
|
path: '/auth/token',
|
|
715
727
|
method: 'POST',
|
|
716
728
|
headers: {
|
|
@@ -721,7 +733,7 @@ function AlexaCookie() {
|
|
|
721
733
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
722
734
|
'Cookie': _options.formerRegistrationData.loginCookie,
|
|
723
735
|
'Accept': 'application/json',
|
|
724
|
-
'x-amzn-identity-auth-domain':
|
|
736
|
+
'x-amzn-identity-auth-domain': `api.${_options.baseAmazonPage}`
|
|
725
737
|
},
|
|
726
738
|
body: querystring.stringify(refreshData)
|
|
727
739
|
};
|
|
@@ -736,11 +748,11 @@ function AlexaCookie() {
|
|
|
736
748
|
try {
|
|
737
749
|
if (typeof body !== 'object') body = JSON.parse(body);
|
|
738
750
|
} catch (err) {
|
|
739
|
-
_options.logger && _options.logger(
|
|
751
|
+
_options.logger && _options.logger(`Refresh Token Response: ${JSON.stringify(body)}`);
|
|
740
752
|
callback && callback(err, null);
|
|
741
753
|
return;
|
|
742
754
|
}
|
|
743
|
-
_options.logger && _options.logger(
|
|
755
|
+
_options.logger && _options.logger(`Refresh Token Response: ${JSON.stringify(body)}`);
|
|
744
756
|
|
|
745
757
|
_options.formerRegistrationData.loginCookie = addCookies(_options.formerRegistrationData.loginCookie, response.headers);
|
|
746
758
|
|
|
@@ -758,8 +770,8 @@ function AlexaCookie() {
|
|
|
758
770
|
|
|
759
771
|
// Restore frc and map-md
|
|
760
772
|
const initCookies = cookieTools.parse(_options.formerRegistrationData.loginCookie);
|
|
761
|
-
let newCookie =
|
|
762
|
-
newCookie +=
|
|
773
|
+
let newCookie = `frc=${initCookies.frc}; `;
|
|
774
|
+
newCookie += `map-md=${initCookies['map-md']}; `;
|
|
763
775
|
newCookie += comCookie;
|
|
764
776
|
|
|
765
777
|
_options.formerRegistrationData.loginCookie = newCookie;
|
package/example/example.js
CHANGED
|
@@ -17,11 +17,12 @@ const config = {
|
|
|
17
17
|
proxyPort: 3456, // optional: use this port for the proxy, default is 0 means random port is selected
|
|
18
18
|
proxyListenBind: '0.0.0.0',// optional: set this to bind the proxy to a special IP, default is '0.0.0.0'
|
|
19
19
|
proxyLogLevel: 'info', // optional: Loglevel of Proxy, default 'warn'
|
|
20
|
-
baseAmazonPage: 'amazon.com', // optional: Change the Proxy Amazon Page - all "western countries" directly use amazon.com! Change to amazon.co.jp for Japan
|
|
20
|
+
baseAmazonPage: 'amazon.com', // optional: Change the Proxy Amazon Page - all "western countries" directly use amazon.com including australia! Change to amazon.co.jp for Japan
|
|
21
21
|
amazonPageProxyLanguage: 'de_DE', // optional: language to be used for the Amazon Sign-in page the proxy calls. default is "de_DE")
|
|
22
22
|
deviceAppName: '...', // optional: name of the device app name which will be registered with Amazon, leave empty to use a default one
|
|
23
23
|
formerDataStorePath: '...', // optional: overwrite path where some of the formerRegistrationData are persisted to optimize against Amazon security measures
|
|
24
|
-
formerRegistrationData: { ... } // optional/preferred: provide the result object from subsequent proxy usages here and some generated data will be reused for next proxy call too
|
|
24
|
+
formerRegistrationData: { ... }, // optional/preferred: provide the result object from subsequent proxy usages here and some generated data will be reused for next proxy call too
|
|
25
|
+
proxyCloseWindowHTML: '...' // optional: use in order to override the default html displayed when the proxy window can be closed, default is '<b>Amazon Alexa Cookie successfully retrieved. You can close the browser.</b>'
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
|
package/lib/proxy.js
CHANGED
|
@@ -90,7 +90,7 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
if (!_options.formerRegistrationData || !_options.formerRegistrationData['map-md']) {
|
|
93
|
-
initialCookies['map-md'] = Buffer.from('{"device_user_dictionary":[],"device_registration_data":{"software_version":"1"},"app_identifier":{"app_version":"2.2.
|
|
93
|
+
initialCookies['map-md'] = Buffer.from('{"device_user_dictionary":[],"device_registration_data":{"software_version":"1"},"app_identifier":{"app_version":"2.2.485407","bundle_id":"com.amazon.echo"}}').toString('base64');
|
|
94
94
|
}
|
|
95
95
|
else {
|
|
96
96
|
_options.logger && _options.logger('Proxy Init: reuse map-md from former data');
|
|
@@ -150,7 +150,7 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
|
|
|
150
150
|
onProxyRes: onProxyRes,
|
|
151
151
|
onProxyReq: onProxyReq,
|
|
152
152
|
headers: {
|
|
153
|
-
'user-agent': '
|
|
153
|
+
'user-agent': 'AppleWebKit PitanguiBridge/2.2.485407.0-[HARDWARE=iPhone10_4][SOFTWARE=15.5][DEVICE=iPhone]',
|
|
154
154
|
'accept-language': _options.acceptLanguage,
|
|
155
155
|
'authority': `www.${_options.baseAmazonPage}`
|
|
156
156
|
},
|
|
@@ -372,7 +372,7 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
|
|
|
372
372
|
|
|
373
373
|
app.use(myProxy);
|
|
374
374
|
app.get('/cookie-success', function(req, res) {
|
|
375
|
-
res.send(
|
|
375
|
+
res.send(_options.proxyCloseWindowHTML);
|
|
376
376
|
});
|
|
377
377
|
const server = app.listen(_options.proxyPort, _options.proxyListenBind, function() {
|
|
378
378
|
_options.logger && _options.logger('Alexa-Cookie: Proxy-Server listening on port ' + server.address().port);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alexa-cookie2",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "Generate Cookie and CSRF for Alexa Remote",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Apollon77",
|
|
@@ -22,16 +22,16 @@
|
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"cookie": "^0.5.0",
|
|
25
|
-
"express": "^4.18.
|
|
25
|
+
"express": "^4.18.2",
|
|
26
26
|
"http-proxy-middleware": "^2.0.6",
|
|
27
27
|
"http-proxy-response-rewrite": "^0.0.1",
|
|
28
28
|
"https": "^1.0.0",
|
|
29
29
|
"querystring": "^0.2.1"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@alcalzone/release-script": "^3.
|
|
32
|
+
"@alcalzone/release-script": "^3.6.0",
|
|
33
33
|
"@alcalzone/release-script-plugin-license": "^3.5.9",
|
|
34
|
-
"eslint": "^8.
|
|
34
|
+
"eslint": "^8.46.0"
|
|
35
35
|
},
|
|
36
36
|
"repository": {
|
|
37
37
|
"type": "git",
|