alexa-cookie2 5.0.0 → 5.0.2

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/README.md CHANGED
@@ -16,13 +16,19 @@ If the automatic authentication fails (which is more common case in the meantime
16
16
 
17
17
  Starting with version 2.0 of this library the proxy approach was changed to be more "as the Amazon mobile Apps" which registers a device at Amazon and uses OAuth tokens to handle the automatic refresh of the cookies afterwards. This should work seamless. A cookie is valid for 14 days, so it is preferred to refresh the cookie after 5-13 days (please report if it should be shorter).
18
18
 
19
+ ## Troubleshooting for getting the cookie and tokens initially
20
+ If you still use the E-Mail or SMS based 2FA flow then this might not work. Please update the 2FA/OTP method in the amazon settings to the current process.
21
+
22
+ If you open the Proxy URL from a mobile device where also the Alexa App is installed on it might be that it do not work because Amazon might open the Alexa App. So please use a device or PC where the Alexa App is not installed
23
+
24
+ If you see a page that tells you that "alexa.amazon.xx is deprecated" and you should use the alexa app and with a QR code on it when you enter the Proxy URL" then this means that you call the proxy URL with a different IP/Domainname then the one you entered in the "proxy own IP" settings or you adjusted the IP shown in the Adapter configuration. The "proxy own IP" setting **needs to** match the IP/Domainname you use to call the proxy URL!
25
+
19
26
  ## Example:
20
27
  See example folder!
21
28
 
22
29
  * **example.js** shows how to use the library to initially get a cookie
23
30
  * **refresh.js** shown how to use the library to refresh the cookies
24
31
 
25
-
26
32
  ## Usage
27
33
  Special note for callback return for parameter result:
28
34
 
@@ -42,9 +48,6 @@ Please use the new method "refreshAlexaCookie" to refresh the cookie data. It ta
42
48
 
43
49
  Since 4.0.0 of this library a new key called "macDms" is also returned when cookies are generated or refreshed. This is (right now Oct 2021) needed to use the Push Connection (alexa-remote library). Better strt also persisting this field, might be needed more later on.
44
50
 
45
- ## Troubleshooting
46
- If you still use the SMS based 2FA flow then this might now work. Please update the 2fa method in the amazon settings to the current process.
47
-
48
51
  ## Thanks:
49
52
  A big thanks go to soef for the initial version of this library and to many other community users to support in finding out what Amazon changes here and there.
50
53
 
@@ -52,6 +55,13 @@ Partly based on [Amazon Alexa Remote Control](http://blog.loetzimmer.de/2017/10/
52
55
  Thank you for that work.
53
56
 
54
57
  ## Changelog:
58
+ ### 5.0.2 (2023-11-25)
59
+ * (Apollon77) Adjust some texts
60
+
61
+ ### 5.0.1 (2023-11-24)
62
+ * (adn77) make registered device name configurable by Appname
63
+ * (Apollon77) Prevent some error/crash cases
64
+
55
65
  ### 5.0.0 (2023-09-08)
56
66
  * IMPORTANT: Node.js 16 is now required minimum Node.js version!
57
67
  * (Apollon77) Enhance registration process by also registering the app capabilities to allow usage of new HTTP/2 push connection
package/alexa-cookie.js CHANGED
@@ -350,7 +350,7 @@ function AlexaCookie() {
350
350
  }
351
351
  if (_options.setupProxy) {
352
352
  if (proxyServer) {
353
- errMessage += ` You can try to get the cookie manually by opening http://${_options.proxyOwnIp}:${_options.proxyPort}/ with your browser.`;
353
+ errMessage += ` Please open http://${_options.proxyOwnIp}:${_options.proxyPort}/ with your browser and login to Amazon. The cookie will be output here after successfull login.`;
354
354
  } else {
355
355
  amazonProxy.initAmazonProxy(_options, prepareResult,
356
356
  (server) => {
@@ -361,7 +361,7 @@ function AlexaCookie() {
361
361
  if (!_options.proxyPort || _options.proxyPort === 0) {
362
362
  _options.proxyPort = proxyServer.address().port;
363
363
  }
364
- errMessage += ` You can try to get the cookie manually by opening http://${_options.proxyOwnIp}:${_options.proxyPort}/ with your browser.`;
364
+ errMessage += ` Please open http://${_options.proxyOwnIp}:${_options.proxyPort}/ with your browser and login to Amazon. The cookie will be output here after successfull login.`;
365
365
  callback && callback(new Error(errMessage), null);
366
366
  }
367
367
  );
@@ -386,7 +386,7 @@ function AlexaCookie() {
386
386
  if (!_options.proxyPort || _options.proxyPort === 0) {
387
387
  _options.proxyPort = proxyServer.address().port;
388
388
  }
389
- const errMessage = `You can try to get the cookie manually by opening http://${_options.proxyOwnIp}:${_options.proxyPort}/ with your browser.`;
389
+ const errMessage = `Please open http://${_options.proxyOwnIp}:${_options.proxyPort}/ with your browser and login to Amazon. The cookie will be output here after successfull login.`;
390
390
  callback && callback(new Error(errMessage), null);
391
391
  });
392
392
  }
@@ -442,7 +442,7 @@ function AlexaCookie() {
442
442
  'domain': 'Device',
443
443
  'app_version': apiCallVersion,
444
444
  'device_type': 'A2IVLV5VM2W81',
445
- 'device_name': '%FIRST_NAME%\u0027s%DUPE_STRATEGY_1ST%ioBroker Alexa2',
445
+ 'device_name': '%FIRST_NAME%\u0027s%DUPE_STRATEGY_1ST%' + _options.deviceAppName,
446
446
  'os_version': '16.6',
447
447
  'device_serial': deviceSerial,
448
448
  'device_model': 'iPhone',
@@ -8,12 +8,17 @@ const alexaCookie = require('../alexa-cookie');
8
8
 
9
9
  const config = {
10
10
  logger: console.log,
11
- amazonPage: 'amazon.com', // optional: possible to use with different countries, default is 'amazon.de'
12
- acceptLanguage: 'en-US', // optional: webpage language, should match to amazon-Page, default is 'de-DE'
11
+ proxyOwnIp: '...', // required if proxy enabled: provide the own IP with which you later access the proxy.
12
+ // Providing/Using a hostname here can lead to issues!
13
+ // Needed to set up all rewriting and proxy stuff internally
14
+
15
+ // The following options are optional. Try without them first and just use really needed ones!!
16
+
17
+ amazonPage: 'amazon.de', // optional: possible to use with different countries, default is 'amazon.de'
18
+ acceptLanguage: 'de-DE', // optional: webpage language, should match to amazon-Page, default is 'de-DE'
13
19
  userAgent: '...', // optional: own userAgent to use for all request, overwrites default one, should not be needed
14
20
  proxyOnly: true, // optional: should only the proxy method be used? When no email/password are provided this will set to true automatically, default: false
15
21
  setupProxy: true, // optional: should the library setup a proxy to get cookie when automatic way did not worked? Default false!
16
- proxyOwnIp: '...', // required if proxy enabled: provide own IP or hostname to later access the proxy. needed to setup all rewriting and proxy stuff internally
17
22
  proxyPort: 3456, // optional: use this port for the proxy, default is 0 means random port is selected
18
23
  proxyListenBind: '0.0.0.0',// optional: set this to bind the proxy to a special IP, default is '0.0.0.0'
19
24
  proxyLogLevel: 'info', // optional: Loglevel of Proxy, default 'warn'
package/lib/proxy.js CHANGED
@@ -28,7 +28,7 @@ function addCookies(Cookie, headers) {
28
28
  }
29
29
  Cookie = '';
30
30
  for (const name of Object.keys(cookies)) {
31
- Cookie += name + '=' + cookies[name] + '; ';
31
+ Cookie += `${name}=${cookies[name]}; `;
32
32
  }
33
33
  Cookie = Cookie.replace(/[; ]*$/, '');
34
34
  return Cookie;
@@ -175,7 +175,7 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
175
175
 
176
176
  function router(req) {
177
177
  const url = (req.originalUrl || req.url);
178
- _options.logger && _options.logger('Router: ' + url + ' / ' + req.method + ' / ' + JSON.stringify(req.headers));
178
+ _options.logger && _options.logger(`Router: ${url} / ${req.method} / ${JSON.stringify(req.headers)}`);
179
179
  if (req.headers.host === `${_options.proxyOwnIp}:${_options.proxyPort}`) {
180
180
  if (url.startsWith(`/www.${_options.baseAmazonPage}/`)) {
181
181
  return `https://www.${_options.baseAmazonPage}`;
@@ -190,7 +190,7 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
190
190
  }
191
191
  if (url === '/') { // initial redirect
192
192
  returnedInitUrl = `https://www.${_options.baseAmazonPage}/ap/signin?openid.return_to=https%3A%2F%2Fwww.${_options.baseAmazonPage}%2Fap%2Fmaplanding&openid.assoc_handle=amzn_dp_project_dee_ios${_options.baseAmazonPageHandle}&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&pageId=amzn_dp_project_dee_ios${_options.baseAmazonPageHandle}&accountStatusPolicy=P1&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.mode=checkid_setup&openid.ns.oa2=http%3A%2F%2Fwww.${_options.baseAmazonPage}%2Fap%2Fext%2Foauth%2F2&openid.oa2.client_id=device%3A${deviceId}&openid.ns.pape=http%3A%2F%2Fspecs.openid.net%2Fextensions%2Fpape%2F1.0&openid.oa2.response_type=code&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.pape.max_auth_age=0&openid.oa2.scope=device_auth_access&openid.oa2.code_challenge_method=S256&openid.oa2.code_challenge=${code_challenge}&language=${_options.amazonPageProxyLanguage}`;
193
- _options.logger && _options.logger('Alexa-Cookie: Initial Page Request: ' + returnedInitUrl);
193
+ _options.logger && _options.logger(`Alexa-Cookie: Initial Page Request: ${returnedInitUrl}`);
194
194
  return returnedInitUrl;
195
195
  }
196
196
  else {
@@ -201,12 +201,12 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
201
201
  }
202
202
 
203
203
  function onError(err, req, res) {
204
- _options.logger && _options.logger('ERROR: ' + err);
204
+ _options.logger && _options.logger(`ERROR: ${err}`);
205
205
  try {
206
206
  res.writeHead(500, {
207
207
  'Content-Type': 'text/plain'
208
208
  });
209
- res.end('Proxy-Error: ' + err);
209
+ res.end(`Proxy-Error: ${err}`);
210
210
  } catch (err) {
211
211
  // ignore
212
212
  }
@@ -239,18 +239,18 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
239
239
  if (url.endsWith('.ico') || url.endsWith('.js') || url.endsWith('.ttf') || url.endsWith('.svg') || url.endsWith('.png') || url.endsWith('.appcache')) return;
240
240
  //if (url.startsWith('/ap/uedata')) return;
241
241
 
242
- _options.logger && _options.logger('Alexa-Cookie: Proxy-Request: ' + req.method + ' ' + url);
242
+ _options.logger && _options.logger(`Alexa-Cookie: Proxy-Request: ${req.method} ${url}`);
243
243
  //_options.logger && _options.logger('Alexa-Cookie: Proxy-Request-Data: ' + customStringify(proxyReq, null, 2));
244
244
 
245
245
  if (typeof proxyReq.getHeader === 'function') {
246
- _options.logger && _options.logger('Alexa-Cookie: Headers: ' + JSON.stringify(proxyReq.getHeaders()));
246
+ _options.logger && _options.logger(`Alexa-Cookie: Headers: ${JSON.stringify(proxyReq.getHeaders())}`);
247
247
  let reqCookie = proxyReq.getHeader('cookie');
248
248
  if (reqCookie === undefined) {
249
249
  reqCookie = '';
250
250
  }
251
251
  for (const cookie of Object.keys(initialCookies)) {
252
- if (!reqCookie.includes(cookie + '=')) {
253
- reqCookie += '; ' + cookie + '=' + initialCookies[cookie];
252
+ if (!reqCookie.includes(`${cookie}=`)) {
253
+ reqCookie += `; ${cookie}=${initialCookies[cookie]}`;
254
254
  }
255
255
  }
256
256
  if (reqCookie.startsWith('; ')) {
@@ -260,9 +260,9 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
260
260
  if (!proxyCookies.length) {
261
261
  proxyCookies = reqCookie;
262
262
  } else {
263
- proxyCookies += '; ' + reqCookie;
263
+ proxyCookies += `; ${reqCookie}`;
264
264
  }
265
- _options.logger && _options.logger('Alexa-Cookie: Headers: ' + JSON.stringify(proxyReq.getHeaders()));
265
+ _options.logger && _options.logger(`Alexa-Cookie: Headers: ${JSON.stringify(proxyReq.getHeaders())}`);
266
266
  }
267
267
 
268
268
  let modified = false;
@@ -271,11 +271,11 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
271
271
  const fixedReferer = replaceHostsBack(proxyReq.getHeader('referer'));
272
272
  if (fixedReferer ) {
273
273
  proxyReq.setHeader('referer', fixedReferer);
274
- _options.logger && _options.logger('Alexa-Cookie: Modify headers: Changed Referer: ' + fixedReferer);
274
+ _options.logger && _options.logger(`Alexa-Cookie: Modify headers: Changed Referer: ${fixedReferer}`);
275
275
  modified = true;
276
276
  }
277
277
  }
278
- if (typeof proxyReq.getHeader === 'function' && proxyReq.getHeader('origin') !== 'https://' + proxyReq.getHeader('host')) {
278
+ if (typeof proxyReq.getHeader === 'function' && proxyReq.getHeader('origin') !== `https://${proxyReq.getHeader('host')}`) {
279
279
  proxyReq.setHeader('origin', `https://www.${_options.baseAmazonPage}`);
280
280
  _options.logger && _options.logger('Alexa-Cookie: Modify headers: Delete Origin');
281
281
  modified = true;
@@ -286,7 +286,7 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
286
286
  postBody += chunk.toString(); // convert Buffer to string
287
287
  });
288
288
  }
289
- _options.proxyLogLevel === 'debug' && _options.logger && _options.logger('Alexa-Cookie: Proxy-Request: (modified:' + modified + ')' + customStringify(proxyReq, null, 2));
289
+ _options.proxyLogLevel === 'debug' && _options.logger && _options.logger(`Alexa-Cookie: Proxy-Request: (modified:${modified})${customStringify(proxyReq, null, 2)}`);
290
290
  }
291
291
 
292
292
  function onProxyRes(proxyRes, req, res) {
@@ -296,9 +296,9 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
296
296
  //_options.logger && _options.logger('Proxy-Response: ' + customStringify(proxyRes, null, 2));
297
297
  let reqestHost = null;
298
298
  if (proxyRes.socket && proxyRes.socket._host) reqestHost = proxyRes.socket._host;
299
- _options.logger && _options.logger('Alexa-Cookie: Proxy Response from Host: ' + reqestHost);
300
- _options.proxyLogLevel === 'debug' && _options.logger && _options.logger('Alexa-Cookie: Proxy-Response Headers: ' + customStringify(proxyRes.headers, null, 2));
301
- _options.proxyLogLevel === 'debug' && _options.logger && _options.logger('Alexa-Cookie: Proxy-Response Outgoing: ' + customStringify(proxyRes.socket.parser.outgoing, null, 2));
299
+ _options.logger && _options.logger(`Alexa-Cookie: Proxy Response from Host: ${reqestHost}`);
300
+ _options.proxyLogLevel === 'debug' && _options.logger && _options.logger(`Alexa-Cookie: Proxy-Response Headers: ${customStringify(proxyRes.headers, null, 2)}`);
301
+ _options.proxyLogLevel === 'debug' && _options.logger && _options.logger(`Alexa-Cookie: Proxy-Response Outgoing: ${customStringify(proxyRes.socket.parser.outgoing, null, 2)}`);
302
302
  //_options.logger && _options.logger('Proxy-Response RES!!: ' + customStringify(res, null, 2));
303
303
 
304
304
  if (proxyRes && proxyRes.headers && proxyRes.headers['set-cookie']) {
@@ -308,7 +308,7 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
308
308
  }
309
309
  proxyCookies = addCookies(proxyCookies, proxyRes.headers);
310
310
  }
311
- _options.logger && _options.logger('Alexa-Cookie: Cookies handled: ' + JSON.stringify(proxyCookies));
311
+ _options.logger && _options.logger(`Alexa-Cookie: Cookies handled: ${JSON.stringify(proxyCookies)}`);
312
312
 
313
313
  if (
314
314
  (proxyRes.socket && proxyRes.socket._host === `www.${_options.baseAmazonPage}` && proxyRes.socket.parser.outgoing && proxyRes.socket.parser.outgoing.method === 'GET' && proxyRes.socket.parser.outgoing.path.startsWith('/ap/maplanding')) ||
@@ -324,8 +324,8 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
324
324
  proxyRes.headers.location = `http://${_options.proxyOwnIp}:${_options.proxyPort}/cookie-success`;
325
325
  delete proxyRes.headers.referer;
326
326
 
327
- _options.logger && _options.logger('Alexa-Cookie: Proxy catched cookie: ' + proxyCookies);
328
- _options.logger && _options.logger('Alexa-Cookie: Proxy catched parameters: ' + JSON.stringify(queryParams));
327
+ _options.logger && _options.logger(`Alexa-Cookie: Proxy catched cookie: ${proxyCookies}`);
328
+ _options.logger && _options.logger(`Alexa-Cookie: Proxy catched parameters: ${JSON.stringify(queryParams)}`);
329
329
 
330
330
  callbackCookie && callbackCookie(null, {
331
331
  'loginCookie': proxyCookies,
@@ -340,12 +340,12 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
340
340
 
341
341
  // If we detect a redirect, rewrite the location header
342
342
  if (proxyRes.headers.location) {
343
- _options.logger && _options.logger('Redirect: Original Location ----> ' + proxyRes.headers.location);
343
+ _options.logger && _options.logger(`Redirect: Original Location ----> ${proxyRes.headers.location}`);
344
344
  proxyRes.headers.location = replaceHosts(proxyRes.headers.location);
345
345
  if (reqestHost && proxyRes.headers.location.startsWith('/')) {
346
- proxyRes.headers.location = `http://${_options.proxyOwnIp}:${_options.proxyPort}/` + reqestHost + proxyRes.headers.location;
346
+ proxyRes.headers.location = `http://${_options.proxyOwnIp}:${_options.proxyPort}/${reqestHost}${proxyRes.headers.location}`;
347
347
  }
348
- _options.logger && _options.logger('Redirect: Final Location ----> ' + proxyRes.headers.location);
348
+ _options.logger && _options.logger(`Redirect: Final Location ----> ${proxyRes.headers.location}`);
349
349
  return;
350
350
  }
351
351
 
@@ -374,12 +374,16 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
374
374
  app.get('/cookie-success', function(req, res) {
375
375
  res.send(_options.proxyCloseWindowHTML);
376
376
  });
377
+ if (_options.proxyPort< 1 || _options.proxyPort > 65535) {
378
+ _options.logger && _options.logger(`Alexa-Cookie: Error: Port ${_options.proxyPort} invalid. Use random port.`);
379
+ _options.proxyPort = undefined;
380
+ }
377
381
  const server = app.listen(_options.proxyPort, _options.proxyListenBind, function() {
378
- _options.logger && _options.logger('Alexa-Cookie: Proxy-Server listening on port ' + server.address().port);
382
+ _options.logger && _options.logger(`Alexa-Cookie: Proxy-Server listening on port ${server.address().port}`);
379
383
  callbackListening && callbackListening(server);
380
384
  callbackListening = null;
381
385
  }).on('error', err => {
382
- _options.logger && _options.logger('Alexa-Cookie: Proxy-Server Error: ' + err);
386
+ _options.logger && _options.logger(`Alexa-Cookie: Proxy-Server Error: ${err}`);
383
387
  callbackListening && callbackListening(null);
384
388
  callbackListening = null;
385
389
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alexa-cookie2",
3
- "version": "5.0.0",
3
+ "version": "5.0.2",
4
4
  "description": "Generate Cookie and CSRF for Alexa Remote",
5
5
  "author": {
6
6
  "name": "Apollon77",
@@ -21,7 +21,7 @@
21
21
  "layla.amazon.de"
22
22
  ],
23
23
  "dependencies": {
24
- "cookie": "^0.5.0",
24
+ "cookie": "^0.6.0",
25
25
  "express": "^4.18.2",
26
26
  "http-proxy-middleware": "^2.0.6",
27
27
  "http-proxy-response-rewrite": "^0.0.1",
@@ -31,7 +31,7 @@
31
31
  "devDependencies": {
32
32
  "@alcalzone/release-script": "^3.6.0",
33
33
  "@alcalzone/release-script-plugin-license": "^3.5.9",
34
- "eslint": "^8.48.0"
34
+ "eslint": "^8.54.0"
35
35
  },
36
36
  "repository": {
37
37
  "type": "git",