@bytescale/sdk 3.59.0 → 3.60.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/dist/browser/cjs/main.js +23 -12
- package/dist/browser/esm/main.mjs +23 -12
- package/dist/types/private/model/AuthSessionConfigBase.d.ts +2 -0
- package/dist/types/public/browser/AuthManagerBrowser.d.ts +1 -0
- package/package.json +1 -1
- package/tests/AuthManagerBrowser.test.ts +62 -0
- package/tests/AuthServiceWorkerRewrite.test.ts +23 -3
package/dist/browser/cjs/main.js
CHANGED
|
@@ -3678,14 +3678,14 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3678
3678
|
return AuthManagerBrowser_invoke(function () {
|
|
3679
3679
|
if (session.authConfigs === undefined && typeof session.params.accountId === "string") {
|
|
3680
3680
|
return AuthManagerBrowser_continueIgnored(AuthManagerBrowser_catch(function () {
|
|
3681
|
-
return AuthManagerBrowser_awaitIgnored(_this3.deleteAccessToken(session.params.options, session.params.accountId));
|
|
3681
|
+
return AuthManagerBrowser_awaitIgnored(_this3.deleteAccessToken(session.params.options, _this3.getCdnUrl(session.params), session.params.accountId));
|
|
3682
3682
|
}, function (e) {
|
|
3683
3683
|
cleanupError = e;
|
|
3684
3684
|
}));
|
|
3685
3685
|
} else {
|
|
3686
3686
|
return AuthManagerBrowser_continueIgnored(AuthManagerBrowser_forOf(cookieConfigs, function (state) {
|
|
3687
3687
|
return AuthManagerBrowser_continueIgnored(AuthManagerBrowser_catch(function () {
|
|
3688
|
-
return AuthManagerBrowser_awaitIgnored(_this3.deleteAccessToken(session.params.options, state.config.accountId));
|
|
3688
|
+
return AuthManagerBrowser_awaitIgnored(_this3.deleteAccessToken(session.params.options, _this3.getConfigCdnUrl(session.params, state.config), state.config.accountId));
|
|
3689
3689
|
}, function (e) {
|
|
3690
3690
|
cleanupError !== null && cleanupError !== void 0 ? cleanupError : cleanupError = e;
|
|
3691
3691
|
}));
|
|
@@ -3736,7 +3736,7 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3736
3736
|
return AuthManagerBrowser_catch(function () {
|
|
3737
3737
|
return AuthManagerBrowser_await(_this4.getAuthorizationToken(session.params, state.config), function (jwt) {
|
|
3738
3738
|
var setCookie = _this4.shouldSetCookie(session, state.config);
|
|
3739
|
-
return AuthManagerBrowser_await(_this4.setAccessToken(session.params.options, state.config.accountId, jwt, setCookie), function (token) {
|
|
3739
|
+
return AuthManagerBrowser_await(_this4.setAccessToken(session.params.options, _this4.getConfigCdnUrl(session.params, state.config), state.config.accountId, jwt, setCookie), function (token) {
|
|
3740
3740
|
var expiresAt = Date.now() + token.ttlSeconds * 1000;
|
|
3741
3741
|
state.accessToken = token.accessToken;
|
|
3742
3742
|
state.expiresAt = expiresAt;
|
|
@@ -3801,7 +3801,7 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3801
3801
|
value: "Bearer ".concat(state.jwt)
|
|
3802
3802
|
}],
|
|
3803
3803
|
sourceUrlPrefixes: state.config.sourceUrlPrefixes,
|
|
3804
|
-
urlPrefix: "".concat(_this5.
|
|
3804
|
+
urlPrefix: "".concat(_this5.getConfigCdnUrl(session.params, state.config), "/").concat(state.config.accountId, "/")
|
|
3805
3805
|
}];
|
|
3806
3806
|
});
|
|
3807
3807
|
return AuthManagerBrowser_await(AuthManagerBrowser_awaitIgnored(_this5.sendServiceWorkerConfig(session, config, _this5.isV2Params(session.params) ? session.params.urlRewriteRules : undefined)));
|
|
@@ -3894,6 +3894,9 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3894
3894
|
if (isV2 && !this.isValidAccountId(config.accountId)) {
|
|
3895
3895
|
throw new Error("Invalid Bytescale account ID: '".concat(String(config.accountId), "'."));
|
|
3896
3896
|
}
|
|
3897
|
+
if (config.cdnUrl !== undefined && typeof config.cdnUrl !== "string") {
|
|
3898
|
+
throw new Error("The 'cdnUrl' field must be a string when provided.");
|
|
3899
|
+
}
|
|
3897
3900
|
if (config.enableCookieAuth !== undefined && typeof config.enableCookieAuth !== "boolean" || config.enableServiceWorkerAuth !== undefined && typeof config.enableServiceWorkerAuth !== "boolean") {
|
|
3898
3901
|
throw new Error("Authentication enablement flags must be booleans when provided.");
|
|
3899
3902
|
}
|
|
@@ -3914,7 +3917,7 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3914
3917
|
cookieConfig = config;
|
|
3915
3918
|
}
|
|
3916
3919
|
if (this.isServiceWorkerEnabled(config)) {
|
|
3917
|
-
var _prefix = "".concat(this.
|
|
3920
|
+
var _prefix = "".concat(this.getConfigCdnUrl(params, config), "/").concat(config.accountId, "/");
|
|
3918
3921
|
if (workerConfigsByPrefix.has(_prefix)) {
|
|
3919
3922
|
throw new Error("Multiple service-worker auth configurations target the same URL prefix: '".concat(_prefix, "'."));
|
|
3920
3923
|
}
|
|
@@ -3927,7 +3930,7 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3927
3930
|
_iterator2.f();
|
|
3928
3931
|
}
|
|
3929
3932
|
if (cookieConfig !== undefined) {
|
|
3930
|
-
var prefix = "".concat(this.
|
|
3933
|
+
var prefix = "".concat(this.getConfigCdnUrl(params, cookieConfig), "/").concat(cookieConfig.accountId, "/");
|
|
3931
3934
|
var workerConfig = workerConfigsByPrefix.get(prefix);
|
|
3932
3935
|
if (workerConfig !== undefined && workerConfig !== cookieConfig) {
|
|
3933
3936
|
throw new Error("Cookie and service-worker authentication cannot target the same account from different configs.");
|
|
@@ -4006,8 +4009,8 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
4006
4009
|
}
|
|
4007
4010
|
}, {
|
|
4008
4011
|
key: "getAccessTokenUrl",
|
|
4009
|
-
value: function getAccessTokenUrl(
|
|
4010
|
-
return "".concat(
|
|
4012
|
+
value: function getAccessTokenUrl(cdnUrl, accountId, setCookie) {
|
|
4013
|
+
return "".concat(cdnUrl, "/api/v1/access_tokens/").concat(accountId, "?set-cookie=").concat(setCookie ? "true" : "false");
|
|
4011
4014
|
}
|
|
4012
4015
|
}, {
|
|
4013
4016
|
key: "getCdnUrl",
|
|
@@ -4015,12 +4018,20 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
4015
4018
|
var _a;
|
|
4016
4019
|
return BytescaleApiClientConfigUtils.getCdnUrl((_a = params.options) !== null && _a !== void 0 ? _a : {});
|
|
4017
4020
|
}
|
|
4021
|
+
}, {
|
|
4022
|
+
key: "getConfigCdnUrl",
|
|
4023
|
+
value: function getConfigCdnUrl(params, config) {
|
|
4024
|
+
var _a, _b;
|
|
4025
|
+
return BytescaleApiClientConfigUtils.getCdnUrl({
|
|
4026
|
+
cdnUrl: (_a = config.cdnUrl) !== null && _a !== void 0 ? _a : (_b = params.options) === null || _b === void 0 ? void 0 : _b.cdnUrl
|
|
4027
|
+
});
|
|
4028
|
+
}
|
|
4018
4029
|
}, {
|
|
4019
4030
|
key: "deleteAccessToken",
|
|
4020
|
-
value: function deleteAccessToken(options, accountId) {
|
|
4031
|
+
value: function deleteAccessToken(options, cdnUrl, accountId) {
|
|
4021
4032
|
try {
|
|
4022
4033
|
var _this8 = this;
|
|
4023
|
-
return AuthManagerBrowser_await(AuthManagerBrowser_awaitIgnored(BaseAPI.fetch(_this8.getAccessTokenUrl(
|
|
4034
|
+
return AuthManagerBrowser_await(AuthManagerBrowser_awaitIgnored(BaseAPI.fetch(_this8.getAccessTokenUrl(cdnUrl, accountId, true), {
|
|
4024
4035
|
method: "DELETE",
|
|
4025
4036
|
credentials: "include",
|
|
4026
4037
|
headers: {}
|
|
@@ -4034,13 +4045,13 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
4034
4045
|
}
|
|
4035
4046
|
}, {
|
|
4036
4047
|
key: "setAccessToken",
|
|
4037
|
-
value: function setAccessToken(options, accountId, jwt, setCookie) {
|
|
4048
|
+
value: function setAccessToken(options, cdnUrl, accountId, jwt, setCookie) {
|
|
4038
4049
|
try {
|
|
4039
4050
|
var _this9 = this;
|
|
4040
4051
|
var request = {
|
|
4041
4052
|
accessToken: jwt
|
|
4042
4053
|
};
|
|
4043
|
-
return AuthManagerBrowser_await(BaseAPI.fetch(_this9.getAccessTokenUrl(
|
|
4054
|
+
return AuthManagerBrowser_await(BaseAPI.fetch(_this9.getAccessTokenUrl(cdnUrl, accountId, setCookie), {
|
|
4044
4055
|
method: "PUT",
|
|
4045
4056
|
credentials: "include",
|
|
4046
4057
|
headers: AuthManagerBrowser_defineProperty({}, _this9.contentType, _this9.contentTypeJson),
|
|
@@ -3638,14 +3638,14 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3638
3638
|
return AuthManagerBrowser_invoke(function () {
|
|
3639
3639
|
if (session.authConfigs === undefined && typeof session.params.accountId === "string") {
|
|
3640
3640
|
return AuthManagerBrowser_continueIgnored(AuthManagerBrowser_catch(function () {
|
|
3641
|
-
return AuthManagerBrowser_awaitIgnored(_this3.deleteAccessToken(session.params.options, session.params.accountId));
|
|
3641
|
+
return AuthManagerBrowser_awaitIgnored(_this3.deleteAccessToken(session.params.options, _this3.getCdnUrl(session.params), session.params.accountId));
|
|
3642
3642
|
}, function (e) {
|
|
3643
3643
|
cleanupError = e;
|
|
3644
3644
|
}));
|
|
3645
3645
|
} else {
|
|
3646
3646
|
return AuthManagerBrowser_continueIgnored(AuthManagerBrowser_forOf(cookieConfigs, function (state) {
|
|
3647
3647
|
return AuthManagerBrowser_continueIgnored(AuthManagerBrowser_catch(function () {
|
|
3648
|
-
return AuthManagerBrowser_awaitIgnored(_this3.deleteAccessToken(session.params.options, state.config.accountId));
|
|
3648
|
+
return AuthManagerBrowser_awaitIgnored(_this3.deleteAccessToken(session.params.options, _this3.getConfigCdnUrl(session.params, state.config), state.config.accountId));
|
|
3649
3649
|
}, function (e) {
|
|
3650
3650
|
cleanupError !== null && cleanupError !== void 0 ? cleanupError : cleanupError = e;
|
|
3651
3651
|
}));
|
|
@@ -3696,7 +3696,7 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3696
3696
|
return AuthManagerBrowser_catch(function () {
|
|
3697
3697
|
return AuthManagerBrowser_await(_this4.getAuthorizationToken(session.params, state.config), function (jwt) {
|
|
3698
3698
|
var setCookie = _this4.shouldSetCookie(session, state.config);
|
|
3699
|
-
return AuthManagerBrowser_await(_this4.setAccessToken(session.params.options, state.config.accountId, jwt, setCookie), function (token) {
|
|
3699
|
+
return AuthManagerBrowser_await(_this4.setAccessToken(session.params.options, _this4.getConfigCdnUrl(session.params, state.config), state.config.accountId, jwt, setCookie), function (token) {
|
|
3700
3700
|
var expiresAt = Date.now() + token.ttlSeconds * 1000;
|
|
3701
3701
|
state.accessToken = token.accessToken;
|
|
3702
3702
|
state.expiresAt = expiresAt;
|
|
@@ -3761,7 +3761,7 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3761
3761
|
value: "Bearer ".concat(state.jwt)
|
|
3762
3762
|
}],
|
|
3763
3763
|
sourceUrlPrefixes: state.config.sourceUrlPrefixes,
|
|
3764
|
-
urlPrefix: "".concat(_this5.
|
|
3764
|
+
urlPrefix: "".concat(_this5.getConfigCdnUrl(session.params, state.config), "/").concat(state.config.accountId, "/")
|
|
3765
3765
|
}];
|
|
3766
3766
|
});
|
|
3767
3767
|
return AuthManagerBrowser_await(AuthManagerBrowser_awaitIgnored(_this5.sendServiceWorkerConfig(session, config, _this5.isV2Params(session.params) ? session.params.urlRewriteRules : undefined)));
|
|
@@ -3854,6 +3854,9 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3854
3854
|
if (isV2 && !this.isValidAccountId(config.accountId)) {
|
|
3855
3855
|
throw new Error("Invalid Bytescale account ID: '".concat(String(config.accountId), "'."));
|
|
3856
3856
|
}
|
|
3857
|
+
if (config.cdnUrl !== undefined && typeof config.cdnUrl !== "string") {
|
|
3858
|
+
throw new Error("The 'cdnUrl' field must be a string when provided.");
|
|
3859
|
+
}
|
|
3857
3860
|
if (config.enableCookieAuth !== undefined && typeof config.enableCookieAuth !== "boolean" || config.enableServiceWorkerAuth !== undefined && typeof config.enableServiceWorkerAuth !== "boolean") {
|
|
3858
3861
|
throw new Error("Authentication enablement flags must be booleans when provided.");
|
|
3859
3862
|
}
|
|
@@ -3874,7 +3877,7 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3874
3877
|
cookieConfig = config;
|
|
3875
3878
|
}
|
|
3876
3879
|
if (this.isServiceWorkerEnabled(config)) {
|
|
3877
|
-
var _prefix = "".concat(this.
|
|
3880
|
+
var _prefix = "".concat(this.getConfigCdnUrl(params, config), "/").concat(config.accountId, "/");
|
|
3878
3881
|
if (workerConfigsByPrefix.has(_prefix)) {
|
|
3879
3882
|
throw new Error("Multiple service-worker auth configurations target the same URL prefix: '".concat(_prefix, "'."));
|
|
3880
3883
|
}
|
|
@@ -3887,7 +3890,7 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3887
3890
|
_iterator2.f();
|
|
3888
3891
|
}
|
|
3889
3892
|
if (cookieConfig !== undefined) {
|
|
3890
|
-
var prefix = "".concat(this.
|
|
3893
|
+
var prefix = "".concat(this.getConfigCdnUrl(params, cookieConfig), "/").concat(cookieConfig.accountId, "/");
|
|
3891
3894
|
var workerConfig = workerConfigsByPrefix.get(prefix);
|
|
3892
3895
|
if (workerConfig !== undefined && workerConfig !== cookieConfig) {
|
|
3893
3896
|
throw new Error("Cookie and service-worker authentication cannot target the same account from different configs.");
|
|
@@ -3966,8 +3969,8 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3966
3969
|
}
|
|
3967
3970
|
}, {
|
|
3968
3971
|
key: "getAccessTokenUrl",
|
|
3969
|
-
value: function getAccessTokenUrl(
|
|
3970
|
-
return "".concat(
|
|
3972
|
+
value: function getAccessTokenUrl(cdnUrl, accountId, setCookie) {
|
|
3973
|
+
return "".concat(cdnUrl, "/api/v1/access_tokens/").concat(accountId, "?set-cookie=").concat(setCookie ? "true" : "false");
|
|
3971
3974
|
}
|
|
3972
3975
|
}, {
|
|
3973
3976
|
key: "getCdnUrl",
|
|
@@ -3975,12 +3978,20 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3975
3978
|
var _a;
|
|
3976
3979
|
return BytescaleApiClientConfigUtils.getCdnUrl((_a = params.options) !== null && _a !== void 0 ? _a : {});
|
|
3977
3980
|
}
|
|
3981
|
+
}, {
|
|
3982
|
+
key: "getConfigCdnUrl",
|
|
3983
|
+
value: function getConfigCdnUrl(params, config) {
|
|
3984
|
+
var _a, _b;
|
|
3985
|
+
return BytescaleApiClientConfigUtils.getCdnUrl({
|
|
3986
|
+
cdnUrl: (_a = config.cdnUrl) !== null && _a !== void 0 ? _a : (_b = params.options) === null || _b === void 0 ? void 0 : _b.cdnUrl
|
|
3987
|
+
});
|
|
3988
|
+
}
|
|
3978
3989
|
}, {
|
|
3979
3990
|
key: "deleteAccessToken",
|
|
3980
|
-
value: function deleteAccessToken(options, accountId) {
|
|
3991
|
+
value: function deleteAccessToken(options, cdnUrl, accountId) {
|
|
3981
3992
|
try {
|
|
3982
3993
|
var _this8 = this;
|
|
3983
|
-
return AuthManagerBrowser_await(AuthManagerBrowser_awaitIgnored(BaseAPI.fetch(_this8.getAccessTokenUrl(
|
|
3994
|
+
return AuthManagerBrowser_await(AuthManagerBrowser_awaitIgnored(BaseAPI.fetch(_this8.getAccessTokenUrl(cdnUrl, accountId, true), {
|
|
3984
3995
|
method: "DELETE",
|
|
3985
3996
|
credentials: "include",
|
|
3986
3997
|
headers: {}
|
|
@@ -3994,13 +4005,13 @@ var AuthManagerImpl = /*#__PURE__*/function () {
|
|
|
3994
4005
|
}
|
|
3995
4006
|
}, {
|
|
3996
4007
|
key: "setAccessToken",
|
|
3997
|
-
value: function setAccessToken(options, accountId, jwt, setCookie) {
|
|
4008
|
+
value: function setAccessToken(options, cdnUrl, accountId, jwt, setCookie) {
|
|
3998
4009
|
try {
|
|
3999
4010
|
var _this9 = this;
|
|
4000
4011
|
var request = {
|
|
4001
4012
|
accessToken: jwt
|
|
4002
4013
|
};
|
|
4003
|
-
return AuthManagerBrowser_await(BaseAPI.fetch(_this9.getAccessTokenUrl(
|
|
4014
|
+
return AuthManagerBrowser_await(BaseAPI.fetch(_this9.getAccessTokenUrl(cdnUrl, accountId, setCookie), {
|
|
4004
4015
|
method: "PUT",
|
|
4005
4016
|
credentials: "include",
|
|
4006
4017
|
headers: AuthManagerBrowser_defineProperty({}, _this9.contentType, _this9.contentTypeJson),
|
|
@@ -3,6 +3,8 @@ export interface AuthSessionConfigBase {
|
|
|
3
3
|
accountId: string;
|
|
4
4
|
/** A string names this configuration. `undefined` deliberately marks it as the session default. */
|
|
5
5
|
authConfigId: string | undefined;
|
|
6
|
+
/** Overrides `options.cdnUrl` for this configuration. Excludes the trailing "/". */
|
|
7
|
+
cdnUrl?: string;
|
|
6
8
|
/** Enables CDN cookie authentication. Defaults to false. */
|
|
7
9
|
enableCookieAuth?: boolean;
|
|
8
10
|
/** Enables CDN service-worker authentication. Defaults to true. */
|
|
@@ -37,6 +37,7 @@ declare class AuthManagerImpl implements AuthManagerInterface {
|
|
|
37
37
|
private waitForServiceWorker;
|
|
38
38
|
private getAccessTokenUrl;
|
|
39
39
|
private getCdnUrl;
|
|
40
|
+
private getConfigCdnUrl;
|
|
40
41
|
private deleteAccessToken;
|
|
41
42
|
private setAccessToken;
|
|
42
43
|
private getAuthorizationToken;
|
package/package.json
CHANGED
|
@@ -203,6 +203,60 @@ describe("AuthManager browser multi-configuration sessions", () => {
|
|
|
203
203
|
});
|
|
204
204
|
});
|
|
205
205
|
|
|
206
|
+
test("uses each config's effective CDN URL for registration, worker prefixes, cleanup, and collisions", async () => {
|
|
207
|
+
const fetchApi = createFetchApi();
|
|
208
|
+
const defaultCdnUrl = "https://downloads-default.example.com";
|
|
209
|
+
const customCdnUrl = "https://downloads-custom.example.com";
|
|
210
|
+
const cookieCdnUrl = "https://downloads-cookie.example.com";
|
|
211
|
+
|
|
212
|
+
await AuthManager.beginAuthSession({
|
|
213
|
+
authConfigs: async () => [
|
|
214
|
+
{
|
|
215
|
+
...apiOnlyConfig("custom-worker", accountA, async () => jwtA),
|
|
216
|
+
cdnUrl: customCdnUrl,
|
|
217
|
+
enableServiceWorkerAuth: true
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
...apiOnlyConfig("default-worker", accountA, async () => jwtB),
|
|
221
|
+
enableServiceWorkerAuth: true
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
...apiOnlyConfig("cookie", accountA, async () => jwtC),
|
|
225
|
+
cdnUrl: cookieCdnUrl,
|
|
226
|
+
enableCookieAuth: true
|
|
227
|
+
}
|
|
228
|
+
],
|
|
229
|
+
options: { cdnUrl: defaultCdnUrl, fetchApi },
|
|
230
|
+
serviceWorkerScript: "/auth-sw.js"
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
expect(fetchApi.mock.calls.filter(([, init]) => init?.method === "PUT").map(([input]) => inputUrl(input))).toEqual([
|
|
234
|
+
`${customCdnUrl}/api/v1/access_tokens/${accountA}?set-cookie=false`,
|
|
235
|
+
`${defaultCdnUrl}/api/v1/access_tokens/${accountA}?set-cookie=false`,
|
|
236
|
+
`${cookieCdnUrl}/api/v1/access_tokens/${accountA}?set-cookie=true`
|
|
237
|
+
]);
|
|
238
|
+
expect((postMessage.mock.calls.at(-1)?.[0] as any).config).toEqual([
|
|
239
|
+
{
|
|
240
|
+
expires: expect.any(Number),
|
|
241
|
+
headers: [{ key: "Authorization", value: `Bearer ${jwtA}` }],
|
|
242
|
+
sourceUrlPrefixes: undefined,
|
|
243
|
+
urlPrefix: `${customCdnUrl}/${accountA}/`
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
expires: expect.any(Number),
|
|
247
|
+
headers: [{ key: "Authorization", value: `Bearer ${jwtB}` }],
|
|
248
|
+
sourceUrlPrefixes: undefined,
|
|
249
|
+
urlPrefix: `${defaultCdnUrl}/${accountA}/`
|
|
250
|
+
}
|
|
251
|
+
]);
|
|
252
|
+
|
|
253
|
+
await AuthManager.endAuthSession();
|
|
254
|
+
|
|
255
|
+
expect(
|
|
256
|
+
fetchApi.mock.calls.filter(([, init]) => init?.method === "DELETE").map(([input]) => inputUrl(input))
|
|
257
|
+
).toEqual([`${cookieCdnUrl}/api/v1/access_tokens/${accountA}?set-cookie=true`]);
|
|
258
|
+
});
|
|
259
|
+
|
|
206
260
|
test("supports a manual cookie-only V2 config without a service worker", async () => {
|
|
207
261
|
delete navigatorValue.serviceWorker;
|
|
208
262
|
const fetchApi = createFetchApi();
|
|
@@ -340,6 +394,14 @@ describe("AuthManager browser multi-configuration sessions", () => {
|
|
|
340
394
|
params: (fetchApi: FetchApi) => v2Params(fetchApi, [apiOnlyConfig("a", "A12/abc", async () => jwtA)]),
|
|
341
395
|
error: "Invalid Bytescale account ID"
|
|
342
396
|
},
|
|
397
|
+
{
|
|
398
|
+
name: "invalid config CDN URL",
|
|
399
|
+
params: (fetchApi: FetchApi) =>
|
|
400
|
+
v2Params(fetchApi, [
|
|
401
|
+
{ ...apiOnlyConfig("a", accountA, async () => jwtA), cdnUrl: 123 } as unknown as AuthSessionConfig
|
|
402
|
+
]),
|
|
403
|
+
error: "cdnUrl"
|
|
404
|
+
},
|
|
343
405
|
{
|
|
344
406
|
name: "overlapping cookie and worker accounts",
|
|
345
407
|
params: (fetchApi: FetchApi): BeginAuthSessionParamsV2 => ({
|
|
@@ -150,6 +150,15 @@ describe("Auth service-worker URL rewriting", () => {
|
|
|
150
150
|
expect(untouched.responded).toBe(false);
|
|
151
151
|
});
|
|
152
152
|
|
|
153
|
+
test("waits for delayed persistent authentication state on a cold start", async () => {
|
|
154
|
+
const harness = new AuthServiceWorkerHarness();
|
|
155
|
+
harness.setPersistentConfig([authConfig("account-a/", "token-a")], 300);
|
|
156
|
+
|
|
157
|
+
const result = await harness.dispatchFetch("https://upcdn.io/account-a/file.pdf");
|
|
158
|
+
|
|
159
|
+
expect(result.outboundRequest?.headers.get("Authorization")).toBe("Bearer token-a");
|
|
160
|
+
});
|
|
161
|
+
|
|
153
162
|
test("keeps source-page authorization independent across multiple client IDs", async () => {
|
|
154
163
|
const harness = new AuthServiceWorkerHarness();
|
|
155
164
|
harness.setWindowClient("client-a", "https://app.example.com/a/");
|
|
@@ -221,6 +230,8 @@ type WorkerEventListener = (event: unknown) => void;
|
|
|
221
230
|
|
|
222
231
|
class AuthServiceWorkerHarness {
|
|
223
232
|
private readonly clientsById = new Map<string, { type: "window"; url: string }>();
|
|
233
|
+
private readonly cacheEntries = new Map<string, NodeFetchResponse>();
|
|
234
|
+
private cacheReadDelayMilliseconds = 0;
|
|
224
235
|
private readonly context: {
|
|
225
236
|
getRewrittenUrl: (url: string, rules: UrlRewriteRule[]) => string | undefined;
|
|
226
237
|
setConfig: (config: AuthSwConfigEntryDto[], rules?: UrlRewriteRule[]) => Promise<void>;
|
|
@@ -231,7 +242,6 @@ class AuthServiceWorkerHarness {
|
|
|
231
242
|
|
|
232
243
|
constructor(private readonly upstreamResponse: NodeFetchResponse = new NodeFetchResponse("ok")) {
|
|
233
244
|
const listeners = new Map<string, WorkerEventListener>();
|
|
234
|
-
const cacheEntries = new Map<string, NodeFetchResponse>();
|
|
235
245
|
this.fetchMock = jest.fn(async (_request: TestRequest): Promise<NodeFetchResponse> => this.upstreamResponse);
|
|
236
246
|
|
|
237
247
|
const self = {
|
|
@@ -246,9 +256,14 @@ class AuthServiceWorkerHarness {
|
|
|
246
256
|
skipWaiting: async (): Promise<void> => {}
|
|
247
257
|
};
|
|
248
258
|
const cache = {
|
|
249
|
-
match: async (key: string): Promise<NodeFetchResponse | undefined> =>
|
|
259
|
+
match: async (key: string): Promise<NodeFetchResponse | undefined> => {
|
|
260
|
+
if (this.cacheReadDelayMilliseconds > 0) {
|
|
261
|
+
await new Promise(resolve => setTimeout(resolve, this.cacheReadDelayMilliseconds));
|
|
262
|
+
}
|
|
263
|
+
return this.cacheEntries.get(key)?.clone();
|
|
264
|
+
},
|
|
250
265
|
put: async (key: string, value: NodeFetchResponse): Promise<void> => {
|
|
251
|
-
cacheEntries.set(key, value.clone());
|
|
266
|
+
this.cacheEntries.set(key, value.clone());
|
|
252
267
|
}
|
|
253
268
|
};
|
|
254
269
|
const sandbox = {
|
|
@@ -284,6 +299,11 @@ class AuthServiceWorkerHarness {
|
|
|
284
299
|
this.clientsById.set(clientId, { type: "window", url });
|
|
285
300
|
}
|
|
286
301
|
|
|
302
|
+
setPersistentConfig(config: AuthSwConfigEntryDto[], cacheReadDelayMilliseconds: number): void {
|
|
303
|
+
this.cacheEntries.set("config", new NodeFetchResponse(JSON.stringify(config)));
|
|
304
|
+
this.cacheReadDelayMilliseconds = cacheReadDelayMilliseconds;
|
|
305
|
+
}
|
|
306
|
+
|
|
287
307
|
async dispatchFetch(url: string, options: FetchOptions = {}): Promise<FetchResult> {
|
|
288
308
|
const request = new TestRequest(url, { headers: options.headers as NodeFetchRequestInit["headers"] });
|
|
289
309
|
if (options.navigation === true) {
|