@webex/webex-core 2.59.3-next.1 → 2.59.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.
- package/.eslintrc.js +6 -6
- package/README.md +79 -79
- package/babel.config.js +3 -3
- package/dist/config.js +24 -24
- package/dist/config.js.map +1 -1
- package/dist/credentials-config.js +56 -56
- package/dist/credentials-config.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interceptors/auth.js +28 -28
- package/dist/interceptors/auth.js.map +1 -1
- package/dist/interceptors/default-options.js +24 -24
- package/dist/interceptors/default-options.js.map +1 -1
- package/dist/interceptors/embargo.js +9 -9
- package/dist/interceptors/embargo.js.map +1 -1
- package/dist/interceptors/network-timing.js +19 -19
- package/dist/interceptors/network-timing.js.map +1 -1
- package/dist/interceptors/payload-transformer.js +19 -19
- package/dist/interceptors/payload-transformer.js.map +1 -1
- package/dist/interceptors/rate-limit.js +40 -40
- package/dist/interceptors/rate-limit.js.map +1 -1
- package/dist/interceptors/redirect.js +13 -13
- package/dist/interceptors/redirect.js.map +1 -1
- package/dist/interceptors/request-event.js +23 -23
- package/dist/interceptors/request-event.js.map +1 -1
- package/dist/interceptors/request-logger.js +13 -13
- package/dist/interceptors/request-logger.js.map +1 -1
- package/dist/interceptors/request-timing.js +23 -23
- package/dist/interceptors/request-timing.js.map +1 -1
- package/dist/interceptors/response-logger.js +19 -19
- package/dist/interceptors/response-logger.js.map +1 -1
- package/dist/interceptors/user-agent.js +29 -29
- package/dist/interceptors/user-agent.js.map +1 -1
- package/dist/interceptors/webex-tracking-id.js +15 -15
- package/dist/interceptors/webex-tracking-id.js.map +1 -1
- package/dist/interceptors/webex-user-agent.js +13 -13
- package/dist/interceptors/webex-user-agent.js.map +1 -1
- package/dist/lib/batcher.js +83 -83
- package/dist/lib/batcher.js.map +1 -1
- package/dist/lib/credentials/credentials.js +103 -103
- package/dist/lib/credentials/credentials.js.map +1 -1
- package/dist/lib/credentials/grant-errors.js +17 -17
- package/dist/lib/credentials/grant-errors.js.map +1 -1
- package/dist/lib/credentials/index.js +2 -2
- package/dist/lib/credentials/index.js.map +1 -1
- package/dist/lib/credentials/scope.js +11 -11
- package/dist/lib/credentials/scope.js.map +1 -1
- package/dist/lib/credentials/token-collection.js +2 -2
- package/dist/lib/credentials/token-collection.js.map +1 -1
- package/dist/lib/credentials/token.js +145 -145
- package/dist/lib/credentials/token.js.map +1 -1
- package/dist/lib/page.js +49 -49
- package/dist/lib/page.js.map +1 -1
- package/dist/lib/services/constants.js.map +1 -1
- package/dist/lib/services/index.js +2 -2
- package/dist/lib/services/index.js.map +1 -1
- package/dist/lib/services/interceptors/server-error.js +9 -9
- package/dist/lib/services/interceptors/server-error.js.map +1 -1
- package/dist/lib/services/interceptors/service.js +24 -24
- package/dist/lib/services/interceptors/service.js.map +1 -1
- package/dist/lib/services/metrics.js.map +1 -1
- package/dist/lib/services/service-catalog.js +104 -104
- package/dist/lib/services/service-catalog.js.map +1 -1
- package/dist/lib/services/service-fed-ramp.js.map +1 -1
- package/dist/lib/services/service-host.js +134 -134
- package/dist/lib/services/service-host.js.map +1 -1
- package/dist/lib/services/service-registry.js +175 -175
- package/dist/lib/services/service-registry.js.map +1 -1
- package/dist/lib/services/service-state.js +38 -38
- package/dist/lib/services/service-state.js.map +1 -1
- package/dist/lib/services/service-url.js +31 -31
- package/dist/lib/services/service-url.js.map +1 -1
- package/dist/lib/services/services.js +245 -245
- package/dist/lib/services/services.js.map +1 -1
- package/dist/lib/stateless-webex-plugin.js +28 -28
- package/dist/lib/stateless-webex-plugin.js.map +1 -1
- package/dist/lib/storage/decorators.js +27 -27
- package/dist/lib/storage/decorators.js.map +1 -1
- package/dist/lib/storage/errors.js +4 -4
- package/dist/lib/storage/errors.js.map +1 -1
- package/dist/lib/storage/index.js.map +1 -1
- package/dist/lib/storage/make-webex-plugin-store.js +44 -44
- package/dist/lib/storage/make-webex-plugin-store.js.map +1 -1
- package/dist/lib/storage/make-webex-store.js +40 -40
- package/dist/lib/storage/make-webex-store.js.map +1 -1
- package/dist/lib/storage/memory-store-adapter.js +9 -9
- package/dist/lib/storage/memory-store-adapter.js.map +1 -1
- package/dist/lib/webex-core-plugin-mixin.js +13 -13
- package/dist/lib/webex-core-plugin-mixin.js.map +1 -1
- package/dist/lib/webex-http-error.js +9 -9
- package/dist/lib/webex-http-error.js.map +1 -1
- package/dist/lib/webex-internal-core-plugin-mixin.js +13 -13
- package/dist/lib/webex-internal-core-plugin-mixin.js.map +1 -1
- package/dist/lib/webex-plugin.js +36 -36
- package/dist/lib/webex-plugin.js.map +1 -1
- package/dist/plugins/logger.js +9 -9
- package/dist/plugins/logger.js.map +1 -1
- package/dist/webex-core.js +104 -104
- package/dist/webex-core.js.map +1 -1
- package/dist/webex-internal-core.js +12 -12
- package/dist/webex-internal-core.js.map +1 -1
- package/jest.config.js +3 -3
- package/package.json +19 -20
- package/process +1 -1
- package/src/config.js +90 -90
- package/src/credentials-config.js +212 -212
- package/src/index.js +62 -62
- package/src/interceptors/auth.js +186 -186
- package/src/interceptors/default-options.js +55 -55
- package/src/interceptors/embargo.js +43 -43
- package/src/interceptors/network-timing.js +54 -54
- package/src/interceptors/payload-transformer.js +55 -55
- package/src/interceptors/rate-limit.js +169 -169
- package/src/interceptors/redirect.js +106 -106
- package/src/interceptors/request-event.js +93 -93
- package/src/interceptors/request-logger.js +78 -78
- package/src/interceptors/request-timing.js +65 -65
- package/src/interceptors/response-logger.js +98 -98
- package/src/interceptors/user-agent.js +77 -77
- package/src/interceptors/webex-tracking-id.js +73 -73
- package/src/interceptors/webex-user-agent.js +79 -79
- package/src/lib/batcher.js +307 -307
- package/src/lib/credentials/credentials.js +552 -552
- package/src/lib/credentials/grant-errors.js +92 -92
- package/src/lib/credentials/index.js +16 -16
- package/src/lib/credentials/scope.js +34 -34
- package/src/lib/credentials/token-collection.js +17 -17
- package/src/lib/credentials/token.js +559 -559
- package/src/lib/page.js +159 -159
- package/src/lib/services/constants.js +9 -9
- package/src/lib/services/index.js +26 -26
- package/src/lib/services/interceptors/server-error.js +48 -48
- package/src/lib/services/interceptors/service.js +101 -101
- package/src/lib/services/metrics.js +4 -4
- package/src/lib/services/service-catalog.js +435 -435
- package/src/lib/services/service-fed-ramp.js +4 -4
- package/src/lib/services/service-host.js +267 -267
- package/src/lib/services/service-registry.js +465 -465
- package/src/lib/services/service-state.js +78 -78
- package/src/lib/services/service-url.js +124 -124
- package/src/lib/services/services.js +1018 -1018
- package/src/lib/stateless-webex-plugin.js +98 -98
- package/src/lib/storage/decorators.js +220 -220
- package/src/lib/storage/errors.js +15 -15
- package/src/lib/storage/index.js +10 -10
- package/src/lib/storage/make-webex-plugin-store.js +211 -211
- package/src/lib/storage/make-webex-store.js +140 -140
- package/src/lib/storage/memory-store-adapter.js +79 -79
- package/src/lib/webex-core-plugin-mixin.js +114 -114
- package/src/lib/webex-http-error.js +61 -61
- package/src/lib/webex-internal-core-plugin-mixin.js +107 -107
- package/src/lib/webex-plugin.js +222 -222
- package/src/plugins/logger.js +60 -60
- package/src/webex-core.js +745 -745
- package/src/webex-internal-core.js +46 -46
- package/test/integration/spec/credentials/credentials.js +139 -139
- package/test/integration/spec/credentials/token.js +102 -102
- package/test/integration/spec/services/service-catalog.js +838 -838
- package/test/integration/spec/services/services.js +1221 -1221
- package/test/integration/spec/webex-core.js +178 -178
- package/test/unit/spec/_setup.js +44 -44
- package/test/unit/spec/credentials/credentials.js +1017 -1017
- package/test/unit/spec/credentials/token.js +441 -441
- package/test/unit/spec/interceptors/auth.js +521 -521
- package/test/unit/spec/interceptors/default-options.js +84 -84
- package/test/unit/spec/interceptors/embargo.js +144 -144
- package/test/unit/spec/interceptors/network-timing.js +49 -49
- package/test/unit/spec/interceptors/payload-transformer.js +155 -155
- package/test/unit/spec/interceptors/rate-limit.js +302 -302
- package/test/unit/spec/interceptors/redirect.js +102 -102
- package/test/unit/spec/interceptors/request-timing.js +92 -92
- package/test/unit/spec/interceptors/user-agent.js +76 -76
- package/test/unit/spec/interceptors/webex-tracking-id.js +76 -76
- package/test/unit/spec/interceptors/webex-user-agent.js +159 -159
- package/test/unit/spec/lib/batcher.js +330 -330
- package/test/unit/spec/lib/page.js +148 -148
- package/test/unit/spec/lib/webex-plugin.js +48 -48
- package/test/unit/spec/services/interceptors/server-error.js +204 -204
- package/test/unit/spec/services/interceptors/service.js +188 -188
- package/test/unit/spec/services/service-catalog.js +194 -194
- package/test/unit/spec/services/service-host.js +260 -260
- package/test/unit/spec/services/service-registry.js +747 -747
- package/test/unit/spec/services/service-state.js +60 -60
- package/test/unit/spec/services/service-url.js +258 -258
- package/test/unit/spec/services/services.js +348 -348
- package/test/unit/spec/storage/persist.js +50 -50
- package/test/unit/spec/storage/storage-adapter.js +12 -12
- package/test/unit/spec/storage/wait-for-value.js +81 -81
- package/test/unit/spec/webex-core.js +253 -253
- package/test/unit/spec/webex-internal-core.js +91 -91
|
@@ -1,441 +1,441 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {assert} from '@webex/test-helper-chai';
|
|
6
|
-
import sinon from 'sinon';
|
|
7
|
-
import {nodeOnly, browserOnly} from '@webex/test-helper-mocha';
|
|
8
|
-
import FakeTimers from '@sinonjs/fake-timers';
|
|
9
|
-
import MockWebex from '@webex/test-helper-mock-webex';
|
|
10
|
-
import {Token} from '@webex/webex-core';
|
|
11
|
-
|
|
12
|
-
/* eslint camelcase: [0] */
|
|
13
|
-
|
|
14
|
-
// eslint-disable-next-line no-empty-function
|
|
15
|
-
function noop() {}
|
|
16
|
-
|
|
17
|
-
describe('webex-core', () => {
|
|
18
|
-
describe('Credentials', () => {
|
|
19
|
-
describe('Token', () => {
|
|
20
|
-
let webex;
|
|
21
|
-
|
|
22
|
-
beforeEach(() => {
|
|
23
|
-
webex = new MockWebex();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
function makeToken(options = {}) {
|
|
27
|
-
return new Token(
|
|
28
|
-
Object.assign(
|
|
29
|
-
{
|
|
30
|
-
access_token: 'AT',
|
|
31
|
-
expires_in: 10000,
|
|
32
|
-
token_type: 'Fake',
|
|
33
|
-
refresh_token: 'RT',
|
|
34
|
-
refresh_token_expires_in: 20000,
|
|
35
|
-
},
|
|
36
|
-
options
|
|
37
|
-
),
|
|
38
|
-
{parent: webex}
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
describe('#canAuthorize', () => {
|
|
43
|
-
it('indicates if this token can be used to authorize a request', () => {
|
|
44
|
-
let token = makeToken();
|
|
45
|
-
|
|
46
|
-
assert.isTrue(token.canAuthorize);
|
|
47
|
-
|
|
48
|
-
token = makeToken({expires: Date.now() + 10000});
|
|
49
|
-
assert.isFalse(token.isExpired);
|
|
50
|
-
assert.isTrue(token.canAuthorize);
|
|
51
|
-
|
|
52
|
-
token = makeToken({expires: Date.now() - 10000});
|
|
53
|
-
assert.isTrue(token.isExpired);
|
|
54
|
-
assert.isFalse(token.canAuthorize);
|
|
55
|
-
|
|
56
|
-
token.unset('expires');
|
|
57
|
-
assert.isFalse(token.isExpired);
|
|
58
|
-
assert.isTrue(token.canAuthorize);
|
|
59
|
-
|
|
60
|
-
token.unset('access_token');
|
|
61
|
-
assert.isFalse(token.canAuthorize);
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
describe('#canDownscope', () => {
|
|
66
|
-
it('indicates if this token can be used to get a token of lesser scope', () => {
|
|
67
|
-
let token = makeToken();
|
|
68
|
-
|
|
69
|
-
assert.isTrue(token.canDownscope);
|
|
70
|
-
|
|
71
|
-
webex.config.credentials.client_id = undefined;
|
|
72
|
-
token = makeToken();
|
|
73
|
-
assert.isFalse(token.canDownscope);
|
|
74
|
-
|
|
75
|
-
webex.config.credentials.client_id = 'blarg';
|
|
76
|
-
token = makeToken();
|
|
77
|
-
assert.isTrue(token.canDownscope);
|
|
78
|
-
|
|
79
|
-
token = makeToken({expires: Date.now() - 10000});
|
|
80
|
-
assert.isFalse(token.canAuthorize);
|
|
81
|
-
assert.isFalse(token.canDownscope);
|
|
82
|
-
|
|
83
|
-
token.unset('expires');
|
|
84
|
-
assert.isTrue(token.canDownscope);
|
|
85
|
-
|
|
86
|
-
token = makeToken({expires: Date.now() + 10000});
|
|
87
|
-
assert.isTrue(token.canAuthorize);
|
|
88
|
-
assert.isTrue(token.canDownscope);
|
|
89
|
-
|
|
90
|
-
token.unset('access_token');
|
|
91
|
-
assert.isFalse(token.canDownscope);
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
describe('#canRefresh', () => {
|
|
96
|
-
browserOnly(it)('indicates if this token can be refreshed', () => {
|
|
97
|
-
let token = makeToken();
|
|
98
|
-
|
|
99
|
-
assert.isFalse(token.canRefresh);
|
|
100
|
-
token.unset('refresh_token');
|
|
101
|
-
assert.isFalse(token.canRefresh);
|
|
102
|
-
|
|
103
|
-
webex.config.credentials.refreshCallback = noop;
|
|
104
|
-
token = makeToken();
|
|
105
|
-
assert.isTrue(token.canRefresh);
|
|
106
|
-
token.unset('refresh_token');
|
|
107
|
-
assert.isFalse(token.canRefresh);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
nodeOnly(it)('indicates if this token can be refreshed', () => {
|
|
111
|
-
let token = makeToken();
|
|
112
|
-
|
|
113
|
-
assert.isTrue(token.canRefresh);
|
|
114
|
-
token.unset('refresh_token');
|
|
115
|
-
assert.isFalse(token.canRefresh);
|
|
116
|
-
|
|
117
|
-
webex.config.credentials.client_secret = undefined;
|
|
118
|
-
token = makeToken();
|
|
119
|
-
assert.isFalse(token.canRefresh);
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
describe('#isExpired', () => {
|
|
124
|
-
it('derives from `expires`', () => {
|
|
125
|
-
let token = makeToken();
|
|
126
|
-
|
|
127
|
-
token.unset('expires');
|
|
128
|
-
token.unset('expires_in');
|
|
129
|
-
assert.isFalse(token.isExpired);
|
|
130
|
-
|
|
131
|
-
token = makeToken({expires: Date.now() - 10000});
|
|
132
|
-
assert.isTrue(token.isExpired);
|
|
133
|
-
|
|
134
|
-
token = makeToken({expires: Date.now() + 10000});
|
|
135
|
-
assert.isFalse(token.isExpired);
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
describe('#_string', () => {
|
|
140
|
-
it('derives from `access_token` and `token_type`', () => {
|
|
141
|
-
const token = makeToken();
|
|
142
|
-
|
|
143
|
-
assert.equal(token._string, 'Fake AT');
|
|
144
|
-
|
|
145
|
-
token.token_type = 'Fake';
|
|
146
|
-
token.unset('access_token');
|
|
147
|
-
assert.equal(token._string, '');
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
describe('#downscope()', () => {
|
|
152
|
-
it('requires an access token', () => {
|
|
153
|
-
const token = makeToken();
|
|
154
|
-
|
|
155
|
-
token.unset('access_token');
|
|
156
|
-
|
|
157
|
-
return assert.isRejected(token.downscope('spark:kms'), /cannot downscope access token/);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
it('requires an unexpired access token', () => {
|
|
161
|
-
const token = makeToken({expires: Date.now() - 10000});
|
|
162
|
-
|
|
163
|
-
return assert.isRejected(
|
|
164
|
-
token.downscope('spark:kms'),
|
|
165
|
-
/cannot downscope expired access token/
|
|
166
|
-
);
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
it('alphabetizes the requested scope', () => {
|
|
170
|
-
const token = makeToken();
|
|
171
|
-
|
|
172
|
-
webex.request.returns(Promise.resolve({body: {access_token: 'AT2'}}));
|
|
173
|
-
|
|
174
|
-
return token
|
|
175
|
-
.downscope('b a')
|
|
176
|
-
.then(() => assert.equal(webex.request.args[0][0].form.scope, 'a b'));
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
describe('#initialize()', () => {
|
|
181
|
-
let clock;
|
|
182
|
-
|
|
183
|
-
beforeEach(() => {
|
|
184
|
-
clock = FakeTimers.install();
|
|
185
|
-
});
|
|
186
|
-
afterEach(() => clock.uninstall());
|
|
187
|
-
|
|
188
|
-
it('requires an access token', () => {
|
|
189
|
-
assert.throws(() => {
|
|
190
|
-
// eslint-disable-next-line no-unused-vars
|
|
191
|
-
const x = new Token();
|
|
192
|
-
}, /`access_token` is required/);
|
|
193
|
-
|
|
194
|
-
assert.doesNotThrow(() => {
|
|
195
|
-
// eslint-disable-next-line no-unused-vars
|
|
196
|
-
const x = new Token({access_token: 'AT'});
|
|
197
|
-
}, /`access_token` is required/);
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
it('infers token_type from an access token string', () => {
|
|
201
|
-
const t = new Token({
|
|
202
|
-
access_token: 'Fake AT',
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
assert.equal(t.access_token, 'AT');
|
|
206
|
-
assert.equal(t.token_type, 'Fake');
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
it('computes expires_in and refresh_token_expires_in if not specified', () => {
|
|
210
|
-
const now = Date.now();
|
|
211
|
-
|
|
212
|
-
const t = makeToken({
|
|
213
|
-
expires_in: 6000,
|
|
214
|
-
refresh_token_expires_in: 12000,
|
|
215
|
-
expires: null,
|
|
216
|
-
refresh_token_expires: null,
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
assert.approximately(t.expires, 6000000 + now, 5);
|
|
220
|
-
assert.approximately(t.refresh_token_expires, 12000000 + now, 5);
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it("alphabetizes the token's scopes", () => {
|
|
224
|
-
const t = new Token({
|
|
225
|
-
access_token: 'AT',
|
|
226
|
-
scope: 'b a',
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
assert.equal(t.scope, 'a b');
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it('it sets a timer to set Token#_isExpired (and therefore Token#isExpired)', () => {
|
|
233
|
-
const t = makeToken({
|
|
234
|
-
// Reminder: expires_in is in seconds, ticks are in miliseconds
|
|
235
|
-
expires_in: 1,
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
assert.isFalse(t.isExpired);
|
|
239
|
-
clock.tick(900);
|
|
240
|
-
assert.isFalse(t.isExpired);
|
|
241
|
-
clock.tick(100);
|
|
242
|
-
assert.isTrue(t.isExpired);
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
it('accepts a string as an access token', () => {
|
|
246
|
-
const token = new Token('AT', {parent: webex});
|
|
247
|
-
|
|
248
|
-
assert.isTrue(token.canAuthorize);
|
|
249
|
-
assert.equal(token.toString(), 'Bearer AT');
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it('accepts a string as an access token (with token type)', () => {
|
|
253
|
-
const token = new Token('Fake AT', {parent: webex});
|
|
254
|
-
|
|
255
|
-
assert.isTrue(token.canAuthorize);
|
|
256
|
-
assert.equal(token.toString(), 'Fake AT');
|
|
257
|
-
});
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
describe('#refresh()', () => {
|
|
261
|
-
browserOnly(it)('refreshes the access_token', () => {
|
|
262
|
-
const token = makeToken();
|
|
263
|
-
|
|
264
|
-
webex.config.credentials.refreshCallback = sinon.stub().returns(
|
|
265
|
-
Promise.resolve({
|
|
266
|
-
access_token: 'AT2',
|
|
267
|
-
expires_in: 10000,
|
|
268
|
-
token_type: 'Fake',
|
|
269
|
-
})
|
|
270
|
-
);
|
|
271
|
-
|
|
272
|
-
// FIXME this next line should be necessary. we need a better way to
|
|
273
|
-
// do config
|
|
274
|
-
token.trigger('change:config');
|
|
275
|
-
|
|
276
|
-
return token.refresh().then((token2) => {
|
|
277
|
-
assert.equal(token2.access_token, 'AT2');
|
|
278
|
-
});
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
nodeOnly(it)('refreshes the access_token', () => {
|
|
282
|
-
const token = makeToken();
|
|
283
|
-
|
|
284
|
-
webex.request.onCall(0).returns(
|
|
285
|
-
Promise.resolve({
|
|
286
|
-
body: {
|
|
287
|
-
access_token: 'AT2',
|
|
288
|
-
expires_in: 10000,
|
|
289
|
-
token_type: 'Fake',
|
|
290
|
-
},
|
|
291
|
-
})
|
|
292
|
-
);
|
|
293
|
-
|
|
294
|
-
return token.refresh().then((token2) => {
|
|
295
|
-
assert.equal(token2.access_token, 'AT2');
|
|
296
|
-
});
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
browserOnly(it)('revokes the previous token when set', () => {
|
|
300
|
-
const token = makeToken();
|
|
301
|
-
|
|
302
|
-
sinon.spy(token, 'revoke');
|
|
303
|
-
webex.config.credentials.refreshCallback = sinon.stub();
|
|
304
|
-
|
|
305
|
-
webex.config.credentials.refreshCallback.onCall(0).returns(
|
|
306
|
-
Promise.resolve({
|
|
307
|
-
access_token: 'AT2',
|
|
308
|
-
expires_in: 10000,
|
|
309
|
-
token_type: 'Fake',
|
|
310
|
-
})
|
|
311
|
-
);
|
|
312
|
-
|
|
313
|
-
webex.config.credentials.refreshCallback.onCall(1).returns(
|
|
314
|
-
Promise.resolve({
|
|
315
|
-
access_token: 'AT3',
|
|
316
|
-
expires_in: 10000,
|
|
317
|
-
token_type: 'Fake',
|
|
318
|
-
})
|
|
319
|
-
);
|
|
320
|
-
|
|
321
|
-
// FIXME this next line should be necessary. we need a better way to
|
|
322
|
-
// do config
|
|
323
|
-
token.trigger('change:config');
|
|
324
|
-
|
|
325
|
-
return token
|
|
326
|
-
.refresh()
|
|
327
|
-
.then((token2) => {
|
|
328
|
-
assert.isTrue(token.canRefresh);
|
|
329
|
-
assert.notCalled(token.revoke);
|
|
330
|
-
|
|
331
|
-
return token2.refresh();
|
|
332
|
-
})
|
|
333
|
-
.then((token3) => {
|
|
334
|
-
assert.equal(token3.access_token, 'AT3');
|
|
335
|
-
assert.called(token.revoke);
|
|
336
|
-
});
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
nodeOnly(it)('revokes the previous token when set', () => {
|
|
340
|
-
const token = makeToken();
|
|
341
|
-
|
|
342
|
-
sinon.spy(token, 'revoke');
|
|
343
|
-
|
|
344
|
-
webex.request.onCall(0).returns(
|
|
345
|
-
Promise.resolve({
|
|
346
|
-
body: {
|
|
347
|
-
access_token: 'AT2',
|
|
348
|
-
expires_in: 10000,
|
|
349
|
-
token_type: 'Fake',
|
|
350
|
-
},
|
|
351
|
-
})
|
|
352
|
-
);
|
|
353
|
-
|
|
354
|
-
webex.request.onCall(1).returns(
|
|
355
|
-
Promise.resolve({
|
|
356
|
-
body: {
|
|
357
|
-
access_token: 'AT3',
|
|
358
|
-
expires_in: 10000,
|
|
359
|
-
token_type: 'Fake',
|
|
360
|
-
},
|
|
361
|
-
})
|
|
362
|
-
);
|
|
363
|
-
|
|
364
|
-
return token
|
|
365
|
-
.refresh()
|
|
366
|
-
.then((token2) => {
|
|
367
|
-
assert.isTrue(token.canRefresh);
|
|
368
|
-
assert.notCalled(token.revoke);
|
|
369
|
-
|
|
370
|
-
return token2.refresh();
|
|
371
|
-
})
|
|
372
|
-
.then((token3) => {
|
|
373
|
-
assert.equal(token3.access_token, 'AT3');
|
|
374
|
-
assert.called(token.revoke);
|
|
375
|
-
});
|
|
376
|
-
});
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
describe('#revoke()', () => {
|
|
380
|
-
describe('when the token has expired', () => {
|
|
381
|
-
it('is a noop', () => {
|
|
382
|
-
const token = makeToken({expires: Date.now() - 10000});
|
|
383
|
-
|
|
384
|
-
return token.revoke().then(() => assert.notCalled(webex.request));
|
|
385
|
-
});
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
describe('when access_token has been unset', () => {
|
|
389
|
-
it('is a noop', () => {
|
|
390
|
-
const token = makeToken();
|
|
391
|
-
|
|
392
|
-
token.unset('access_token');
|
|
393
|
-
|
|
394
|
-
return token.revoke().then(() => assert.notCalled(webex.request));
|
|
395
|
-
});
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
// FIXME this test is temporary; there's currently no practical way to
|
|
399
|
-
// revoke a token without a client secret.
|
|
400
|
-
describe('when the client_secret is unavailable', () => {
|
|
401
|
-
it('is a noop', () => {
|
|
402
|
-
webex.config.credentials.client_secret = undefined;
|
|
403
|
-
|
|
404
|
-
const token = makeToken();
|
|
405
|
-
|
|
406
|
-
token.unset('access_token');
|
|
407
|
-
|
|
408
|
-
return token.revoke().then(() => assert.notCalled(webex.request));
|
|
409
|
-
});
|
|
410
|
-
});
|
|
411
|
-
|
|
412
|
-
it('unsets the access_token and related values', () => {
|
|
413
|
-
const token = makeToken();
|
|
414
|
-
|
|
415
|
-
return token.revoke().then(() => {
|
|
416
|
-
assert.isUndefined(token.access_token);
|
|
417
|
-
assert.isUndefined(token.expires);
|
|
418
|
-
assert.isUndefined(token.expires_in);
|
|
419
|
-
assert.isDefined(token.refresh_token);
|
|
420
|
-
assert.isDefined(token.refresh_token_expires);
|
|
421
|
-
assert.isDefined(token.refresh_token_expires_in);
|
|
422
|
-
});
|
|
423
|
-
});
|
|
424
|
-
});
|
|
425
|
-
|
|
426
|
-
describe('#toString()', () => {
|
|
427
|
-
it('produces a value for an auth header', () => {
|
|
428
|
-
const token = makeToken();
|
|
429
|
-
|
|
430
|
-
assert.equal(token.toString(), 'Fake AT');
|
|
431
|
-
|
|
432
|
-
token.unset('access_token');
|
|
433
|
-
|
|
434
|
-
assert.throws(() => {
|
|
435
|
-
token.toString();
|
|
436
|
-
}, /cannot stringify Token/);
|
|
437
|
-
});
|
|
438
|
-
});
|
|
439
|
-
});
|
|
440
|
-
});
|
|
441
|
-
});
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {assert} from '@webex/test-helper-chai';
|
|
6
|
+
import sinon from 'sinon';
|
|
7
|
+
import {nodeOnly, browserOnly} from '@webex/test-helper-mocha';
|
|
8
|
+
import FakeTimers from '@sinonjs/fake-timers';
|
|
9
|
+
import MockWebex from '@webex/test-helper-mock-webex';
|
|
10
|
+
import {Token} from '@webex/webex-core';
|
|
11
|
+
|
|
12
|
+
/* eslint camelcase: [0] */
|
|
13
|
+
|
|
14
|
+
// eslint-disable-next-line no-empty-function
|
|
15
|
+
function noop() {}
|
|
16
|
+
|
|
17
|
+
describe('webex-core', () => {
|
|
18
|
+
describe('Credentials', () => {
|
|
19
|
+
describe('Token', () => {
|
|
20
|
+
let webex;
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
webex = new MockWebex();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
function makeToken(options = {}) {
|
|
27
|
+
return new Token(
|
|
28
|
+
Object.assign(
|
|
29
|
+
{
|
|
30
|
+
access_token: 'AT',
|
|
31
|
+
expires_in: 10000,
|
|
32
|
+
token_type: 'Fake',
|
|
33
|
+
refresh_token: 'RT',
|
|
34
|
+
refresh_token_expires_in: 20000,
|
|
35
|
+
},
|
|
36
|
+
options
|
|
37
|
+
),
|
|
38
|
+
{parent: webex}
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
describe('#canAuthorize', () => {
|
|
43
|
+
it('indicates if this token can be used to authorize a request', () => {
|
|
44
|
+
let token = makeToken();
|
|
45
|
+
|
|
46
|
+
assert.isTrue(token.canAuthorize);
|
|
47
|
+
|
|
48
|
+
token = makeToken({expires: Date.now() + 10000});
|
|
49
|
+
assert.isFalse(token.isExpired);
|
|
50
|
+
assert.isTrue(token.canAuthorize);
|
|
51
|
+
|
|
52
|
+
token = makeToken({expires: Date.now() - 10000});
|
|
53
|
+
assert.isTrue(token.isExpired);
|
|
54
|
+
assert.isFalse(token.canAuthorize);
|
|
55
|
+
|
|
56
|
+
token.unset('expires');
|
|
57
|
+
assert.isFalse(token.isExpired);
|
|
58
|
+
assert.isTrue(token.canAuthorize);
|
|
59
|
+
|
|
60
|
+
token.unset('access_token');
|
|
61
|
+
assert.isFalse(token.canAuthorize);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('#canDownscope', () => {
|
|
66
|
+
it('indicates if this token can be used to get a token of lesser scope', () => {
|
|
67
|
+
let token = makeToken();
|
|
68
|
+
|
|
69
|
+
assert.isTrue(token.canDownscope);
|
|
70
|
+
|
|
71
|
+
webex.config.credentials.client_id = undefined;
|
|
72
|
+
token = makeToken();
|
|
73
|
+
assert.isFalse(token.canDownscope);
|
|
74
|
+
|
|
75
|
+
webex.config.credentials.client_id = 'blarg';
|
|
76
|
+
token = makeToken();
|
|
77
|
+
assert.isTrue(token.canDownscope);
|
|
78
|
+
|
|
79
|
+
token = makeToken({expires: Date.now() - 10000});
|
|
80
|
+
assert.isFalse(token.canAuthorize);
|
|
81
|
+
assert.isFalse(token.canDownscope);
|
|
82
|
+
|
|
83
|
+
token.unset('expires');
|
|
84
|
+
assert.isTrue(token.canDownscope);
|
|
85
|
+
|
|
86
|
+
token = makeToken({expires: Date.now() + 10000});
|
|
87
|
+
assert.isTrue(token.canAuthorize);
|
|
88
|
+
assert.isTrue(token.canDownscope);
|
|
89
|
+
|
|
90
|
+
token.unset('access_token');
|
|
91
|
+
assert.isFalse(token.canDownscope);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe('#canRefresh', () => {
|
|
96
|
+
browserOnly(it)('indicates if this token can be refreshed', () => {
|
|
97
|
+
let token = makeToken();
|
|
98
|
+
|
|
99
|
+
assert.isFalse(token.canRefresh);
|
|
100
|
+
token.unset('refresh_token');
|
|
101
|
+
assert.isFalse(token.canRefresh);
|
|
102
|
+
|
|
103
|
+
webex.config.credentials.refreshCallback = noop;
|
|
104
|
+
token = makeToken();
|
|
105
|
+
assert.isTrue(token.canRefresh);
|
|
106
|
+
token.unset('refresh_token');
|
|
107
|
+
assert.isFalse(token.canRefresh);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
nodeOnly(it)('indicates if this token can be refreshed', () => {
|
|
111
|
+
let token = makeToken();
|
|
112
|
+
|
|
113
|
+
assert.isTrue(token.canRefresh);
|
|
114
|
+
token.unset('refresh_token');
|
|
115
|
+
assert.isFalse(token.canRefresh);
|
|
116
|
+
|
|
117
|
+
webex.config.credentials.client_secret = undefined;
|
|
118
|
+
token = makeToken();
|
|
119
|
+
assert.isFalse(token.canRefresh);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('#isExpired', () => {
|
|
124
|
+
it('derives from `expires`', () => {
|
|
125
|
+
let token = makeToken();
|
|
126
|
+
|
|
127
|
+
token.unset('expires');
|
|
128
|
+
token.unset('expires_in');
|
|
129
|
+
assert.isFalse(token.isExpired);
|
|
130
|
+
|
|
131
|
+
token = makeToken({expires: Date.now() - 10000});
|
|
132
|
+
assert.isTrue(token.isExpired);
|
|
133
|
+
|
|
134
|
+
token = makeToken({expires: Date.now() + 10000});
|
|
135
|
+
assert.isFalse(token.isExpired);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe('#_string', () => {
|
|
140
|
+
it('derives from `access_token` and `token_type`', () => {
|
|
141
|
+
const token = makeToken();
|
|
142
|
+
|
|
143
|
+
assert.equal(token._string, 'Fake AT');
|
|
144
|
+
|
|
145
|
+
token.token_type = 'Fake';
|
|
146
|
+
token.unset('access_token');
|
|
147
|
+
assert.equal(token._string, '');
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('#downscope()', () => {
|
|
152
|
+
it('requires an access token', () => {
|
|
153
|
+
const token = makeToken();
|
|
154
|
+
|
|
155
|
+
token.unset('access_token');
|
|
156
|
+
|
|
157
|
+
return assert.isRejected(token.downscope('spark:kms'), /cannot downscope access token/);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('requires an unexpired access token', () => {
|
|
161
|
+
const token = makeToken({expires: Date.now() - 10000});
|
|
162
|
+
|
|
163
|
+
return assert.isRejected(
|
|
164
|
+
token.downscope('spark:kms'),
|
|
165
|
+
/cannot downscope expired access token/
|
|
166
|
+
);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('alphabetizes the requested scope', () => {
|
|
170
|
+
const token = makeToken();
|
|
171
|
+
|
|
172
|
+
webex.request.returns(Promise.resolve({body: {access_token: 'AT2'}}));
|
|
173
|
+
|
|
174
|
+
return token
|
|
175
|
+
.downscope('b a')
|
|
176
|
+
.then(() => assert.equal(webex.request.args[0][0].form.scope, 'a b'));
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe('#initialize()', () => {
|
|
181
|
+
let clock;
|
|
182
|
+
|
|
183
|
+
beforeEach(() => {
|
|
184
|
+
clock = FakeTimers.install();
|
|
185
|
+
});
|
|
186
|
+
afterEach(() => clock.uninstall());
|
|
187
|
+
|
|
188
|
+
it('requires an access token', () => {
|
|
189
|
+
assert.throws(() => {
|
|
190
|
+
// eslint-disable-next-line no-unused-vars
|
|
191
|
+
const x = new Token();
|
|
192
|
+
}, /`access_token` is required/);
|
|
193
|
+
|
|
194
|
+
assert.doesNotThrow(() => {
|
|
195
|
+
// eslint-disable-next-line no-unused-vars
|
|
196
|
+
const x = new Token({access_token: 'AT'});
|
|
197
|
+
}, /`access_token` is required/);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('infers token_type from an access token string', () => {
|
|
201
|
+
const t = new Token({
|
|
202
|
+
access_token: 'Fake AT',
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
assert.equal(t.access_token, 'AT');
|
|
206
|
+
assert.equal(t.token_type, 'Fake');
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('computes expires_in and refresh_token_expires_in if not specified', () => {
|
|
210
|
+
const now = Date.now();
|
|
211
|
+
|
|
212
|
+
const t = makeToken({
|
|
213
|
+
expires_in: 6000,
|
|
214
|
+
refresh_token_expires_in: 12000,
|
|
215
|
+
expires: null,
|
|
216
|
+
refresh_token_expires: null,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
assert.approximately(t.expires, 6000000 + now, 5);
|
|
220
|
+
assert.approximately(t.refresh_token_expires, 12000000 + now, 5);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("alphabetizes the token's scopes", () => {
|
|
224
|
+
const t = new Token({
|
|
225
|
+
access_token: 'AT',
|
|
226
|
+
scope: 'b a',
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
assert.equal(t.scope, 'a b');
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('it sets a timer to set Token#_isExpired (and therefore Token#isExpired)', () => {
|
|
233
|
+
const t = makeToken({
|
|
234
|
+
// Reminder: expires_in is in seconds, ticks are in miliseconds
|
|
235
|
+
expires_in: 1,
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
assert.isFalse(t.isExpired);
|
|
239
|
+
clock.tick(900);
|
|
240
|
+
assert.isFalse(t.isExpired);
|
|
241
|
+
clock.tick(100);
|
|
242
|
+
assert.isTrue(t.isExpired);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('accepts a string as an access token', () => {
|
|
246
|
+
const token = new Token('AT', {parent: webex});
|
|
247
|
+
|
|
248
|
+
assert.isTrue(token.canAuthorize);
|
|
249
|
+
assert.equal(token.toString(), 'Bearer AT');
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('accepts a string as an access token (with token type)', () => {
|
|
253
|
+
const token = new Token('Fake AT', {parent: webex});
|
|
254
|
+
|
|
255
|
+
assert.isTrue(token.canAuthorize);
|
|
256
|
+
assert.equal(token.toString(), 'Fake AT');
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
describe('#refresh()', () => {
|
|
261
|
+
browserOnly(it)('refreshes the access_token', () => {
|
|
262
|
+
const token = makeToken();
|
|
263
|
+
|
|
264
|
+
webex.config.credentials.refreshCallback = sinon.stub().returns(
|
|
265
|
+
Promise.resolve({
|
|
266
|
+
access_token: 'AT2',
|
|
267
|
+
expires_in: 10000,
|
|
268
|
+
token_type: 'Fake',
|
|
269
|
+
})
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
// FIXME this next line should be necessary. we need a better way to
|
|
273
|
+
// do config
|
|
274
|
+
token.trigger('change:config');
|
|
275
|
+
|
|
276
|
+
return token.refresh().then((token2) => {
|
|
277
|
+
assert.equal(token2.access_token, 'AT2');
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
nodeOnly(it)('refreshes the access_token', () => {
|
|
282
|
+
const token = makeToken();
|
|
283
|
+
|
|
284
|
+
webex.request.onCall(0).returns(
|
|
285
|
+
Promise.resolve({
|
|
286
|
+
body: {
|
|
287
|
+
access_token: 'AT2',
|
|
288
|
+
expires_in: 10000,
|
|
289
|
+
token_type: 'Fake',
|
|
290
|
+
},
|
|
291
|
+
})
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
return token.refresh().then((token2) => {
|
|
295
|
+
assert.equal(token2.access_token, 'AT2');
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
browserOnly(it)('revokes the previous token when set', () => {
|
|
300
|
+
const token = makeToken();
|
|
301
|
+
|
|
302
|
+
sinon.spy(token, 'revoke');
|
|
303
|
+
webex.config.credentials.refreshCallback = sinon.stub();
|
|
304
|
+
|
|
305
|
+
webex.config.credentials.refreshCallback.onCall(0).returns(
|
|
306
|
+
Promise.resolve({
|
|
307
|
+
access_token: 'AT2',
|
|
308
|
+
expires_in: 10000,
|
|
309
|
+
token_type: 'Fake',
|
|
310
|
+
})
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
webex.config.credentials.refreshCallback.onCall(1).returns(
|
|
314
|
+
Promise.resolve({
|
|
315
|
+
access_token: 'AT3',
|
|
316
|
+
expires_in: 10000,
|
|
317
|
+
token_type: 'Fake',
|
|
318
|
+
})
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
// FIXME this next line should be necessary. we need a better way to
|
|
322
|
+
// do config
|
|
323
|
+
token.trigger('change:config');
|
|
324
|
+
|
|
325
|
+
return token
|
|
326
|
+
.refresh()
|
|
327
|
+
.then((token2) => {
|
|
328
|
+
assert.isTrue(token.canRefresh);
|
|
329
|
+
assert.notCalled(token.revoke);
|
|
330
|
+
|
|
331
|
+
return token2.refresh();
|
|
332
|
+
})
|
|
333
|
+
.then((token3) => {
|
|
334
|
+
assert.equal(token3.access_token, 'AT3');
|
|
335
|
+
assert.called(token.revoke);
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
nodeOnly(it)('revokes the previous token when set', () => {
|
|
340
|
+
const token = makeToken();
|
|
341
|
+
|
|
342
|
+
sinon.spy(token, 'revoke');
|
|
343
|
+
|
|
344
|
+
webex.request.onCall(0).returns(
|
|
345
|
+
Promise.resolve({
|
|
346
|
+
body: {
|
|
347
|
+
access_token: 'AT2',
|
|
348
|
+
expires_in: 10000,
|
|
349
|
+
token_type: 'Fake',
|
|
350
|
+
},
|
|
351
|
+
})
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
webex.request.onCall(1).returns(
|
|
355
|
+
Promise.resolve({
|
|
356
|
+
body: {
|
|
357
|
+
access_token: 'AT3',
|
|
358
|
+
expires_in: 10000,
|
|
359
|
+
token_type: 'Fake',
|
|
360
|
+
},
|
|
361
|
+
})
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
return token
|
|
365
|
+
.refresh()
|
|
366
|
+
.then((token2) => {
|
|
367
|
+
assert.isTrue(token.canRefresh);
|
|
368
|
+
assert.notCalled(token.revoke);
|
|
369
|
+
|
|
370
|
+
return token2.refresh();
|
|
371
|
+
})
|
|
372
|
+
.then((token3) => {
|
|
373
|
+
assert.equal(token3.access_token, 'AT3');
|
|
374
|
+
assert.called(token.revoke);
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
describe('#revoke()', () => {
|
|
380
|
+
describe('when the token has expired', () => {
|
|
381
|
+
it('is a noop', () => {
|
|
382
|
+
const token = makeToken({expires: Date.now() - 10000});
|
|
383
|
+
|
|
384
|
+
return token.revoke().then(() => assert.notCalled(webex.request));
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
describe('when access_token has been unset', () => {
|
|
389
|
+
it('is a noop', () => {
|
|
390
|
+
const token = makeToken();
|
|
391
|
+
|
|
392
|
+
token.unset('access_token');
|
|
393
|
+
|
|
394
|
+
return token.revoke().then(() => assert.notCalled(webex.request));
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
// FIXME this test is temporary; there's currently no practical way to
|
|
399
|
+
// revoke a token without a client secret.
|
|
400
|
+
describe('when the client_secret is unavailable', () => {
|
|
401
|
+
it('is a noop', () => {
|
|
402
|
+
webex.config.credentials.client_secret = undefined;
|
|
403
|
+
|
|
404
|
+
const token = makeToken();
|
|
405
|
+
|
|
406
|
+
token.unset('access_token');
|
|
407
|
+
|
|
408
|
+
return token.revoke().then(() => assert.notCalled(webex.request));
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
it('unsets the access_token and related values', () => {
|
|
413
|
+
const token = makeToken();
|
|
414
|
+
|
|
415
|
+
return token.revoke().then(() => {
|
|
416
|
+
assert.isUndefined(token.access_token);
|
|
417
|
+
assert.isUndefined(token.expires);
|
|
418
|
+
assert.isUndefined(token.expires_in);
|
|
419
|
+
assert.isDefined(token.refresh_token);
|
|
420
|
+
assert.isDefined(token.refresh_token_expires);
|
|
421
|
+
assert.isDefined(token.refresh_token_expires_in);
|
|
422
|
+
});
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
describe('#toString()', () => {
|
|
427
|
+
it('produces a value for an auth header', () => {
|
|
428
|
+
const token = makeToken();
|
|
429
|
+
|
|
430
|
+
assert.equal(token.toString(), 'Fake AT');
|
|
431
|
+
|
|
432
|
+
token.unset('access_token');
|
|
433
|
+
|
|
434
|
+
assert.throws(() => {
|
|
435
|
+
token.toString();
|
|
436
|
+
}, /cannot stringify Token/);
|
|
437
|
+
});
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
});
|
|
441
|
+
});
|