alexa-cookie2 5.0.2 → 5.0.4

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.
@@ -0,0 +1,184 @@
1
+ const assert = require('assert');
2
+ const fs = require('fs');
3
+ const os = require('os');
4
+ const path = require('path');
5
+ const vm = require('vm');
6
+
7
+ const testName = 'proxy-initial-url';
8
+ const outputDir = process.env.ALEXA_COOKIE_TEST_OUTPUT_DIR || path.join(__dirname, '..', 'test-output');
9
+ const outputFile = path.join(outputDir, `${testName}.txt`);
10
+ const lines = [];
11
+
12
+ function line(value = '') {
13
+ lines.push(value);
14
+ }
15
+
16
+ function writeOutput() {
17
+ fs.mkdirSync(outputDir, { recursive: true });
18
+ fs.writeFileSync(outputFile, `${lines.join('\n')}\n`);
19
+ }
20
+
21
+ function recordAssertion(description, fn) {
22
+ try {
23
+ fn();
24
+ line(`${description}: PASS`);
25
+ } catch (err) {
26
+ line(`${description}: FAIL`);
27
+ writeOutput();
28
+ throw err;
29
+ }
30
+ }
31
+
32
+ const proxyFile = path.join(__dirname, '..', 'lib', 'proxy.js');
33
+ const source = fs.readFileSync(proxyFile, 'utf8');
34
+
35
+ let capturedProxyOptions;
36
+
37
+ function createExpressStub() {
38
+ return {
39
+ use() {},
40
+ get() {},
41
+ listen() {
42
+ const server = {
43
+ address: () => ({ port: 3456 }),
44
+ on: () => server
45
+ };
46
+ return server;
47
+ }
48
+ };
49
+ }
50
+
51
+ function loadProxyModule() {
52
+ const module = { exports: {} };
53
+ const sandbox = {
54
+ Buffer,
55
+ URL,
56
+ __dirname: path.dirname(proxyFile),
57
+ console,
58
+ module,
59
+ exports: module.exports,
60
+ require(name) {
61
+ if (name === 'express') return createExpressStub;
62
+ if (name === 'http-proxy-response-rewrite') return () => {};
63
+ if (name === 'http-proxy-middleware') {
64
+ return {
65
+ createProxyMiddleware(_context, options) {
66
+ capturedProxyOptions = options;
67
+ return function proxyMiddleware() {};
68
+ }
69
+ };
70
+ }
71
+ if (name === 'cookie') {
72
+ return { parse: () => ({}) };
73
+ }
74
+ return require(name);
75
+ }
76
+ };
77
+ vm.runInNewContext(source, sandbox, { filename: proxyFile });
78
+ return module.exports;
79
+ }
80
+
81
+ function applyPathRewrite(pathname, req) {
82
+ const rewrite = capturedProxyOptions.pathRewrite;
83
+ if (typeof rewrite === 'function') return rewrite(pathname, req);
84
+ for (const pattern of Object.keys(rewrite)) {
85
+ const regex = new RegExp(pattern);
86
+ if (regex.test(pathname)) return pathname.replace(regex, rewrite[pattern]);
87
+ }
88
+ return pathname;
89
+ }
90
+
91
+ const proxyModule = loadProxyModule();
92
+ const formerDataStorePath = path.join(os.tmpdir(), `alexa-cookie-proxy-test-${Date.now()}.json`);
93
+
94
+ try {
95
+ const input = {
96
+ proxyOwnIp: '127.0.0.1',
97
+ proxyPort: 3456,
98
+ proxyListenBind: '0.0.0.0',
99
+ baseAmazonPage: 'amazon.co.uk',
100
+ baseAmazonPageHandle: '_uk',
101
+ amazonPageProxyLanguage: 'en_GB',
102
+ acceptLanguage: 'en-GB',
103
+ proxyLogLevel: 'silent',
104
+ formerDataStorePath
105
+ };
106
+ proxyModule.initAmazonProxy(input);
107
+
108
+ const req = {
109
+ method: 'GET',
110
+ url: '/',
111
+ headers: {
112
+ host: '127.0.0.1:3456'
113
+ }
114
+ };
115
+
116
+ const target = capturedProxyOptions.router(req);
117
+ const rewrittenPath = applyPathRewrite(req.url, req);
118
+ const targetUrl = new URL(target);
119
+ const rewrittenUrl = new URL(rewrittenPath, target);
120
+
121
+ line('TEST: proxy initial URL');
122
+ line('');
123
+ line('CODE UNDER TEST:');
124
+ line('- lib/proxy.js: router()');
125
+ line('- lib/proxy.js: pathRewrite / rewriteProxyPath()');
126
+ line('- lib/proxy.js: buildInitialUrl()');
127
+ line('');
128
+ line('INPUT:');
129
+ line(`baseAmazonPage: ${input.baseAmazonPage}`);
130
+ line(`baseAmazonPageHandle: ${input.baseAmazonPageHandle}`);
131
+ line(`proxy host header: ${req.headers.host}`);
132
+ line(`request url: ${req.url}`);
133
+ line('');
134
+ line('OBSERVED:');
135
+ line(`router target host: ${targetUrl.host}`);
136
+ line(`router target search: ${targetUrl.search}`);
137
+ line(`rewritten pathname: ${rewrittenUrl.pathname}`);
138
+ line(`rewritten openid.assoc_handle: ${rewrittenUrl.searchParams.get('openid.assoc_handle')}`);
139
+ line(`rewritten pageId: ${rewrittenUrl.searchParams.get('pageId')}`);
140
+ line(`rewritten openid.return_to: ${rewrittenUrl.searchParams.get('openid.return_to')}`);
141
+ line(`rewritten openid.ns.oa2: ${rewrittenUrl.searchParams.get('openid.ns.oa2')}`);
142
+ line(`rewritten path starts with /ap/signin?: ${rewrittenPath.startsWith('/ap/signin?')}`);
143
+ line(`rewritten path contains openid.return_to: ${rewrittenPath.includes('openid.return_to=')}`);
144
+ line(`rewritten path contains regional handle: ${rewrittenPath.includes('amzn_dp_project_dee_ios_uk')}`);
145
+ line(`rewritten path contains code challenge: ${rewrittenPath.includes('openid.oa2.code_challenge=')}`);
146
+ line('');
147
+ line('ASSERTIONS:');
148
+ recordAssertion('router target host === "www.amazon.co.uk"', () => {
149
+ assert.strictEqual(targetUrl.host, 'www.amazon.co.uk');
150
+ });
151
+ recordAssertion('router target search === ""', () => {
152
+ assert.ok(targetUrl.search === '', 'router target search must be empty');
153
+ });
154
+ recordAssertion('rewritten path starts with "/ap/signin?"', () => {
155
+ assert.ok(rewrittenPath.startsWith('/ap/signin?'), `expected signin path, got ${rewrittenPath}`);
156
+ });
157
+ recordAssertion('rewritten assoc handle === "amzn_dp_project_dee_ios_uk"', () => {
158
+ assert.strictEqual(rewrittenUrl.searchParams.get('openid.assoc_handle'), 'amzn_dp_project_dee_ios_uk');
159
+ });
160
+ recordAssertion('rewritten pageId === "amzn_dp_project_dee_ios_uk"', () => {
161
+ assert.strictEqual(rewrittenUrl.searchParams.get('pageId'), 'amzn_dp_project_dee_ios_uk');
162
+ });
163
+ recordAssertion('rewritten path contains "openid.return_to="', () => {
164
+ assert.ok(rewrittenPath.includes('openid.return_to='));
165
+ });
166
+ recordAssertion('rewritten path contains regional "_uk" handle', () => {
167
+ assert.ok(rewrittenPath.includes('amzn_dp_project_dee_ios_uk'));
168
+ });
169
+ recordAssertion('rewritten path contains "openid.oa2.code_challenge="', () => {
170
+ assert.ok(rewrittenPath.includes('openid.oa2.code_challenge='));
171
+ });
172
+ line('');
173
+ line('RESULT: PASS');
174
+ writeOutput();
175
+ } catch (err) {
176
+ if (!lines.includes('RESULT: PASS')) {
177
+ line('');
178
+ line('RESULT: FAIL');
179
+ writeOutput();
180
+ }
181
+ throw err;
182
+ } finally {
183
+ fs.rmSync(formerDataStorePath, { force: true });
184
+ }
@@ -0,0 +1,170 @@
1
+ const assert = require('assert');
2
+ const fs = require('fs');
3
+ const os = require('os');
4
+ const path = require('path');
5
+ const vm = require('vm');
6
+
7
+ const testName = 'proxy-success-requires-auth-code';
8
+ const outputDir = process.env.ALEXA_COOKIE_TEST_OUTPUT_DIR || path.join(__dirname, '..', 'test-output');
9
+ const outputFile = path.join(outputDir, `${testName}.txt`);
10
+ const lines = [];
11
+
12
+ function line(value = '') {
13
+ lines.push(value);
14
+ }
15
+
16
+ function writeOutput() {
17
+ fs.mkdirSync(outputDir, { recursive: true });
18
+ fs.writeFileSync(outputFile, `${lines.join('\n')}\n`);
19
+ }
20
+
21
+ function recordAssertion(description, fn) {
22
+ try {
23
+ fn();
24
+ line(`${description}: PASS`);
25
+ } catch (err) {
26
+ line(`${description}: FAIL`);
27
+ writeOutput();
28
+ throw err;
29
+ }
30
+ }
31
+
32
+ const proxyFile = path.join(__dirname, '..', 'lib', 'proxy.js');
33
+ const source = fs.readFileSync(proxyFile, 'utf8');
34
+
35
+ let capturedProxyOptions;
36
+
37
+ function createExpressStub() {
38
+ return {
39
+ use() {},
40
+ get() {},
41
+ listen() {
42
+ const server = {
43
+ address: () => ({ port: 3456 }),
44
+ on: () => server
45
+ };
46
+ return server;
47
+ }
48
+ };
49
+ }
50
+
51
+ function loadProxyModule() {
52
+ capturedProxyOptions = undefined;
53
+ const module = { exports: {} };
54
+ const sandbox = {
55
+ Buffer,
56
+ URL,
57
+ __dirname: path.dirname(proxyFile),
58
+ console,
59
+ module,
60
+ exports: module.exports,
61
+ require(name) {
62
+ if (name === 'express') return createExpressStub;
63
+ if (name === 'http-proxy-response-rewrite') return () => {};
64
+ if (name === 'http-proxy-middleware') {
65
+ return {
66
+ createProxyMiddleware(_context, options) {
67
+ capturedProxyOptions = options;
68
+ return function proxyMiddleware() {};
69
+ }
70
+ };
71
+ }
72
+ if (name === 'cookie') {
73
+ return { parse: () => ({}) };
74
+ }
75
+ return require(name);
76
+ }
77
+ };
78
+ vm.runInNewContext(source, sandbox, { filename: proxyFile });
79
+ return module.exports;
80
+ }
81
+
82
+ function createProxyResponse(location) {
83
+ return {
84
+ statusCode: 302,
85
+ headers: {
86
+ location
87
+ },
88
+ socket: {
89
+ _host: 'www.amazon.de',
90
+ parser: {
91
+ outgoing: {
92
+ method: 'POST',
93
+ path: '/ap/signin',
94
+ getHeader() {
95
+ return undefined;
96
+ }
97
+ }
98
+ }
99
+ }
100
+ };
101
+ }
102
+
103
+ const proxyModule = loadProxyModule();
104
+ const formerDataStorePath = path.join(os.tmpdir(), `alexa-cookie-proxy-success-test-${Date.now()}.json`);
105
+ let callbackData;
106
+
107
+ try {
108
+ const input = {
109
+ proxyOwnIp: '127.0.0.1',
110
+ proxyPort: 3456,
111
+ proxyListenBind: '0.0.0.0',
112
+ baseAmazonPage: 'amazon.de',
113
+ baseAmazonPageHandle: '_de',
114
+ amazonPageProxyLanguage: 'de_DE',
115
+ acceptLanguage: 'de-DE',
116
+ proxyLogLevel: 'silent',
117
+ formerDataStorePath
118
+ };
119
+ proxyModule.initAmazonProxy(input, (_err, data) => {
120
+ callbackData = data;
121
+ });
122
+
123
+ const responseLocation = 'https://www.amazon.de/ap/maplanding?openid.mode=id_res&openid.return_to=https%3A%2F%2Fwww.amazon.de%2Fap%2Fmaplanding';
124
+ const proxyRes = createProxyResponse(responseLocation);
125
+ const req = {
126
+ method: 'POST',
127
+ url: '/www.amazon.de/ap/signin',
128
+ originalUrl: '/www.amazon.de/ap/signin'
129
+ };
130
+
131
+ capturedProxyOptions.onProxyRes(proxyRes, req, {});
132
+
133
+ line('TEST: proxy success requires auth code');
134
+ line('');
135
+ line('CODE UNDER TEST:');
136
+ line('- lib/proxy.js: onProxyRes()');
137
+ line('- lib/proxy.js: maplanding success detection');
138
+ line('');
139
+ line('INPUT:');
140
+ line(`response location: ${responseLocation}`);
141
+ line(`request method: ${req.method}`);
142
+ line(`request originalUrl: ${req.originalUrl}`);
143
+ line('');
144
+ line('OBSERVED:');
145
+ line(`callback data present: ${callbackData !== undefined}`);
146
+ line(`final response location: ${proxyRes.headers.location}`);
147
+ line('');
148
+ line('ASSERTIONS:');
149
+ recordAssertion('callbackData === undefined', () => {
150
+ assert.strictEqual(callbackData === undefined, true);
151
+ });
152
+ recordAssertion('final location !== local /cookie-success', () => {
153
+ assert.notStrictEqual(proxyRes.headers.location, 'http://127.0.0.1:3456/cookie-success');
154
+ });
155
+ recordAssertion('final location preserves proxied maplanding path', () => {
156
+ assert.strictEqual(proxyRes.headers.location, 'http://127.0.0.1:3456/www.amazon.de/ap/maplanding?openid.mode=id_res&openid.return_to=https%3A%2F%2Fwww.amazon.de%2Fap%2Fmaplanding');
157
+ });
158
+ line('');
159
+ line('RESULT: PASS');
160
+ writeOutput();
161
+ } catch (err) {
162
+ if (!lines.includes('RESULT: PASS')) {
163
+ line('');
164
+ line('RESULT: FAIL');
165
+ writeOutput();
166
+ }
167
+ throw err;
168
+ } finally {
169
+ fs.rmSync(formerDataStorePath, { force: true });
170
+ }
@@ -0,0 +1,270 @@
1
+ const assert = require('assert');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const vm = require('vm');
5
+ const EventEmitter = require('events');
6
+
7
+ const testName = 'refresh-skips-app-registration';
8
+ const outputDir = process.env.ALEXA_COOKIE_TEST_OUTPUT_DIR || path.join(__dirname, '..', 'test-output');
9
+ const outputFile = path.join(outputDir, `${testName}.txt`);
10
+ const lines = [];
11
+
12
+ function line(value = '') {
13
+ lines.push(value);
14
+ }
15
+
16
+ function writeOutput() {
17
+ fs.mkdirSync(outputDir, { recursive: true });
18
+ fs.writeFileSync(outputFile, `${lines.join('\n')}\n`);
19
+ }
20
+
21
+ function recordAssertion(description, fn) {
22
+ try {
23
+ fn();
24
+ line(`${description}: PASS`);
25
+ } catch (err) {
26
+ line(`${description}: FAIL`);
27
+ writeOutput();
28
+ throw err;
29
+ }
30
+ }
31
+
32
+ function parseCookies(cookieHeader) {
33
+ const result = {};
34
+ for (const part of String(cookieHeader || '').split(';')) {
35
+ const trimmed = part.trim();
36
+ if (!trimmed) continue;
37
+ const idx = trimmed.indexOf('=');
38
+ if (idx === -1) continue;
39
+ result[trimmed.slice(0, idx)] = trimmed.slice(idx + 1);
40
+ }
41
+ return result;
42
+ }
43
+
44
+ const cookieFile = path.join(__dirname, '..', 'alexa-cookie.js');
45
+ const source = fs.readFileSync(cookieFile, 'utf8');
46
+
47
+ function loadCookieModule(overrides = {}) {
48
+ const module = { exports: {} };
49
+ const sandbox = {
50
+ Buffer,
51
+ URL,
52
+ __dirname: path.dirname(cookieFile),
53
+ console,
54
+ module,
55
+ exports: module.exports,
56
+ require(name) {
57
+ if (name === 'https' && overrides.https) return overrides.https;
58
+ if (name === './lib/proxy.js') {
59
+ return {
60
+ initAmazonProxy() {
61
+ throw new Error('proxy should not start in this test');
62
+ }
63
+ };
64
+ }
65
+ if (name === 'cookie') return { parse: parseCookies };
66
+ return require(name);
67
+ }
68
+ };
69
+ vm.runInNewContext(source, sandbox, { filename: cookieFile });
70
+ return module.exports;
71
+ }
72
+
73
+ function createFakeHttps(calls) {
74
+ function responseFor(options) {
75
+ if (options.path === '/auth/token') {
76
+ return {
77
+ statusCode: 200,
78
+ headers: { 'set-cookie': ['session-id=SID_REFRESH; Path=/; Domain=.amazon.de'] },
79
+ body: JSON.stringify({ access_token: 'ACCESS_TOKEN_AFTER_REFRESH' })
80
+ };
81
+ }
82
+ if (options.host === 'api.amazonalexa.com' && options.path === '/v1/devices/@self/capabilities') {
83
+ return { statusCode: 204, headers: {}, body: '' };
84
+ }
85
+ if (options.path === '/ap/exchangetoken/cookies') {
86
+ return {
87
+ statusCode: 200,
88
+ headers: { 'set-cookie': ['exchange-cookie=EXCHANGE_HEADER; Path=/; Domain=.amazon.de'] },
89
+ body: JSON.stringify({
90
+ response: {
91
+ tokens: {
92
+ cookies: {
93
+ '.amazon.de': [
94
+ { Name: 'session-id', Value: 'SID_LOCAL' },
95
+ { Name: 'ubid-acbde', Value: 'UBID_LOCAL' }
96
+ ]
97
+ }
98
+ }
99
+ }
100
+ })
101
+ };
102
+ }
103
+ if (options.path === '/api/language') {
104
+ return {
105
+ statusCode: 200,
106
+ headers: { 'set-cookie': ['csrf=CSRF_FROM_API; Path=/; Domain=.amazon.de'] },
107
+ body: '{}'
108
+ };
109
+ }
110
+ throw new Error(`Unexpected request: ${options.method || 'GET'} ${options.host}${options.path}`);
111
+ }
112
+
113
+ return {
114
+ request(options, callback) {
115
+ const req = new EventEmitter();
116
+ let requestBody = '';
117
+ req.write = (chunk) => {
118
+ requestBody += chunk;
119
+ };
120
+ req.end = () => {
121
+ calls.push({
122
+ method: options.method || 'GET',
123
+ host: options.host,
124
+ path: options.path,
125
+ status: null,
126
+ hasAuthorization: Boolean(options.headers && options.headers.authorization),
127
+ bodyLength: requestBody.length
128
+ });
129
+ const response = responseFor(options);
130
+ calls[calls.length - 1].status = response.statusCode;
131
+ const res = new EventEmitter();
132
+ res.statusCode = response.statusCode;
133
+ res.headers = response.headers || {};
134
+ res.socket = { end() {} };
135
+ callback(res);
136
+ if (response.body) res.emit('data', Buffer.from(response.body));
137
+ res.emit('end');
138
+ };
139
+ return req;
140
+ }
141
+ };
142
+ }
143
+
144
+ function refresh(cookieModule, options) {
145
+ return new Promise((resolve, reject) => {
146
+ cookieModule.refreshAlexaCookie(options, (err, data) => {
147
+ if (err) reject(err);
148
+ else resolve(data);
149
+ });
150
+ });
151
+ }
152
+
153
+ (async () => {
154
+ const calls = [];
155
+ const cookieModule = loadCookieModule({ https: createFakeHttps(calls) });
156
+ const formerRegistrationData = {
157
+ loginCookie: 'frc=FRC_OLD; map-md=MAPMD_OLD; session-id=SID_OLD',
158
+ localCookie: 'old-local=OLD',
159
+ refreshToken: 'REFRESH_TOKEN_OLD',
160
+ accessToken: 'ACCESS_TOKEN_OLD',
161
+ macDms: 'MAC_DMS_OLD',
162
+ csrf: 'CSRF_OLD',
163
+ amazonPage: 'amazon.de',
164
+ authorization_code: 'AUTH_CODE_FROM_LOGIN',
165
+ verifier: 'VERIFIER_FROM_LOGIN',
166
+ dataVersion: 2
167
+ };
168
+
169
+ try {
170
+ const result = await refresh(cookieModule, {
171
+ baseAmazonPage: 'amazon.de',
172
+ amazonPage: 'amazon.de',
173
+ acceptLanguage: 'de-DE',
174
+ formerRegistrationData,
175
+ logger: () => {}
176
+ });
177
+
178
+ const paths = calls.map((call) => call.path);
179
+ const capabilityCall = calls.find((call) => call.path === '/v1/devices/@self/capabilities');
180
+
181
+ line('TEST: refresh skips app registration');
182
+ line('');
183
+ line('CODE UNDER TEST:');
184
+ line('- alexa-cookie.js: refreshAlexaCookie()');
185
+ line('- alexa-cookie.js: registerTokenCapabilities()');
186
+ line('- alexa-cookie.js: getLocalCookies()');
187
+ line('');
188
+ line('INPUT:');
189
+ line('baseAmazonPage: amazon.de');
190
+ line('amazonPage: amazon.de');
191
+ line(`formerRegistrationData has refreshToken: ${Boolean(formerRegistrationData.refreshToken)}`);
192
+ line(`formerRegistrationData has accessToken: ${Boolean(formerRegistrationData.accessToken)}`);
193
+ line(`formerRegistrationData has authorization_code: ${Object.prototype.hasOwnProperty.call(formerRegistrationData, 'authorization_code')}`);
194
+ line(`formerRegistrationData has verifier: ${Object.prototype.hasOwnProperty.call(formerRegistrationData, 'verifier')}`);
195
+ line('');
196
+ line('OBSERVED REQUESTS:');
197
+ calls.forEach((call) => {
198
+ line(`- ${call.method} ${call.host}${call.path} -> ${call.status}`);
199
+ });
200
+ line('');
201
+ line('OBSERVED RESULT:');
202
+ line(`result amazonPage: ${result.amazonPage}`);
203
+ line(`result has accessToken: ${Boolean(result.accessToken)}`);
204
+ line(`result has refreshToken: ${Boolean(result.refreshToken)}`);
205
+ line(`result has macDms: ${Boolean(result.macDms)}`);
206
+ line(`result has csrf: ${Boolean(result.csrf)}`);
207
+ line(`result has authorization_code: ${Object.prototype.hasOwnProperty.call(result, 'authorization_code')}`);
208
+ line(`result has verifier: ${Object.prototype.hasOwnProperty.call(result, 'verifier')}`);
209
+ line(`result loginCookie includes exchange-cookie: ${result.loginCookie.includes('exchange-cookie=EXCHANGE_HEADER')}`);
210
+ line(`result localCookie includes refreshed session-id: ${result.localCookie.includes('session-id=SID_LOCAL')}`);
211
+ line('');
212
+ line('ASSERTIONS:');
213
+ recordAssertion('requests include /auth/token', () => {
214
+ assert.ok(paths.includes('/auth/token'));
215
+ });
216
+ recordAssertion('requests include /v1/devices/@self/capabilities', () => {
217
+ assert.ok(paths.includes('/v1/devices/@self/capabilities'));
218
+ });
219
+ recordAssertion('requests include /ap/exchangetoken/cookies', () => {
220
+ assert.ok(paths.includes('/ap/exchangetoken/cookies'));
221
+ });
222
+ recordAssertion('requests include /api/language', () => {
223
+ assert.ok(paths.includes('/api/language'));
224
+ });
225
+ recordAssertion('requests do not include /auth/register', () => {
226
+ assert.ok(!paths.includes('/auth/register'));
227
+ });
228
+ recordAssertion('capability request uses PUT api.amazonalexa.com', () => {
229
+ assert.strictEqual(capabilityCall.host, 'api.amazonalexa.com');
230
+ assert.strictEqual(capabilityCall.method, 'PUT');
231
+ });
232
+ recordAssertion('capability request has authorization header', () => {
233
+ assert.strictEqual(capabilityCall.hasAuthorization, true);
234
+ });
235
+ recordAssertion('result accessToken was refreshed', () => {
236
+ assert.strictEqual(result.accessToken, 'ACCESS_TOKEN_AFTER_REFRESH');
237
+ });
238
+ recordAssertion('result refreshToken preserved', () => {
239
+ assert.strictEqual(result.refreshToken, 'REFRESH_TOKEN_OLD');
240
+ });
241
+ recordAssertion('result macDms preserved', () => {
242
+ assert.strictEqual(result.macDms, 'MAC_DMS_OLD');
243
+ });
244
+ recordAssertion('result csrf refreshed from API cookie', () => {
245
+ assert.strictEqual(result.csrf, 'CSRF_FROM_API');
246
+ });
247
+ recordAssertion('result localCookie contains exchanged session-id', () => {
248
+ assert.ok(result.localCookie.includes('session-id=SID_LOCAL'));
249
+ });
250
+ recordAssertion('result loginCookie excludes non-Amazon exchange response cookie', () => {
251
+ assert.ok(!result.loginCookie.includes('exchange-cookie=EXCHANGE_HEADER'));
252
+ });
253
+ recordAssertion('result does not keep authorization_code', () => {
254
+ assert.strictEqual(Object.prototype.hasOwnProperty.call(result, 'authorization_code'), false);
255
+ });
256
+ recordAssertion('result does not keep verifier', () => {
257
+ assert.strictEqual(Object.prototype.hasOwnProperty.call(result, 'verifier'), false);
258
+ });
259
+ line('');
260
+ line('RESULT: PASS');
261
+ writeOutput();
262
+ } catch (err) {
263
+ if (!lines.includes('RESULT: PASS')) {
264
+ line('');
265
+ line('RESULT: FAIL');
266
+ writeOutput();
267
+ }
268
+ throw err;
269
+ }
270
+ })();