@pega/auth 0.2.25 → 0.2.27
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/lib/oauth-client/auth.js +571 -562
- package/lib/oauth-client/auth.js.map +1 -1
- package/lib/sdk-auth-manager/authManager.d.ts.map +1 -1
- package/lib/sdk-auth-manager/authManager.js +685 -671
- package/lib/sdk-auth-manager/authManager.js.map +1 -1
- package/lib/sdk-auth-manager/config_access.js +50 -75
- package/lib/sdk-auth-manager/config_access.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
// This file wraps various calls related to logging in, logging out, etc.
|
|
2
2
|
// that use the auth.html/auth.js to do the work of logging in via OAuth 2.0.
|
|
3
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
4
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
5
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
6
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
7
|
-
};
|
|
8
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
9
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
10
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
11
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
12
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
13
|
-
};
|
|
14
|
-
var _AuthManager_instances, _AuthManager_ssKeyPrefix, _AuthManager_pegaAuth, _AuthManager_ssKeyConfigInfo, _AuthManager_ssKeySessionInfo, _AuthManager_ssKeyTokenInfo, _AuthManager_ssKeyState, _AuthManager_authConfig, _AuthManager_authDynState, _AuthManager_authHeader, _AuthManager_customTokenParamsCB, _AuthManager_bOAuthCustom, _AuthManager_tokenInfo, _AuthManager_userInfo, _AuthManager_usePASS, _AuthManager_beforeUnloadAdded, _AuthManager_tokenStorage, _AuthManager_transform, _AuthManager_foldSpot, _AuthManager_loadUserinfo, _AuthManager_loginProps, _AuthManager_promiseInitialize, _AuthManager_transformAndParse, _AuthManager_getStorage, _AuthManager_setStorage, _AuthManager_calcFoldSpot, _AuthManager_transformer, _AuthManager_doUnloadUpdates, _AuthManager_doBeforeUnload, _AuthManager_doPageHide, _AuthManager_loadState, _AuthManager_doOnLoad, _AuthManager_doAuthDynStateChanged, _AuthManager_initialize, _AuthManager_constellationInit, _AuthManager_customConstellationInit, _AuthManager_fireTokenAvailable, _AuthManager_processTokenOnLogin, _AuthManager_doCustomTokenParamsCB, _AuthManager_updateLoginStatus, _AuthManager_authFullReauth, _AuthManager_authTokenUpdated;
|
|
15
3
|
// It utilizes a JS Class and private members to protect any sensitive tokens
|
|
16
4
|
// and token obfuscation routines
|
|
17
5
|
import { PegaAuth } from '../oauth-client/auth.js';
|
|
@@ -19,112 +7,158 @@ import { isEmptyObject } from './common-utils.js';
|
|
|
19
7
|
import { getSdkConfig, SdkConfigAccess } from './config_access.js';
|
|
20
8
|
// Meant to be a singleton...only one instance per page
|
|
21
9
|
class AuthManager {
|
|
10
|
+
#ssKeyPrefix = 'rs';
|
|
11
|
+
iOSDevice = false;
|
|
12
|
+
// will store the PegaAuth (OAuth 2.0 client library) instance
|
|
13
|
+
#pegaAuth = null;
|
|
14
|
+
#ssKeyConfigInfo = '';
|
|
15
|
+
#ssKeySessionInfo = '';
|
|
16
|
+
#ssKeyTokenInfo = '';
|
|
17
|
+
#ssKeyState = `${this.#ssKeyPrefix}State`;
|
|
18
|
+
#authConfig = {};
|
|
19
|
+
#authDynState = {};
|
|
20
|
+
#authHeader = null;
|
|
21
|
+
#customTokenParamsCB = null;
|
|
22
|
+
// state that should be persisted across loads
|
|
23
|
+
state = { usePopup: false, noInitialRedirect: false, locale: null };
|
|
24
|
+
// # of properties within initial state object
|
|
25
|
+
stateKeysCount = 3;
|
|
26
|
+
bC11NBootstrapInProgress = false;
|
|
27
|
+
bC11NBootstrapComplete = false;
|
|
28
|
+
bCustomAuth = false;
|
|
29
|
+
#bOAuthCustom = false;
|
|
30
|
+
#tokenInfo;
|
|
31
|
+
#userInfo;
|
|
32
|
+
onLoadDone = false;
|
|
33
|
+
msReauthStart = null;
|
|
34
|
+
initInProgress = false;
|
|
35
|
+
isLoggedIn = false;
|
|
36
|
+
// Whether to pass a session storage key or structure to auth library
|
|
37
|
+
#usePASS = false;
|
|
38
|
+
#beforeUnloadAdded = false;
|
|
39
|
+
#tokenStorage = 'temp';
|
|
40
|
+
#transform = true;
|
|
41
|
+
#foldSpot = 2;
|
|
42
|
+
// Whether to load and cache user info as part of login
|
|
43
|
+
#loadUserinfo = false;
|
|
44
|
+
// Keep loginProps passed to loginIfNecessary
|
|
45
|
+
#loginProps = null;
|
|
46
|
+
// Promise for Initialization of PegaAuth and resolution callback
|
|
47
|
+
#promiseInitialize = null;
|
|
22
48
|
constructor() {
|
|
23
|
-
_AuthManager_instances.add(this);
|
|
24
|
-
_AuthManager_ssKeyPrefix.set(this, 'rs');
|
|
25
|
-
Object.defineProperty(this, "iOSDevice", {
|
|
26
|
-
enumerable: true,
|
|
27
|
-
configurable: true,
|
|
28
|
-
writable: true,
|
|
29
|
-
value: false
|
|
30
|
-
});
|
|
31
|
-
// will store the PegaAuth (OAuth 2.0 client library) instance
|
|
32
|
-
_AuthManager_pegaAuth.set(this, null);
|
|
33
|
-
_AuthManager_ssKeyConfigInfo.set(this, '');
|
|
34
|
-
_AuthManager_ssKeySessionInfo.set(this, '');
|
|
35
|
-
_AuthManager_ssKeyTokenInfo.set(this, '');
|
|
36
|
-
_AuthManager_ssKeyState.set(this, `${__classPrivateFieldGet(this, _AuthManager_ssKeyPrefix, "f")}State`);
|
|
37
|
-
_AuthManager_authConfig.set(this, {});
|
|
38
|
-
_AuthManager_authDynState.set(this, {});
|
|
39
|
-
_AuthManager_authHeader.set(this, null);
|
|
40
|
-
_AuthManager_customTokenParamsCB.set(this, null);
|
|
41
|
-
// state that should be persisted across loads
|
|
42
|
-
Object.defineProperty(this, "state", {
|
|
43
|
-
enumerable: true,
|
|
44
|
-
configurable: true,
|
|
45
|
-
writable: true,
|
|
46
|
-
value: { usePopup: false, noInitialRedirect: false, locale: null }
|
|
47
|
-
});
|
|
48
|
-
// # of properties within initial state object
|
|
49
|
-
Object.defineProperty(this, "stateKeysCount", {
|
|
50
|
-
enumerable: true,
|
|
51
|
-
configurable: true,
|
|
52
|
-
writable: true,
|
|
53
|
-
value: 3
|
|
54
|
-
});
|
|
55
|
-
Object.defineProperty(this, "bC11NBootstrapInProgress", {
|
|
56
|
-
enumerable: true,
|
|
57
|
-
configurable: true,
|
|
58
|
-
writable: true,
|
|
59
|
-
value: false
|
|
60
|
-
});
|
|
61
|
-
Object.defineProperty(this, "bCustomAuth", {
|
|
62
|
-
enumerable: true,
|
|
63
|
-
configurable: true,
|
|
64
|
-
writable: true,
|
|
65
|
-
value: false
|
|
66
|
-
});
|
|
67
|
-
_AuthManager_bOAuthCustom.set(this, false);
|
|
68
|
-
_AuthManager_tokenInfo.set(this, void 0);
|
|
69
|
-
_AuthManager_userInfo.set(this, void 0);
|
|
70
|
-
Object.defineProperty(this, "onLoadDone", {
|
|
71
|
-
enumerable: true,
|
|
72
|
-
configurable: true,
|
|
73
|
-
writable: true,
|
|
74
|
-
value: false
|
|
75
|
-
});
|
|
76
|
-
Object.defineProperty(this, "msReauthStart", {
|
|
77
|
-
enumerable: true,
|
|
78
|
-
configurable: true,
|
|
79
|
-
writable: true,
|
|
80
|
-
value: null
|
|
81
|
-
});
|
|
82
|
-
Object.defineProperty(this, "initInProgress", {
|
|
83
|
-
enumerable: true,
|
|
84
|
-
configurable: true,
|
|
85
|
-
writable: true,
|
|
86
|
-
value: false
|
|
87
|
-
});
|
|
88
|
-
Object.defineProperty(this, "isLoggedIn", {
|
|
89
|
-
enumerable: true,
|
|
90
|
-
configurable: true,
|
|
91
|
-
writable: true,
|
|
92
|
-
value: false
|
|
93
|
-
});
|
|
94
|
-
// Whether to pass a session storage key or structure to auth library
|
|
95
|
-
_AuthManager_usePASS.set(this, false);
|
|
96
|
-
_AuthManager_beforeUnloadAdded.set(this, false);
|
|
97
|
-
_AuthManager_tokenStorage.set(this, 'temp');
|
|
98
|
-
_AuthManager_transform.set(this, true);
|
|
99
|
-
_AuthManager_foldSpot.set(this, 2);
|
|
100
|
-
// Whether to load and cache user info as part of login
|
|
101
|
-
_AuthManager_loadUserinfo.set(this, false);
|
|
102
|
-
// Keep loginProps passed to loginIfNecessary
|
|
103
|
-
_AuthManager_loginProps.set(this, null);
|
|
104
|
-
// Promise for Initialization of PegaAuth and resolution callback
|
|
105
|
-
_AuthManager_promiseInitialize.set(this, null);
|
|
106
49
|
// Auth Manager specific state is saved within session storage as important in redirect and popup window scenarios
|
|
107
|
-
|
|
50
|
+
this.#loadState();
|
|
108
51
|
this.iOSDevice = /iPad|iPhone|iPod/.test(navigator.userAgent);
|
|
109
52
|
}
|
|
53
|
+
#transformAndParse(ssKey, ssItem, bForce = false) {
|
|
54
|
+
let obj = {};
|
|
55
|
+
try {
|
|
56
|
+
obj = JSON.parse(this.#transformer(ssKey, ssItem, false, bForce));
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
// fall thru and return empty object
|
|
60
|
+
}
|
|
61
|
+
return obj;
|
|
62
|
+
}
|
|
63
|
+
// helper routine to retrieve JSON object stored in a session storage key
|
|
64
|
+
// a 2nd optional arg can also retrieve an individual attribute
|
|
65
|
+
#getStorage(ssKey, sAttrib = null) {
|
|
66
|
+
let ssItem = ssKey ? window.sessionStorage.getItem(ssKey) : null;
|
|
67
|
+
let obj = {};
|
|
68
|
+
if (this.#loginProps?.altStateStorage &&
|
|
69
|
+
!this.isLoggedIn &&
|
|
70
|
+
!ssItem &&
|
|
71
|
+
(ssKey === this.#ssKeyState || ssKey === this.#ssKeySessionInfo)) {
|
|
72
|
+
ssItem = window.localStorage.getItem(ssKey);
|
|
73
|
+
}
|
|
74
|
+
if (ssItem) {
|
|
75
|
+
try {
|
|
76
|
+
obj = JSON.parse(ssItem);
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
obj = this.#transformAndParse(ssKey, ssItem, true);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return sAttrib ? obj[sAttrib] : obj;
|
|
83
|
+
}
|
|
84
|
+
// helper routine to set storage to the passed in JSON
|
|
85
|
+
#setStorage(ssKey, obj, bVerify = false) {
|
|
86
|
+
try {
|
|
87
|
+
// Set storage only if obj is not empty, else delete the storage
|
|
88
|
+
if (!obj || isEmptyObject(obj)) {
|
|
89
|
+
window.sessionStorage.removeItem(ssKey);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
// const bClear = (ssKey === this.#ssKeyState || ssKey === this.#ssKeySessionInfo);
|
|
93
|
+
const bClear = false;
|
|
94
|
+
const sValue = bClear
|
|
95
|
+
? JSON.stringify(obj)
|
|
96
|
+
: this.#transformer(ssKey, JSON.stringify(obj), true);
|
|
97
|
+
window.sessionStorage.setItem(ssKey, sValue);
|
|
98
|
+
if (bVerify) {
|
|
99
|
+
const sStored = window.sessionStorage.getItem(ssKey);
|
|
100
|
+
if (sStored !== sValue) {
|
|
101
|
+
// eslint-disable-next-line no-console
|
|
102
|
+
console.error(`Failed to properly write sessionStorage (${ssKey})`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (this.#loginProps?.altStateStorage &&
|
|
106
|
+
!this.isLoggedIn &&
|
|
107
|
+
(ssKey === this.#ssKeyState || ssKey === this.#ssKeySessionInfo)) {
|
|
108
|
+
window.localStorage.setItem(ssKey, sValue);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (e) {
|
|
113
|
+
// eslint-disable-next-line no-console
|
|
114
|
+
console.error(`Exception ${e} on attempted write of sessionStorage (${ssKey})`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
#calcFoldSpot(s) {
|
|
118
|
+
const nOffset = 1;
|
|
119
|
+
const sChar = s.length > nOffset ? s.charAt(nOffset) : '2';
|
|
120
|
+
const nSpot = parseInt(sChar, 10);
|
|
121
|
+
this.#foldSpot = Number.isNaN(nSpot) ? 2 : (nSpot % 4) + 2;
|
|
122
|
+
}
|
|
123
|
+
// helper function to encode storage
|
|
124
|
+
#transformer(ssKey, s, bIn, bForce = false) {
|
|
125
|
+
const bTransform = bForce || this.#transform;
|
|
126
|
+
const fnFold = (x) => {
|
|
127
|
+
const nLen = x.length;
|
|
128
|
+
const nExtra = nLen % this.#foldSpot;
|
|
129
|
+
const nOffset = Math.floor(nLen / this.#foldSpot) + nExtra;
|
|
130
|
+
const nRem = x.length - nOffset;
|
|
131
|
+
return x.substring(bIn ? nOffset : nRem) + x.substring(0, bIn ? nOffset : nRem);
|
|
132
|
+
};
|
|
133
|
+
const bTknInfo = ssKey === this.#ssKeyTokenInfo;
|
|
134
|
+
if (bTknInfo && !bIn && bTransform) {
|
|
135
|
+
s = window.atob(fnFold(s));
|
|
136
|
+
}
|
|
137
|
+
// eslint-disable-next-line no-nested-ternary
|
|
138
|
+
let result = bTransform ? (bIn ? window.btoa(s) : window.atob(s)) : s;
|
|
139
|
+
if (bTknInfo && bIn && bTransform) {
|
|
140
|
+
result = fnFold(window.btoa(result));
|
|
141
|
+
}
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
110
144
|
// Setter for authHeader (no getter)
|
|
111
145
|
set authHeader(value) {
|
|
112
|
-
|
|
146
|
+
this.#authHeader = value;
|
|
113
147
|
// setAuthorizationHeader method not available til 8.8 so do safety check
|
|
114
148
|
if (window.PCore?.getAuthUtils().setAuthorizationHeader) {
|
|
115
149
|
const authHdr = value === null ? '' : value;
|
|
116
150
|
window.PCore.getAuthUtils().setAuthorizationHeader(authHdr);
|
|
117
151
|
}
|
|
118
|
-
|
|
152
|
+
this.#updateLoginStatus();
|
|
119
153
|
}
|
|
120
154
|
// Setter for customTokenParamsCB
|
|
121
155
|
set customTokenParamsCB(fn) {
|
|
122
|
-
|
|
156
|
+
this.#customTokenParamsCB = fn;
|
|
123
157
|
}
|
|
124
158
|
// Setter/getter for appName
|
|
125
159
|
set appName(appName) {
|
|
126
160
|
this.state.appName = appName;
|
|
127
|
-
|
|
161
|
+
this.#setStorage(this.#ssKeyState, this.state);
|
|
128
162
|
}
|
|
129
163
|
get appName() {
|
|
130
164
|
return this.state.appName;
|
|
@@ -132,7 +166,7 @@ class AuthManager {
|
|
|
132
166
|
// Setter/getter for usePopupForRestOfSession
|
|
133
167
|
set usePopupForRestOfSession(usePopup) {
|
|
134
168
|
this.state.usePopup = usePopup;
|
|
135
|
-
|
|
169
|
+
this.#setStorage(this.#ssKeyState, this.state);
|
|
136
170
|
}
|
|
137
171
|
get usePopupForRestOfSession() {
|
|
138
172
|
return this.state.usePopup;
|
|
@@ -143,7 +177,7 @@ class AuthManager {
|
|
|
143
177
|
this.usePopupForRestOfSession = true;
|
|
144
178
|
}
|
|
145
179
|
this.state.noInitialRedirect = bNoInitialRedirect;
|
|
146
|
-
|
|
180
|
+
this.#setStorage(this.#ssKeyState, this.state);
|
|
147
181
|
}
|
|
148
182
|
get noInitialRedirect() {
|
|
149
183
|
return this.state.noInitialRedirect || false;
|
|
@@ -151,7 +185,7 @@ class AuthManager {
|
|
|
151
185
|
// Setter/getter for locale (override)
|
|
152
186
|
set locale(localeOverride) {
|
|
153
187
|
this.state.locale = localeOverride;
|
|
154
|
-
|
|
188
|
+
this.#setStorage(this.#ssKeyState, this.state);
|
|
155
189
|
}
|
|
156
190
|
get locale() {
|
|
157
191
|
return this.state.locale;
|
|
@@ -164,7 +198,7 @@ class AuthManager {
|
|
|
164
198
|
else if (this.msReauthStart) {
|
|
165
199
|
delete this.msReauthStart;
|
|
166
200
|
}
|
|
167
|
-
|
|
201
|
+
this.#setStorage(this.#ssKeyState, this.state);
|
|
168
202
|
}
|
|
169
203
|
get reauthStart() {
|
|
170
204
|
return this.msReauthStart || 0;
|
|
@@ -173,22 +207,22 @@ class AuthManager {
|
|
|
173
207
|
set keySuffix(s) {
|
|
174
208
|
this.state.sfx = s || undefined;
|
|
175
209
|
if (s) {
|
|
176
|
-
|
|
210
|
+
this.#setStorage(this.#ssKeyState, this.state);
|
|
177
211
|
// To make it a bit more obtuse reverse the string and use that as the actual suffix
|
|
178
212
|
const sSfx = s.split('').reverse().join('');
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
213
|
+
this.#ssKeyConfigInfo = `${this.#ssKeyPrefix}CI_${sSfx}`;
|
|
214
|
+
this.#ssKeySessionInfo = `${this.#ssKeyPrefix}SI_${sSfx}`;
|
|
215
|
+
this.#ssKeyTokenInfo = `${this.#ssKeyPrefix}TI_${sSfx}`;
|
|
216
|
+
this.#calcFoldSpot(sSfx);
|
|
183
217
|
}
|
|
184
218
|
else {
|
|
185
|
-
sessionStorage.removeItem(
|
|
186
|
-
sessionStorage.removeItem(
|
|
187
|
-
sessionStorage.removeItem(
|
|
188
|
-
sessionStorage.removeItem(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
219
|
+
sessionStorage.removeItem(this.#ssKeyTokenInfo);
|
|
220
|
+
sessionStorage.removeItem(this.#ssKeyConfigInfo);
|
|
221
|
+
sessionStorage.removeItem(this.#ssKeySessionInfo);
|
|
222
|
+
sessionStorage.removeItem(this.#ssKeyState);
|
|
223
|
+
this.#ssKeyConfigInfo = '';
|
|
224
|
+
this.#ssKeySessionInfo = '';
|
|
225
|
+
this.#ssKeyTokenInfo = '';
|
|
192
226
|
}
|
|
193
227
|
}
|
|
194
228
|
/**
|
|
@@ -196,25 +230,444 @@ class AuthManager {
|
|
|
196
230
|
*/
|
|
197
231
|
clear(bFullReauth = false) {
|
|
198
232
|
if (!this.bCustomAuth) {
|
|
199
|
-
|
|
233
|
+
this.#authHeader = null;
|
|
200
234
|
}
|
|
201
235
|
// Clear any established auth tokens
|
|
202
|
-
|
|
203
|
-
sessionStorage.removeItem(
|
|
236
|
+
this.#tokenInfo = null;
|
|
237
|
+
sessionStorage.removeItem(this.#ssKeyTokenInfo);
|
|
204
238
|
this.isLoggedIn = false;
|
|
205
239
|
// reset the initial redirect as well by using this setter
|
|
206
240
|
this.usePopupForRestOfSession = bFullReauth;
|
|
207
241
|
if (!bFullReauth) {
|
|
208
|
-
if (!
|
|
209
|
-
|
|
210
|
-
|
|
242
|
+
if (!this.#usePASS) {
|
|
243
|
+
this.#authConfig = {};
|
|
244
|
+
this.#authDynState = {};
|
|
211
245
|
}
|
|
212
246
|
// keySuffix setter has cleanup logic
|
|
213
247
|
this.keySuffix = '';
|
|
214
248
|
}
|
|
215
249
|
}
|
|
250
|
+
// Found beforeunload to not work well on iOS browsers, and pagehide to work better
|
|
251
|
+
// However also seeing some scenario like navigating to a different page on Chrome & Firefox only invoking beforeunload
|
|
252
|
+
// Chrome, Firefox, Safari browsers sequence on page reload: beforeunload, pagehide, visibilitychange
|
|
253
|
+
// visibilitychange is fired whenever a tab is made visible and when it is hidden
|
|
254
|
+
#doUnloadUpdates() {
|
|
255
|
+
// Safari and particularly Safari on mobile devices doesn't seem to load this on first main redirect or
|
|
256
|
+
// reliably, so have moved to having PegaAuth manage writing all state props to session storage
|
|
257
|
+
this.#setStorage(this.#ssKeyState, this.state);
|
|
258
|
+
this.#setStorage(this.#ssKeySessionInfo, this.#authDynState);
|
|
259
|
+
// If tokenStorage was always, token would already be there
|
|
260
|
+
if (this.#tokenStorage === 'temp') {
|
|
261
|
+
this.#setStorage(this.#ssKeyTokenInfo, this.#tokenInfo);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
#doBeforeUnload() {
|
|
265
|
+
this.#doUnloadUpdates();
|
|
266
|
+
}
|
|
267
|
+
#doPageHide() {
|
|
268
|
+
this.#doUnloadUpdates();
|
|
269
|
+
}
|
|
270
|
+
#loadState() {
|
|
271
|
+
// Note: State storage key doesn't have a client id associated with it
|
|
272
|
+
const oState = this.#getStorage(this.#ssKeyState);
|
|
273
|
+
if (oState) {
|
|
274
|
+
Object.assign(this.state, oState);
|
|
275
|
+
if (this.state.sfx) {
|
|
276
|
+
// Setter sets up the ssKey values as well
|
|
277
|
+
this.keySuffix = this.state.sfx;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// This is only called from initialize after #ssKey values are setup
|
|
282
|
+
#doOnLoad() {
|
|
283
|
+
if (!this.onLoadDone) {
|
|
284
|
+
// This authConfig state doesn't collide with other calculated static state...so load it first
|
|
285
|
+
// Note: transform setting will have already been loaded into #authConfig at this point
|
|
286
|
+
this.#authDynState = this.#getStorage(this.#ssKeySessionInfo);
|
|
287
|
+
this.#tokenInfo = this.#getStorage(this.#ssKeyTokenInfo);
|
|
288
|
+
if (this.#tokenStorage !== 'always') {
|
|
289
|
+
sessionStorage.removeItem(this.#ssKeyTokenInfo);
|
|
290
|
+
// Finding on iOS browsers the pageHide event is sometimes not happening causing failed redirects.
|
|
291
|
+
if (!this.iOSDevice) {
|
|
292
|
+
sessionStorage.removeItem(this.#ssKeySessionInfo);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
this.onLoadDone = true;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
// Callback when auth dynamic state has changed. Decide whether to persisting it based on
|
|
299
|
+
// config settings
|
|
300
|
+
#doAuthDynStateChanged() {
|
|
301
|
+
// If tokenStorage is setup for always then always persist the auth dynamic state as well
|
|
302
|
+
if (this.#tokenStorage === 'always' || this.iOSDevice) {
|
|
303
|
+
this.#setStorage(this.#ssKeySessionInfo, this.#authDynState);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Initialize OAuth config structure members and create authMgr instance (if necessary)
|
|
308
|
+
* bNew - governs whether to create new sessionStorage or load existing one
|
|
309
|
+
*/
|
|
310
|
+
async #initialize(bNew = false) {
|
|
311
|
+
if (!bNew && this.#promiseInitialize) {
|
|
312
|
+
return this.#promiseInitialize;
|
|
313
|
+
}
|
|
314
|
+
this.#promiseInitialize = new Promise(resolve => {
|
|
315
|
+
/* if (!this.initInProgress && (bNew || isEmptyObject(this.#authConfig) || !this.#pegaAuth)) { */
|
|
316
|
+
this.initInProgress = true;
|
|
317
|
+
getSdkConfig().then(sdkConfig => {
|
|
318
|
+
const sdkConfigAuth = sdkConfig.authConfig;
|
|
319
|
+
const sdkConfigServer = sdkConfig.serverConfig;
|
|
320
|
+
const serverType = sdkConfigServer.serverType || 'infinity';
|
|
321
|
+
const bInfinity = serverType === 'infinity';
|
|
322
|
+
let pegaUrl = bInfinity
|
|
323
|
+
? sdkConfigServer.infinityRestServerUrl
|
|
324
|
+
: sdkConfigServer.launchpadRestServerUrl;
|
|
325
|
+
// Expecting boolean true/false or undefined
|
|
326
|
+
const secureCookie = !!sdkConfigAuth.secureCookie;
|
|
327
|
+
const bNoInitialRedirect = this.noInitialRedirect;
|
|
328
|
+
const appAliasSeg = sdkConfigServer.appAlias ? `app/${sdkConfigServer.appAlias}/` : '';
|
|
329
|
+
// Construct default OAuth endpoints (if not explicitly specified)
|
|
330
|
+
if (pegaUrl) {
|
|
331
|
+
// Cope with trailing slash being present
|
|
332
|
+
if (!pegaUrl.endsWith('/')) {
|
|
333
|
+
pegaUrl += '/';
|
|
334
|
+
}
|
|
335
|
+
if (!sdkConfigAuth.authorize) {
|
|
336
|
+
sdkConfigAuth.authorize = bInfinity
|
|
337
|
+
? `${pegaUrl}PRRestService/oauth2/v1/authorize`
|
|
338
|
+
: `${pegaUrl}uas/oauth/authorize`;
|
|
339
|
+
}
|
|
340
|
+
const infinityOAuth2Url = bInfinity
|
|
341
|
+
? pegaUrl + (secureCookie && appAliasSeg ? `${appAliasSeg}api/` : 'PRRestService/')
|
|
342
|
+
: '';
|
|
343
|
+
if (!sdkConfigAuth.token) {
|
|
344
|
+
sdkConfigAuth.token = bInfinity
|
|
345
|
+
? `${infinityOAuth2Url}oauth2/v1/token`
|
|
346
|
+
: `${pegaUrl}uas/oauth/token`;
|
|
347
|
+
}
|
|
348
|
+
if (!sdkConfigAuth.revoke) {
|
|
349
|
+
// Launchpad still does not have a revoke endpoint
|
|
350
|
+
sdkConfigAuth.revoke = bInfinity ? `${infinityOAuth2Url}oauth2/v1/revoke` : '';
|
|
351
|
+
}
|
|
352
|
+
if (!sdkConfigAuth.redirectUri) {
|
|
353
|
+
sdkConfigAuth.redirectUri = `${window.location.origin}${window.location.pathname}`;
|
|
354
|
+
}
|
|
355
|
+
if (!sdkConfigAuth.userinfo) {
|
|
356
|
+
sdkConfigAuth.userinfo = bInfinity
|
|
357
|
+
? `${pegaUrl}${appAliasSeg}api/oauthclients/v1/userinfo/JSON`
|
|
358
|
+
: '';
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
// Auth service alias
|
|
362
|
+
if (!sdkConfigAuth.authService) {
|
|
363
|
+
sdkConfigAuth.authService = 'pega';
|
|
364
|
+
}
|
|
365
|
+
// mashupAuthService provides way to have a different auth service for embedded
|
|
366
|
+
if (!sdkConfigAuth.mashupAuthService) {
|
|
367
|
+
sdkConfigAuth.mashupAuthService = sdkConfigAuth.authService;
|
|
368
|
+
}
|
|
369
|
+
// Construct path to auth.html (used for case when not doing a main window redirect)
|
|
370
|
+
let sNoMainRedirectUri = sdkConfigAuth.redirectUri;
|
|
371
|
+
const nLastPathSep = sNoMainRedirectUri.lastIndexOf('/');
|
|
372
|
+
sNoMainRedirectUri =
|
|
373
|
+
nLastPathSep !== -1
|
|
374
|
+
? `${sNoMainRedirectUri.substring(0, nLastPathSep + 1)}auth.html`
|
|
375
|
+
: `${sNoMainRedirectUri}/auth.html`;
|
|
376
|
+
const portalGrantType = sdkConfigAuth.portalGrantType || 'authCode';
|
|
377
|
+
const mashupGrantType = sdkConfigAuth.mashupGrantType || 'authCode';
|
|
378
|
+
// Some grant types are only available with confidential registrations and require a client secret
|
|
379
|
+
const clientSecret = bNoInitialRedirect
|
|
380
|
+
? sdkConfigAuth.mashupClientSecret
|
|
381
|
+
: sdkConfigAuth.portalClientSecret;
|
|
382
|
+
const pegaAuthConfig = {
|
|
383
|
+
serverType,
|
|
384
|
+
clientId: bNoInitialRedirect
|
|
385
|
+
? sdkConfigAuth.mashupClientId
|
|
386
|
+
: sdkConfigAuth.portalClientId,
|
|
387
|
+
grantType: bNoInitialRedirect ? mashupGrantType : portalGrantType,
|
|
388
|
+
tokenUri: sdkConfigAuth.token,
|
|
389
|
+
revokeUri: sdkConfigAuth.revoke,
|
|
390
|
+
userinfoUri: sdkConfigAuth.userinfo,
|
|
391
|
+
authService: bNoInitialRedirect
|
|
392
|
+
? sdkConfigAuth.mashupAuthService
|
|
393
|
+
: sdkConfigAuth.authService,
|
|
394
|
+
appAlias: sdkConfigServer.appAlias || '',
|
|
395
|
+
useLocking: true
|
|
396
|
+
};
|
|
397
|
+
if (clientSecret) {
|
|
398
|
+
pegaAuthConfig.clientSecret = clientSecret;
|
|
399
|
+
}
|
|
400
|
+
if (serverType === 'launchpad' && pegaAuthConfig.grantType === 'authCode') {
|
|
401
|
+
pegaAuthConfig.noPKCE = true;
|
|
402
|
+
}
|
|
403
|
+
// Invoke keySuffix setter
|
|
404
|
+
// Was using pegaAuthConfig.clientId as key but more secure to just use a random string as getting
|
|
405
|
+
// both a clientId and the refresh token could yield a new access token.
|
|
406
|
+
// Suffix is so we might in future move to an array of suffixes based on the appName, so might store
|
|
407
|
+
// both portal and embedded tokens/session info at same time
|
|
408
|
+
if (!this.state?.sfx) {
|
|
409
|
+
// Just using a random number to make the suffix unique on each session
|
|
410
|
+
this.keySuffix = `${Math.ceil(Math.random() * 100000000)}`;
|
|
411
|
+
}
|
|
412
|
+
this.#authConfig.transform =
|
|
413
|
+
sdkConfigAuth.transform !== undefined ? sdkConfigAuth.transform : this.#transform;
|
|
414
|
+
// Using property in class as authConfig may be empty at times
|
|
415
|
+
this.#transform = this.#authConfig.transform;
|
|
416
|
+
if (sdkConfigAuth.tokenStorage !== undefined) {
|
|
417
|
+
this.#tokenStorage = sdkConfigAuth.tokenStorage;
|
|
418
|
+
}
|
|
419
|
+
if (sdkConfigAuth.secureCookie) {
|
|
420
|
+
this.#authConfig.secureCookie = true;
|
|
421
|
+
}
|
|
422
|
+
// Get latest state once client ids, transform and tokenStorage have been established
|
|
423
|
+
this.#doOnLoad();
|
|
424
|
+
// If no clientId is specified assume not OAuth but custom auth
|
|
425
|
+
if (pegaAuthConfig.grantType === 'none' || !pegaAuthConfig.clientId) {
|
|
426
|
+
this.bCustomAuth = true;
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
// For some OAuth grant type scenarios we opt to pass the Orchestration Engine just an authHeader as
|
|
430
|
+
// service broker doesn't have proper support for dealing with refreshing or revoking these:
|
|
431
|
+
// * customBearer (except when secureCookie being used)
|
|
432
|
+
// * confidential grant types (ones with clientSecret)
|
|
433
|
+
// (With 25.1 orchestration engine does support this if client_secret is specified on bootstrap)
|
|
434
|
+
this.#bOAuthCustom =
|
|
435
|
+
(pegaAuthConfig.grantType === 'customBearer' && !secureCookie) || clientSecret;
|
|
436
|
+
if (pegaAuthConfig.grantType === 'authCode') {
|
|
437
|
+
const authCodeProps = {
|
|
438
|
+
authorizeUri: sdkConfigAuth.authorize,
|
|
439
|
+
// If we have already specified a redirect on the authorize redirect, we need to continue to use that
|
|
440
|
+
// on token endpoint
|
|
441
|
+
redirectUri: bNoInitialRedirect || this.usePopupForRestOfSession
|
|
442
|
+
? sNoMainRedirectUri
|
|
443
|
+
: sdkConfigAuth.redirectUri
|
|
444
|
+
};
|
|
445
|
+
if ('silentTimeout' in sdkConfigAuth) {
|
|
446
|
+
authCodeProps.silentTimeout = sdkConfigAuth.silentTimeout;
|
|
447
|
+
}
|
|
448
|
+
if (bNoInitialRedirect &&
|
|
449
|
+
pegaAuthConfig.authService === 'pega' &&
|
|
450
|
+
sdkConfigAuth.mashupUserIdentifier &&
|
|
451
|
+
sdkConfigAuth.mashupPassword) {
|
|
452
|
+
authCodeProps.userIdentifier = sdkConfigAuth.mashupUserIdentifier;
|
|
453
|
+
authCodeProps.password = sdkConfigAuth.mashupPassword;
|
|
454
|
+
}
|
|
455
|
+
if ('iframeLoginUI' in sdkConfigAuth) {
|
|
456
|
+
authCodeProps.iframeLoginUI =
|
|
457
|
+
sdkConfigAuth.iframeLoginUI.toString().toLowerCase() === 'true';
|
|
458
|
+
}
|
|
459
|
+
Object.assign(pegaAuthConfig, authCodeProps);
|
|
460
|
+
}
|
|
461
|
+
else if (pegaAuthConfig.grantType === 'passwordCreds') {
|
|
462
|
+
pegaAuthConfig.userIdentifier = sdkConfigAuth.mashupUserIdentifier;
|
|
463
|
+
pegaAuthConfig.password = sdkConfigAuth.mashupPassword;
|
|
464
|
+
}
|
|
465
|
+
Object.assign(this.#authConfig, pegaAuthConfig);
|
|
466
|
+
// Add beforeunload and page hide handlers to write out key properties that we want to survive a
|
|
467
|
+
// browser reload
|
|
468
|
+
if (!this.#beforeUnloadAdded && (!this.#usePASS || this.#tokenStorage !== 'always')) {
|
|
469
|
+
window.addEventListener('beforeunload', this.#doBeforeUnload.bind(this));
|
|
470
|
+
window.addEventListener('pagehide', this.#doPageHide.bind(this));
|
|
471
|
+
this.#beforeUnloadAdded = true;
|
|
472
|
+
}
|
|
473
|
+
// Initialize PegaAuth OAuth 2.0 client library
|
|
474
|
+
if (this.#usePASS) {
|
|
475
|
+
this.#setStorage(this.#ssKeyConfigInfo, this.#authConfig);
|
|
476
|
+
this.#setStorage(this.#ssKeySessionInfo, this.#authDynState);
|
|
477
|
+
this.#pegaAuth = new PegaAuth(this.#ssKeyConfigInfo, this.#ssKeySessionInfo);
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
this.#authConfig.fnDynStateChangedCB = this.#doAuthDynStateChanged.bind(this);
|
|
481
|
+
this.#pegaAuth = new PegaAuth(this.#authConfig, this.#authDynState);
|
|
482
|
+
}
|
|
483
|
+
this.initInProgress = false;
|
|
484
|
+
resolve(this.#pegaAuth);
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
return this.#promiseInitialize;
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Initiate the process to get the Constellation bootstrap shell loaded and initialized
|
|
491
|
+
* @param {Object} tokenInfo
|
|
492
|
+
* @param {Function} authTokenUpdated - callback invoked when Constellation JS Engine silently updates
|
|
493
|
+
* an expired access_token
|
|
494
|
+
* @param {Function} fnReauth - callback invoked when a full or custom reauth is needed
|
|
495
|
+
*/
|
|
496
|
+
#constellationInit(tokenInfo, authTokenUpdated, fnReauth) {
|
|
497
|
+
const constellationBootConfig = {};
|
|
498
|
+
const sdkConfigServer = SdkConfigAccess.getSdkConfigServer();
|
|
499
|
+
const sdkConfigAuth = SdkConfigAccess.getSdkConfigAuth();
|
|
500
|
+
const authConfig = this.#authConfig;
|
|
501
|
+
// Set up constellationConfig with data that bootstrapWithAuthHeader expects
|
|
502
|
+
constellationBootConfig.customRendering = true;
|
|
503
|
+
constellationBootConfig.restServerUrl = sdkConfigServer.infinityRestServerUrl;
|
|
504
|
+
// NOTE: Needs a trailing slash! So add one if not provided
|
|
505
|
+
if (!sdkConfigServer.sdkContentServerUrl.endsWith('/')) {
|
|
506
|
+
sdkConfigServer.sdkContentServerUrl = `${sdkConfigServer.sdkContentServerUrl}/`;
|
|
507
|
+
}
|
|
508
|
+
constellationBootConfig.staticContentServerUrl = `${sdkConfigServer.sdkContentServerUrl}constellation/`;
|
|
509
|
+
if (!constellationBootConfig.staticContentServerUrl.endsWith('/')) {
|
|
510
|
+
constellationBootConfig.staticContentServerUrl = `${constellationBootConfig.staticContentServerUrl}/`;
|
|
511
|
+
}
|
|
512
|
+
// If appAlias specified, use it
|
|
513
|
+
if (sdkConfigServer.appAlias) {
|
|
514
|
+
constellationBootConfig.appAlias = sdkConfigServer.appAlias;
|
|
515
|
+
}
|
|
516
|
+
// Determine whether to send credentials with DX API transactions
|
|
517
|
+
if (sdkConfigAuth.customCookies) {
|
|
518
|
+
constellationBootConfig.customCookies = true;
|
|
519
|
+
}
|
|
520
|
+
if (this.#bOAuthCustom || !tokenInfo) {
|
|
521
|
+
if (tokenInfo) {
|
|
522
|
+
this.#authHeader = `${tokenInfo.token_type} ${tokenInfo.access_token}`;
|
|
523
|
+
}
|
|
524
|
+
if (this.#authHeader) {
|
|
525
|
+
constellationBootConfig.authorizationHeader = this.#authHeader;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
// Pass in auth info to Constellation
|
|
530
|
+
constellationBootConfig.authInfo = {
|
|
531
|
+
authType: 'OAuth2.0',
|
|
532
|
+
tokenInfo,
|
|
533
|
+
// Set whether we want constellation to try to do a full re-Auth or not ()
|
|
534
|
+
// true doesn't seem to be working in SDK scenario so always passing false for now
|
|
535
|
+
popupReauth: false /* !this.noInitialRedirect */,
|
|
536
|
+
client_id: authConfig.clientId,
|
|
537
|
+
client_secret: authConfig.clientSecret,
|
|
538
|
+
authentication_service: authConfig.authService,
|
|
539
|
+
redirect_uri: authConfig.redirectUri,
|
|
540
|
+
endPoints: {
|
|
541
|
+
authorize: authConfig.authorizeUri,
|
|
542
|
+
token: authConfig.tokenUri,
|
|
543
|
+
revoke: authConfig.revokeUri
|
|
544
|
+
},
|
|
545
|
+
secureCookie: authConfig.secureCookie,
|
|
546
|
+
onTokenRetrieval: authTokenUpdated
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
// Turn off dynamic load components (should be able to do it here instead of after load?)
|
|
550
|
+
constellationBootConfig.dynamicLoadComponents = false;
|
|
551
|
+
// Set envType if appropriate
|
|
552
|
+
if (authConfig.serverType === 'launchpad') {
|
|
553
|
+
constellationBootConfig.envType = 'LAUNCHPAD';
|
|
554
|
+
}
|
|
555
|
+
// Set locale override if specified
|
|
556
|
+
const localeOverride = this.locale;
|
|
557
|
+
if (localeOverride) {
|
|
558
|
+
constellationBootConfig.locale = localeOverride;
|
|
559
|
+
}
|
|
560
|
+
// Set additional headers if specified
|
|
561
|
+
const additionalHeaders = this.#loginProps.additionalHeaders;
|
|
562
|
+
if (additionalHeaders) {
|
|
563
|
+
constellationBootConfig.additionalHeaders = additionalHeaders;
|
|
564
|
+
}
|
|
565
|
+
if (this.bC11NBootstrapInProgress) {
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
this.bC11NBootstrapInProgress = true;
|
|
569
|
+
// Note that staticContentServerUrl already ends with a slash (see above), so no slash added.
|
|
570
|
+
// In order to have this import succeed needed to use the webpackIgnore magic comment tag.
|
|
571
|
+
// See: https://webpack.js.org/api/module-methods/
|
|
572
|
+
import(
|
|
573
|
+
/* webpackIgnore: true */ `${constellationBootConfig.staticContentServerUrl}bootstrap-shell.js?v=${Date.now()}`).then(bootstrapShell => {
|
|
574
|
+
// NOTE: once this callback is done, we lose the ability to access loadMashup.
|
|
575
|
+
// So, create a reference to it
|
|
576
|
+
window.myLoadMashup = bootstrapShell.loadMashup;
|
|
577
|
+
window.myLoadPortal = bootstrapShell.loadPortal;
|
|
578
|
+
window.myLoadDefaultPortal = bootstrapShell.loadDefaultPortal;
|
|
579
|
+
bootstrapShell
|
|
580
|
+
.bootstrapWithAuthHeader(constellationBootConfig, 'pega-root')
|
|
581
|
+
.then(() => {
|
|
582
|
+
// eslint-disable-next-line no-console
|
|
583
|
+
console.log('ConstellationJS bootstrap successful!');
|
|
584
|
+
this.bC11NBootstrapInProgress = false;
|
|
585
|
+
this.bC11NBootstrapComplete = true;
|
|
586
|
+
// Setup listener for the reauth event
|
|
587
|
+
if (!this.#bOAuthCustom && tokenInfo) {
|
|
588
|
+
PCore.getPubSubUtils().subscribe(PCore.getConstants().PUB_SUB_EVENTS.EVENT_FULL_REAUTH, fnReauth, 'authFullReauth');
|
|
589
|
+
}
|
|
590
|
+
else {
|
|
591
|
+
// customReauth event introduced with 8.8
|
|
592
|
+
const sEvent = PCore.getConstants().PUB_SUB_EVENTS.EVENT_CUSTOM_REAUTH;
|
|
593
|
+
if (sEvent) {
|
|
594
|
+
PCore.getPubSubUtils().subscribe(sEvent, fnReauth, 'doReauth');
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
// Fire SdkConstellationReady event so bridge and app route can do expected post PCore initializations
|
|
598
|
+
const event = new CustomEvent('SdkConstellationReady', {});
|
|
599
|
+
document.dispatchEvent(event);
|
|
600
|
+
})
|
|
601
|
+
.catch(e => {
|
|
602
|
+
// Assume error caught is because token is not valid and attempt a full reauth
|
|
603
|
+
// eslint-disable-next-line no-console
|
|
604
|
+
console.error(`ConstellationJS bootstrap failed. ${e}`);
|
|
605
|
+
this.bC11NBootstrapInProgress = false;
|
|
606
|
+
fnReauth();
|
|
607
|
+
});
|
|
608
|
+
});
|
|
609
|
+
/* Ends here */
|
|
610
|
+
}
|
|
611
|
+
#customConstellationInit(fnReauth) {
|
|
612
|
+
this.#constellationInit(null, null, fnReauth);
|
|
613
|
+
}
|
|
614
|
+
#fireTokenAvailable(token, bLoadC11N = true) {
|
|
615
|
+
if (!token) {
|
|
616
|
+
// This is used on page reload to load the token from sessionStorage and carry on
|
|
617
|
+
token = this.#tokenInfo;
|
|
618
|
+
if (!token) {
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
this.#tokenInfo = token;
|
|
623
|
+
if (this.#tokenStorage === 'always') {
|
|
624
|
+
this.#setStorage(this.#ssKeyTokenInfo, this.#tokenInfo);
|
|
625
|
+
}
|
|
626
|
+
this.#updateLoginStatus();
|
|
627
|
+
// this.isLoggedIn is getting updated in updateLoginStatus
|
|
628
|
+
this.isLoggedIn = true;
|
|
629
|
+
this.usePopupForRestOfSession = true;
|
|
630
|
+
if (!window.PCore && bLoadC11N) {
|
|
631
|
+
this.#constellationInit(token, this.#authTokenUpdated.bind(this), this.#authRefreshOrFullReauth.bind(this));
|
|
632
|
+
}
|
|
633
|
+
/*
|
|
634
|
+
// Create and dispatch the SdkLoggedIn event to trigger constellationInit
|
|
635
|
+
const event = new CustomEvent('SdkLoggedIn', { detail: { authConfig, tokenInfo: token } });
|
|
636
|
+
document.dispatchEvent(event);
|
|
637
|
+
*/
|
|
638
|
+
}
|
|
639
|
+
#processTokenOnLogin(token, bLoadC11N = true) {
|
|
640
|
+
this.#tokenInfo = token;
|
|
641
|
+
if (this.#tokenStorage === 'always') {
|
|
642
|
+
this.#setStorage(this.#ssKeyTokenInfo, this.#tokenInfo);
|
|
643
|
+
}
|
|
644
|
+
if (this.#bOAuthCustom) {
|
|
645
|
+
// authHeader setter will also set #authHeader and invoke getAuthUtils().setAuthorizationHeader
|
|
646
|
+
this.authHeader = `${token.token_type} ${token.access_token}`;
|
|
647
|
+
}
|
|
648
|
+
if (window.PCore && !this.#authHeader) {
|
|
649
|
+
PCore.getAuthUtils().setTokens(token);
|
|
650
|
+
}
|
|
651
|
+
else {
|
|
652
|
+
this.#fireTokenAvailable(token, bLoadC11N);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
#doCustomTokenParamsCB() {
|
|
656
|
+
if (this.#authConfig.grantType === 'customBearer' && this.#customTokenParamsCB) {
|
|
657
|
+
try {
|
|
658
|
+
const customTokenParams = this.#customTokenParamsCB();
|
|
659
|
+
if (customTokenParams) {
|
|
660
|
+
this.#authConfig.customTokenParams = customTokenParams;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
catch (e) {
|
|
664
|
+
// eslint-disable-next-line no-console
|
|
665
|
+
console.error(`Error on customTokenParams callback. ${e}`);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
216
669
|
updateRedirectUri(sRedirectUri) {
|
|
217
|
-
|
|
670
|
+
this.#authConfig.redirectUri = sRedirectUri;
|
|
218
671
|
}
|
|
219
672
|
/**
|
|
220
673
|
* Get available portals which supports SDK
|
|
@@ -230,9 +683,9 @@ class AuthManager {
|
|
|
230
683
|
const appAlias = serverConfig.appAlias;
|
|
231
684
|
const appAliasPath = appAlias ? `/app/${appAlias}` : '';
|
|
232
685
|
const arExcludedPortals = serverConfig.excludePortals;
|
|
233
|
-
const additionalHeaders =
|
|
234
|
-
const oHeaders =
|
|
235
|
-
? { Authorization:
|
|
686
|
+
const additionalHeaders = this.#loginProps.additionalHeaders || {};
|
|
687
|
+
const oHeaders = this.#authHeader
|
|
688
|
+
? { Authorization: this.#authHeader, ...additionalHeaders }
|
|
236
689
|
: additionalHeaders;
|
|
237
690
|
const headers = {
|
|
238
691
|
'Content-Type': 'application/json',
|
|
@@ -243,7 +696,7 @@ class AuthManager {
|
|
|
243
696
|
return fetch(`${serverUrl}${appAliasPath}/api/v1/data/${dataPageName}`, {
|
|
244
697
|
method: 'GET',
|
|
245
698
|
headers,
|
|
246
|
-
credentials:
|
|
699
|
+
credentials: this.#authConfig.secureCookie ? 'include' : 'omit'
|
|
247
700
|
})
|
|
248
701
|
.then(response => {
|
|
249
702
|
if (response.ok && response.status === 200) {
|
|
@@ -284,27 +737,97 @@ class AuthManager {
|
|
|
284
737
|
});
|
|
285
738
|
});
|
|
286
739
|
}
|
|
740
|
+
#updateLoginStatus() {
|
|
741
|
+
if (!this.#authHeader && this.#tokenInfo?.access_token) {
|
|
742
|
+
// Use setter to set this securely
|
|
743
|
+
this.authHeader = `${this.#tokenInfo.token_type} ${this.#tokenInfo.access_token}`;
|
|
744
|
+
}
|
|
745
|
+
this.isLoggedIn =
|
|
746
|
+
!!(this.#authHeader && this.#authHeader.length > 0) ||
|
|
747
|
+
(this.#authConfig.secureCookie && Object.keys(this.#tokenInfo || {}).length > 0);
|
|
748
|
+
}
|
|
749
|
+
// Initiate a full OAuth re-authorization (any refresh token has also expired).
|
|
750
|
+
#authFullReauth() {
|
|
751
|
+
const bHandleHere = true; // Other alternative is to raise an event and have someone else handle it
|
|
752
|
+
if (this.reauthStart) {
|
|
753
|
+
const reauthIgnoreInterval = 300000; // 5 minutes
|
|
754
|
+
const currTime = Date.now();
|
|
755
|
+
const bReauthInProgress = currTime - this.reauthStart <= reauthIgnoreInterval;
|
|
756
|
+
if (bReauthInProgress) {
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
if (bHandleHere) {
|
|
761
|
+
// Don't want to do a full clear of authMgr as will loose state props (like sessionIndex). Rather just clear the tokens
|
|
762
|
+
this.clear(true);
|
|
763
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
764
|
+
login(true);
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
// Fire the SdkFullReauth event to indicate a new token is needed (PCore.getAuthUtils.setTokens method
|
|
768
|
+
// should be used to communicate the new token to Constellation JS Engine.
|
|
769
|
+
const event = new CustomEvent('SdkFullReauth', {
|
|
770
|
+
detail: this.#processTokenOnLogin.bind(this)
|
|
771
|
+
});
|
|
772
|
+
document.dispatchEvent(event);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
#authRefresh(tokenInfo) {
|
|
776
|
+
const bBootstrapComplete = this.bC11NBootstrapComplete;
|
|
777
|
+
this.#initialize(false).then(aMgr => {
|
|
778
|
+
aMgr.refreshToken(tokenInfo.refresh_token).then(token => {
|
|
779
|
+
if (token?.token_type) {
|
|
780
|
+
this.#processTokenOnLogin(token, !bBootstrapComplete);
|
|
781
|
+
}
|
|
782
|
+
else {
|
|
783
|
+
this.#authFullReauth();
|
|
784
|
+
}
|
|
785
|
+
});
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
#isRefreshTokenAvailable() {
|
|
789
|
+
return ((!this.#authConfig.secureCookie && this.#tokenInfo?.refresh_token) ||
|
|
790
|
+
(this.#authConfig.secureCookie && this.#tokenInfo.is_refresh_token_enabled));
|
|
791
|
+
}
|
|
792
|
+
// Do a full reauth or token refresh
|
|
793
|
+
#authRefreshOrFullReauth() {
|
|
794
|
+
if (this.#authHeader && this.#authConfig.grantType === 'none') {
|
|
795
|
+
// Should never come down this path
|
|
796
|
+
}
|
|
797
|
+
else if (this.#isRefreshTokenAvailable() &&
|
|
798
|
+
(this.#authConfig.secureCookie || this.#bOAuthCustom || !this.bC11NBootstrapComplete)) {
|
|
799
|
+
// If not doing custom and have a refresh token, then attempt a refresh
|
|
800
|
+
this.#authRefresh(this.#tokenInfo);
|
|
801
|
+
}
|
|
802
|
+
else {
|
|
803
|
+
this.#authFullReauth();
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
// Passive update where just session storage is updated so can be used on a window refresh
|
|
807
|
+
#authTokenUpdated(tokenInfo) {
|
|
808
|
+
this.#tokenInfo = tokenInfo;
|
|
809
|
+
}
|
|
287
810
|
// TODO: Cope with 401 and refresh token if possible (or just hope that it succeeds during login)
|
|
288
811
|
/**
|
|
289
812
|
* Retrieve UserInfo for current authentication service
|
|
290
813
|
*/
|
|
291
814
|
getUserInfo() {
|
|
292
|
-
if (
|
|
293
|
-
return
|
|
815
|
+
if (this.#userInfo) {
|
|
816
|
+
return this.#userInfo;
|
|
294
817
|
}
|
|
295
|
-
return
|
|
296
|
-
return aMgr.getUserinfo(
|
|
297
|
-
|
|
298
|
-
return
|
|
818
|
+
return this.#initialize(false).then(aMgr => {
|
|
819
|
+
return aMgr.getUserinfo(this.#tokenInfo.access_token).then(data => {
|
|
820
|
+
this.#userInfo = data;
|
|
821
|
+
return this.#userInfo;
|
|
299
822
|
});
|
|
300
823
|
});
|
|
301
824
|
}
|
|
302
825
|
login(bFullReauth = false) {
|
|
303
826
|
if (this.bCustomAuth)
|
|
304
827
|
return;
|
|
305
|
-
|
|
828
|
+
this.#initialize(!bFullReauth).then(aMgr => {
|
|
306
829
|
const sdkConfigAuth = SdkConfigAccess.getSdkConfigAuth();
|
|
307
|
-
if (
|
|
830
|
+
if (this.#authConfig.grantType === 'authCode') {
|
|
308
831
|
const bMainRedirect = !this.noInitialRedirect;
|
|
309
832
|
let sRedirectUri = sdkConfigAuth.redirectUri;
|
|
310
833
|
// If initial main redirect is OK, redirect to main page, otherwise will authorize in a popup window
|
|
@@ -325,12 +848,12 @@ class AuthManager {
|
|
|
325
848
|
this.updateRedirectUri(sRedirectUri);
|
|
326
849
|
}
|
|
327
850
|
return new Promise((resolve, reject) => {
|
|
328
|
-
|
|
851
|
+
this.#doCustomTokenParamsCB();
|
|
329
852
|
aMgr
|
|
330
853
|
.login()
|
|
331
854
|
.then(token => {
|
|
332
|
-
|
|
333
|
-
if (
|
|
855
|
+
this.#processTokenOnLogin(token);
|
|
856
|
+
if (this.#loadUserinfo) {
|
|
334
857
|
this.getUserInfo();
|
|
335
858
|
}
|
|
336
859
|
resolve(token.access_token);
|
|
@@ -351,17 +874,17 @@ class AuthManager {
|
|
|
351
874
|
const state = urlParams.get('state');
|
|
352
875
|
// If state should also match before accepting code
|
|
353
876
|
if (code) {
|
|
354
|
-
|
|
877
|
+
this.#initialize(false).then(aMgr => {
|
|
355
878
|
if (aMgr.checkStateMatch(state)) {
|
|
356
879
|
aMgr.getToken(code).then(token => {
|
|
357
880
|
// Remove any altStateStorage
|
|
358
|
-
if (
|
|
359
|
-
window.localStorage.removeItem(
|
|
360
|
-
window.localStorage.removeItem(
|
|
881
|
+
if (this.#loginProps?.altStateStorage) {
|
|
882
|
+
window.localStorage.removeItem(this.#ssKeySessionInfo);
|
|
883
|
+
window.localStorage.removeItem(this.#ssKeyState);
|
|
361
884
|
}
|
|
362
885
|
if (token && token.token_type) {
|
|
363
|
-
|
|
364
|
-
if (
|
|
886
|
+
this.#processTokenOnLogin(token, false);
|
|
887
|
+
if (this.#loadUserinfo) {
|
|
365
888
|
this.getUserInfo();
|
|
366
889
|
}
|
|
367
890
|
if (fnLoggedInCB) {
|
|
@@ -387,14 +910,14 @@ class AuthManager {
|
|
|
387
910
|
}
|
|
388
911
|
loginIfNecessary(loginProps) {
|
|
389
912
|
const { appName, deferLogin, redirectDoneCB, locale } = loginProps;
|
|
390
|
-
|
|
913
|
+
this.#loginProps = { ...loginProps };
|
|
391
914
|
const noMainRedirect = !loginProps.mainRedirect;
|
|
392
915
|
// We need to load state before making any decisions. If appName is not there
|
|
393
916
|
// and this is not the first time load...suspect something is wrong and we need to reload
|
|
394
917
|
if (Object.keys(this.state).length <= this.stateKeysCount || !this.appName) {
|
|
395
918
|
// Once appName is defined it should exceed this count. If not there should be no
|
|
396
919
|
// harm trying once more
|
|
397
|
-
|
|
920
|
+
this.#loadState();
|
|
398
921
|
}
|
|
399
922
|
// If no initial redirect status of page changed...clear AuthMgr
|
|
400
923
|
const currNoMainRedirect = this.noInitialRedirect;
|
|
@@ -413,9 +936,9 @@ class AuthManager {
|
|
|
413
936
|
}
|
|
414
937
|
// If custom auth no need to do any OAuth logic
|
|
415
938
|
if (this.bCustomAuth) {
|
|
416
|
-
|
|
939
|
+
this.#updateLoginStatus();
|
|
417
940
|
if (!window.PCore) {
|
|
418
|
-
|
|
941
|
+
this.#customConstellationInit(() => {
|
|
419
942
|
// Fire the SdkCustomReauth event to indicate a new authHeader is needed. Event listener should invoke sdkSetAuthHeader
|
|
420
943
|
// to communicate the new token to sdk (and Constellation JS Engine)
|
|
421
944
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
@@ -444,7 +967,7 @@ class AuthManager {
|
|
|
444
967
|
window.location.replace(window.location.pathname);
|
|
445
968
|
};
|
|
446
969
|
// INC-B43979 had strange case where sessionStorage was empty after redirects
|
|
447
|
-
if (!this.state.sfx && !
|
|
970
|
+
if (!this.state.sfx && !this.#loginProps?.altStateStorage) {
|
|
448
971
|
// Reload the page to trigger another login. Invoking login method here instead didn't
|
|
449
972
|
// resolve the issue in client environment.
|
|
450
973
|
this.clear();
|
|
@@ -453,11 +976,11 @@ class AuthManager {
|
|
|
453
976
|
return this.authRedirectCallback(window.location.href, redirectDoneCB || cbDefault);
|
|
454
977
|
}
|
|
455
978
|
if (!deferLogin) {
|
|
456
|
-
return
|
|
457
|
-
|
|
979
|
+
return this.#initialize(false).then(() => {
|
|
980
|
+
this.#updateLoginStatus();
|
|
458
981
|
if (this.isLoggedIn) {
|
|
459
|
-
|
|
460
|
-
if (
|
|
982
|
+
this.#fireTokenAvailable(this.#tokenInfo);
|
|
983
|
+
if (this.#loadUserinfo) {
|
|
461
984
|
this.getUserInfo();
|
|
462
985
|
}
|
|
463
986
|
}
|
|
@@ -468,10 +991,10 @@ class AuthManager {
|
|
|
468
991
|
}
|
|
469
992
|
}
|
|
470
993
|
logout() {
|
|
471
|
-
if (
|
|
472
|
-
window.removeEventListener('beforeunload',
|
|
473
|
-
window.removeEventListener('pagehide',
|
|
474
|
-
|
|
994
|
+
if (this.#beforeUnloadAdded) {
|
|
995
|
+
window.removeEventListener('beforeunload', this.#doBeforeUnload.bind(this));
|
|
996
|
+
window.removeEventListener('pagehide', this.#doPageHide.bind(this));
|
|
997
|
+
this.#beforeUnloadAdded = false;
|
|
475
998
|
}
|
|
476
999
|
return new Promise(resolve => {
|
|
477
1000
|
const fnClearAndResolve = () => {
|
|
@@ -485,8 +1008,8 @@ class AuthManager {
|
|
|
485
1008
|
return;
|
|
486
1009
|
}
|
|
487
1010
|
// For secure cookie there will not be an access_token so just check for token_type
|
|
488
|
-
if (
|
|
489
|
-
if (window.PCore && !
|
|
1011
|
+
if (this.#tokenInfo && this.#tokenInfo.token_type) {
|
|
1012
|
+
if (window.PCore && !this.#bOAuthCustom) {
|
|
490
1013
|
window.PCore.getAuthUtils()
|
|
491
1014
|
.revokeTokens()
|
|
492
1015
|
.catch(err => {
|
|
@@ -498,11 +1021,11 @@ class AuthManager {
|
|
|
498
1021
|
});
|
|
499
1022
|
}
|
|
500
1023
|
else {
|
|
501
|
-
|
|
1024
|
+
this.#initialize(false).then(aMgr => {
|
|
502
1025
|
aMgr
|
|
503
|
-
.revokeTokens(
|
|
1026
|
+
.revokeTokens(this.#authConfig.secureCookie ? 'cookie' : this.#tokenInfo.access_token, this.#authConfig.secureCookie && this.#tokenInfo.is_refresh_token_enabled
|
|
504
1027
|
? 'cookie'
|
|
505
|
-
:
|
|
1028
|
+
: this.#tokenInfo.refresh_token)
|
|
506
1029
|
.then(() => {
|
|
507
1030
|
// Go to finally
|
|
508
1031
|
})
|
|
@@ -518,515 +1041,6 @@ class AuthManager {
|
|
|
518
1041
|
});
|
|
519
1042
|
}
|
|
520
1043
|
}
|
|
521
|
-
_AuthManager_ssKeyPrefix = new WeakMap(), _AuthManager_pegaAuth = new WeakMap(), _AuthManager_ssKeyConfigInfo = new WeakMap(), _AuthManager_ssKeySessionInfo = new WeakMap(), _AuthManager_ssKeyTokenInfo = new WeakMap(), _AuthManager_ssKeyState = new WeakMap(), _AuthManager_authConfig = new WeakMap(), _AuthManager_authDynState = new WeakMap(), _AuthManager_authHeader = new WeakMap(), _AuthManager_customTokenParamsCB = new WeakMap(), _AuthManager_bOAuthCustom = new WeakMap(), _AuthManager_tokenInfo = new WeakMap(), _AuthManager_userInfo = new WeakMap(), _AuthManager_usePASS = new WeakMap(), _AuthManager_beforeUnloadAdded = new WeakMap(), _AuthManager_tokenStorage = new WeakMap(), _AuthManager_transform = new WeakMap(), _AuthManager_foldSpot = new WeakMap(), _AuthManager_loadUserinfo = new WeakMap(), _AuthManager_loginProps = new WeakMap(), _AuthManager_promiseInitialize = new WeakMap(), _AuthManager_instances = new WeakSet(), _AuthManager_transformAndParse = function _AuthManager_transformAndParse(ssKey, ssItem, bForce = false) {
|
|
522
|
-
let obj = {};
|
|
523
|
-
try {
|
|
524
|
-
obj = JSON.parse(__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_transformer).call(this, ssKey, ssItem, false, bForce));
|
|
525
|
-
}
|
|
526
|
-
catch (e) {
|
|
527
|
-
// fall thru and return empty object
|
|
528
|
-
}
|
|
529
|
-
return obj;
|
|
530
|
-
}, _AuthManager_getStorage = function _AuthManager_getStorage(ssKey, sAttrib = null) {
|
|
531
|
-
let ssItem = ssKey ? window.sessionStorage.getItem(ssKey) : null;
|
|
532
|
-
let obj = {};
|
|
533
|
-
if (__classPrivateFieldGet(this, _AuthManager_loginProps, "f")?.altStateStorage &&
|
|
534
|
-
!this.isLoggedIn &&
|
|
535
|
-
!ssItem &&
|
|
536
|
-
(ssKey === __classPrivateFieldGet(this, _AuthManager_ssKeyState, "f") || ssKey === __classPrivateFieldGet(this, _AuthManager_ssKeySessionInfo, "f"))) {
|
|
537
|
-
ssItem = window.localStorage.getItem(ssKey);
|
|
538
|
-
}
|
|
539
|
-
if (ssItem) {
|
|
540
|
-
try {
|
|
541
|
-
obj = JSON.parse(ssItem);
|
|
542
|
-
}
|
|
543
|
-
catch (e) {
|
|
544
|
-
obj = __classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_transformAndParse).call(this, ssKey, ssItem, true);
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
return sAttrib ? obj[sAttrib] : obj;
|
|
548
|
-
}, _AuthManager_setStorage = function _AuthManager_setStorage(ssKey, obj, bVerify = false) {
|
|
549
|
-
try {
|
|
550
|
-
// Set storage only if obj is not empty, else delete the storage
|
|
551
|
-
if (!obj || isEmptyObject(obj)) {
|
|
552
|
-
window.sessionStorage.removeItem(ssKey);
|
|
553
|
-
}
|
|
554
|
-
else {
|
|
555
|
-
// const bClear = (ssKey === this.#ssKeyState || ssKey === this.#ssKeySessionInfo);
|
|
556
|
-
const bClear = false;
|
|
557
|
-
const sValue = bClear
|
|
558
|
-
? JSON.stringify(obj)
|
|
559
|
-
: __classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_transformer).call(this, ssKey, JSON.stringify(obj), true);
|
|
560
|
-
window.sessionStorage.setItem(ssKey, sValue);
|
|
561
|
-
if (bVerify) {
|
|
562
|
-
const sStored = window.sessionStorage.getItem(ssKey);
|
|
563
|
-
if (sStored !== sValue) {
|
|
564
|
-
// eslint-disable-next-line no-console
|
|
565
|
-
console.error(`Failed to properly write sessionStorage (${ssKey})`);
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
if (__classPrivateFieldGet(this, _AuthManager_loginProps, "f")?.altStateStorage &&
|
|
569
|
-
!this.isLoggedIn &&
|
|
570
|
-
(ssKey === __classPrivateFieldGet(this, _AuthManager_ssKeyState, "f") || ssKey === __classPrivateFieldGet(this, _AuthManager_ssKeySessionInfo, "f"))) {
|
|
571
|
-
window.localStorage.setItem(ssKey, sValue);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
catch (e) {
|
|
576
|
-
// eslint-disable-next-line no-console
|
|
577
|
-
console.error(`Exception ${e} on attempted write of sessionStorage (${ssKey})`);
|
|
578
|
-
}
|
|
579
|
-
}, _AuthManager_calcFoldSpot = function _AuthManager_calcFoldSpot(s) {
|
|
580
|
-
const nOffset = 1;
|
|
581
|
-
const sChar = s.length > nOffset ? s.charAt(nOffset) : '2';
|
|
582
|
-
const nSpot = parseInt(sChar, 10);
|
|
583
|
-
__classPrivateFieldSet(this, _AuthManager_foldSpot, Number.isNaN(nSpot) ? 2 : (nSpot % 4) + 2, "f");
|
|
584
|
-
}, _AuthManager_transformer = function _AuthManager_transformer(ssKey, s, bIn, bForce = false) {
|
|
585
|
-
const bTransform = bForce || __classPrivateFieldGet(this, _AuthManager_transform, "f");
|
|
586
|
-
const fnFold = (x) => {
|
|
587
|
-
const nLen = x.length;
|
|
588
|
-
const nExtra = nLen % __classPrivateFieldGet(this, _AuthManager_foldSpot, "f");
|
|
589
|
-
const nOffset = Math.floor(nLen / __classPrivateFieldGet(this, _AuthManager_foldSpot, "f")) + nExtra;
|
|
590
|
-
const nRem = x.length - nOffset;
|
|
591
|
-
return x.substring(bIn ? nOffset : nRem) + x.substring(0, bIn ? nOffset : nRem);
|
|
592
|
-
};
|
|
593
|
-
const bTknInfo = ssKey === __classPrivateFieldGet(this, _AuthManager_ssKeyTokenInfo, "f");
|
|
594
|
-
if (bTknInfo && !bIn && bTransform) {
|
|
595
|
-
s = window.atob(fnFold(s));
|
|
596
|
-
}
|
|
597
|
-
// eslint-disable-next-line no-nested-ternary
|
|
598
|
-
let result = bTransform ? (bIn ? window.btoa(s) : window.atob(s)) : s;
|
|
599
|
-
if (bTknInfo && bIn && bTransform) {
|
|
600
|
-
result = fnFold(window.btoa(result));
|
|
601
|
-
}
|
|
602
|
-
return result;
|
|
603
|
-
}, _AuthManager_doUnloadUpdates = function _AuthManager_doUnloadUpdates() {
|
|
604
|
-
// Safari and particularly Safari on mobile devices doesn't seem to load this on first main redirect or
|
|
605
|
-
// reliably, so have moved to having PegaAuth manage writing all state props to session storage
|
|
606
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_setStorage).call(this, __classPrivateFieldGet(this, _AuthManager_ssKeyState, "f"), this.state);
|
|
607
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_setStorage).call(this, __classPrivateFieldGet(this, _AuthManager_ssKeySessionInfo, "f"), __classPrivateFieldGet(this, _AuthManager_authDynState, "f"));
|
|
608
|
-
// If tokenStorage was always, token would already be there
|
|
609
|
-
if (__classPrivateFieldGet(this, _AuthManager_tokenStorage, "f") === 'temp') {
|
|
610
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_setStorage).call(this, __classPrivateFieldGet(this, _AuthManager_ssKeyTokenInfo, "f"), __classPrivateFieldGet(this, _AuthManager_tokenInfo, "f"));
|
|
611
|
-
}
|
|
612
|
-
}, _AuthManager_doBeforeUnload = function _AuthManager_doBeforeUnload() {
|
|
613
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_doUnloadUpdates).call(this);
|
|
614
|
-
}, _AuthManager_doPageHide = function _AuthManager_doPageHide() {
|
|
615
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_doUnloadUpdates).call(this);
|
|
616
|
-
}, _AuthManager_loadState = function _AuthManager_loadState() {
|
|
617
|
-
// Note: State storage key doesn't have a client id associated with it
|
|
618
|
-
const oState = __classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_getStorage).call(this, __classPrivateFieldGet(this, _AuthManager_ssKeyState, "f"));
|
|
619
|
-
if (oState) {
|
|
620
|
-
Object.assign(this.state, oState);
|
|
621
|
-
if (this.state.sfx) {
|
|
622
|
-
// Setter sets up the ssKey values as well
|
|
623
|
-
this.keySuffix = this.state.sfx;
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
}, _AuthManager_doOnLoad = function _AuthManager_doOnLoad() {
|
|
627
|
-
if (!this.onLoadDone) {
|
|
628
|
-
// This authConfig state doesn't collide with other calculated static state...so load it first
|
|
629
|
-
// Note: transform setting will have already been loaded into #authConfig at this point
|
|
630
|
-
__classPrivateFieldSet(this, _AuthManager_authDynState, __classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_getStorage).call(this, __classPrivateFieldGet(this, _AuthManager_ssKeySessionInfo, "f")), "f");
|
|
631
|
-
__classPrivateFieldSet(this, _AuthManager_tokenInfo, __classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_getStorage).call(this, __classPrivateFieldGet(this, _AuthManager_ssKeyTokenInfo, "f")), "f");
|
|
632
|
-
if (__classPrivateFieldGet(this, _AuthManager_tokenStorage, "f") !== 'always') {
|
|
633
|
-
sessionStorage.removeItem(__classPrivateFieldGet(this, _AuthManager_ssKeyTokenInfo, "f"));
|
|
634
|
-
// Finding on iOS browsers the pageHide event is sometimes not happening causing failed redirects.
|
|
635
|
-
if (!this.iOSDevice) {
|
|
636
|
-
sessionStorage.removeItem(__classPrivateFieldGet(this, _AuthManager_ssKeySessionInfo, "f"));
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
this.onLoadDone = true;
|
|
640
|
-
}
|
|
641
|
-
}, _AuthManager_doAuthDynStateChanged = function _AuthManager_doAuthDynStateChanged() {
|
|
642
|
-
// If tokenStorage is setup for always then always persist the auth dynamic state as well
|
|
643
|
-
if (__classPrivateFieldGet(this, _AuthManager_tokenStorage, "f") === 'always' || this.iOSDevice) {
|
|
644
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_setStorage).call(this, __classPrivateFieldGet(this, _AuthManager_ssKeySessionInfo, "f"), __classPrivateFieldGet(this, _AuthManager_authDynState, "f"));
|
|
645
|
-
}
|
|
646
|
-
}, _AuthManager_initialize =
|
|
647
|
-
/**
|
|
648
|
-
* Initialize OAuth config structure members and create authMgr instance (if necessary)
|
|
649
|
-
* bNew - governs whether to create new sessionStorage or load existing one
|
|
650
|
-
*/
|
|
651
|
-
async function _AuthManager_initialize(bNew = false) {
|
|
652
|
-
if (!bNew && __classPrivateFieldGet(this, _AuthManager_promiseInitialize, "f")) {
|
|
653
|
-
return __classPrivateFieldGet(this, _AuthManager_promiseInitialize, "f");
|
|
654
|
-
}
|
|
655
|
-
__classPrivateFieldSet(this, _AuthManager_promiseInitialize, new Promise(resolve => {
|
|
656
|
-
/* if (!this.initInProgress && (bNew || isEmptyObject(this.#authConfig) || !this.#pegaAuth)) { */
|
|
657
|
-
this.initInProgress = true;
|
|
658
|
-
getSdkConfig().then(sdkConfig => {
|
|
659
|
-
const sdkConfigAuth = sdkConfig.authConfig;
|
|
660
|
-
const sdkConfigServer = sdkConfig.serverConfig;
|
|
661
|
-
const serverType = sdkConfigServer.serverType || 'infinity';
|
|
662
|
-
const bInfinity = serverType === 'infinity';
|
|
663
|
-
let pegaUrl = bInfinity
|
|
664
|
-
? sdkConfigServer.infinityRestServerUrl
|
|
665
|
-
: sdkConfigServer.launchpadRestServerUrl;
|
|
666
|
-
// Expecting boolean true/false or undefined
|
|
667
|
-
const secureCookie = !!sdkConfigAuth.secureCookie;
|
|
668
|
-
const bNoInitialRedirect = this.noInitialRedirect;
|
|
669
|
-
const appAliasSeg = sdkConfigServer.appAlias ? `app/${sdkConfigServer.appAlias}/` : '';
|
|
670
|
-
// Construct default OAuth endpoints (if not explicitly specified)
|
|
671
|
-
if (pegaUrl) {
|
|
672
|
-
// Cope with trailing slash being present
|
|
673
|
-
if (!pegaUrl.endsWith('/')) {
|
|
674
|
-
pegaUrl += '/';
|
|
675
|
-
}
|
|
676
|
-
if (!sdkConfigAuth.authorize) {
|
|
677
|
-
sdkConfigAuth.authorize = bInfinity
|
|
678
|
-
? `${pegaUrl}PRRestService/oauth2/v1/authorize`
|
|
679
|
-
: `${pegaUrl}uas/oauth/authorize`;
|
|
680
|
-
}
|
|
681
|
-
const infinityOAuth2Url = bInfinity
|
|
682
|
-
? pegaUrl + (secureCookie && appAliasSeg ? `${appAliasSeg}api/` : 'PRRestService/')
|
|
683
|
-
: '';
|
|
684
|
-
if (!sdkConfigAuth.token) {
|
|
685
|
-
sdkConfigAuth.token = bInfinity
|
|
686
|
-
? `${infinityOAuth2Url}oauth2/v1/token`
|
|
687
|
-
: `${pegaUrl}uas/oauth/token`;
|
|
688
|
-
}
|
|
689
|
-
if (!sdkConfigAuth.revoke) {
|
|
690
|
-
// Launchpad still does not have a revoke endpoint
|
|
691
|
-
sdkConfigAuth.revoke = bInfinity ? `${infinityOAuth2Url}oauth2/v1/revoke` : '';
|
|
692
|
-
}
|
|
693
|
-
if (!sdkConfigAuth.redirectUri) {
|
|
694
|
-
sdkConfigAuth.redirectUri = `${window.location.origin}${window.location.pathname}`;
|
|
695
|
-
}
|
|
696
|
-
if (!sdkConfigAuth.userinfo) {
|
|
697
|
-
sdkConfigAuth.userinfo = bInfinity
|
|
698
|
-
? `${pegaUrl}${appAliasSeg}api/oauthclients/v1/userinfo/JSON`
|
|
699
|
-
: '';
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
// Auth service alias
|
|
703
|
-
if (!sdkConfigAuth.authService) {
|
|
704
|
-
sdkConfigAuth.authService = 'pega';
|
|
705
|
-
}
|
|
706
|
-
// mashupAuthService provides way to have a different auth service for embedded
|
|
707
|
-
if (!sdkConfigAuth.mashupAuthService) {
|
|
708
|
-
sdkConfigAuth.mashupAuthService = sdkConfigAuth.authService;
|
|
709
|
-
}
|
|
710
|
-
// Construct path to auth.html (used for case when not doing a main window redirect)
|
|
711
|
-
let sNoMainRedirectUri = sdkConfigAuth.redirectUri;
|
|
712
|
-
const nLastPathSep = sNoMainRedirectUri.lastIndexOf('/');
|
|
713
|
-
sNoMainRedirectUri =
|
|
714
|
-
nLastPathSep !== -1
|
|
715
|
-
? `${sNoMainRedirectUri.substring(0, nLastPathSep + 1)}auth.html`
|
|
716
|
-
: `${sNoMainRedirectUri}/auth.html`;
|
|
717
|
-
const portalGrantType = sdkConfigAuth.portalGrantType || 'authCode';
|
|
718
|
-
const mashupGrantType = sdkConfigAuth.mashupGrantType || 'authCode';
|
|
719
|
-
// Some grant types are only available with confidential registrations and require a client secret
|
|
720
|
-
const clientSecret = bNoInitialRedirect
|
|
721
|
-
? sdkConfigAuth.mashupClientSecret
|
|
722
|
-
: sdkConfigAuth.portalClientSecret;
|
|
723
|
-
const pegaAuthConfig = {
|
|
724
|
-
serverType,
|
|
725
|
-
clientId: bNoInitialRedirect
|
|
726
|
-
? sdkConfigAuth.mashupClientId
|
|
727
|
-
: sdkConfigAuth.portalClientId,
|
|
728
|
-
grantType: bNoInitialRedirect ? mashupGrantType : portalGrantType,
|
|
729
|
-
tokenUri: sdkConfigAuth.token,
|
|
730
|
-
revokeUri: sdkConfigAuth.revoke,
|
|
731
|
-
userinfoUri: sdkConfigAuth.userinfo,
|
|
732
|
-
authService: bNoInitialRedirect
|
|
733
|
-
? sdkConfigAuth.mashupAuthService
|
|
734
|
-
: sdkConfigAuth.authService,
|
|
735
|
-
appAlias: sdkConfigServer.appAlias || '',
|
|
736
|
-
useLocking: true
|
|
737
|
-
};
|
|
738
|
-
if (clientSecret) {
|
|
739
|
-
pegaAuthConfig.clientSecret = clientSecret;
|
|
740
|
-
}
|
|
741
|
-
if (serverType === 'launchpad' && pegaAuthConfig.grantType === 'authCode') {
|
|
742
|
-
pegaAuthConfig.noPKCE = true;
|
|
743
|
-
}
|
|
744
|
-
// Invoke keySuffix setter
|
|
745
|
-
// Was using pegaAuthConfig.clientId as key but more secure to just use a random string as getting
|
|
746
|
-
// both a clientId and the refresh token could yield a new access token.
|
|
747
|
-
// Suffix is so we might in future move to an array of suffixes based on the appName, so might store
|
|
748
|
-
// both portal and embedded tokens/session info at same time
|
|
749
|
-
if (!this.state?.sfx) {
|
|
750
|
-
// Just using a random number to make the suffix unique on each session
|
|
751
|
-
this.keySuffix = `${Math.ceil(Math.random() * 100000000)}`;
|
|
752
|
-
}
|
|
753
|
-
__classPrivateFieldGet(this, _AuthManager_authConfig, "f").transform =
|
|
754
|
-
sdkConfigAuth.transform !== undefined ? sdkConfigAuth.transform : __classPrivateFieldGet(this, _AuthManager_transform, "f");
|
|
755
|
-
// Using property in class as authConfig may be empty at times
|
|
756
|
-
__classPrivateFieldSet(this, _AuthManager_transform, __classPrivateFieldGet(this, _AuthManager_authConfig, "f").transform, "f");
|
|
757
|
-
if (sdkConfigAuth.tokenStorage !== undefined) {
|
|
758
|
-
__classPrivateFieldSet(this, _AuthManager_tokenStorage, sdkConfigAuth.tokenStorage, "f");
|
|
759
|
-
}
|
|
760
|
-
if (sdkConfigAuth.secureCookie) {
|
|
761
|
-
__classPrivateFieldGet(this, _AuthManager_authConfig, "f").secureCookie = true;
|
|
762
|
-
}
|
|
763
|
-
// Get latest state once client ids, transform and tokenStorage have been established
|
|
764
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_doOnLoad).call(this);
|
|
765
|
-
// If no clientId is specified assume not OAuth but custom auth
|
|
766
|
-
if (pegaAuthConfig.grantType === 'none' || !pegaAuthConfig.clientId) {
|
|
767
|
-
this.bCustomAuth = true;
|
|
768
|
-
return;
|
|
769
|
-
}
|
|
770
|
-
// For some OAuth grant type scenarios we opt to pass the Orchestration Engine just an authHeader as
|
|
771
|
-
// service broker doesn't have proper support for dealing with refreshing or revoking these:
|
|
772
|
-
// * customBearer (except when secureCookie being used)
|
|
773
|
-
// * confidential grant types (ones with clientSecret)
|
|
774
|
-
// (With 25.1 orchestration engine does support this if client_secret is specified on bootstrap)
|
|
775
|
-
__classPrivateFieldSet(this, _AuthManager_bOAuthCustom, (pegaAuthConfig.grantType === 'customBearer' && !secureCookie) || clientSecret, "f");
|
|
776
|
-
if (pegaAuthConfig.grantType === 'authCode') {
|
|
777
|
-
const authCodeProps = {
|
|
778
|
-
authorizeUri: sdkConfigAuth.authorize,
|
|
779
|
-
// If we have already specified a redirect on the authorize redirect, we need to continue to use that
|
|
780
|
-
// on token endpoint
|
|
781
|
-
redirectUri: bNoInitialRedirect || this.usePopupForRestOfSession
|
|
782
|
-
? sNoMainRedirectUri
|
|
783
|
-
: sdkConfigAuth.redirectUri
|
|
784
|
-
};
|
|
785
|
-
if ('silentTimeout' in sdkConfigAuth) {
|
|
786
|
-
authCodeProps.silentTimeout = sdkConfigAuth.silentTimeout;
|
|
787
|
-
}
|
|
788
|
-
if (bNoInitialRedirect &&
|
|
789
|
-
pegaAuthConfig.authService === 'pega' &&
|
|
790
|
-
sdkConfigAuth.mashupUserIdentifier &&
|
|
791
|
-
sdkConfigAuth.mashupPassword) {
|
|
792
|
-
authCodeProps.userIdentifier = sdkConfigAuth.mashupUserIdentifier;
|
|
793
|
-
authCodeProps.password = sdkConfigAuth.mashupPassword;
|
|
794
|
-
}
|
|
795
|
-
if ('iframeLoginUI' in sdkConfigAuth) {
|
|
796
|
-
authCodeProps.iframeLoginUI =
|
|
797
|
-
sdkConfigAuth.iframeLoginUI.toString().toLowerCase() === 'true';
|
|
798
|
-
}
|
|
799
|
-
Object.assign(pegaAuthConfig, authCodeProps);
|
|
800
|
-
}
|
|
801
|
-
else if (pegaAuthConfig.grantType === 'passwordCreds') {
|
|
802
|
-
pegaAuthConfig.userIdentifier = sdkConfigAuth.mashupUserIdentifier;
|
|
803
|
-
pegaAuthConfig.password = sdkConfigAuth.mashupPassword;
|
|
804
|
-
}
|
|
805
|
-
Object.assign(__classPrivateFieldGet(this, _AuthManager_authConfig, "f"), pegaAuthConfig);
|
|
806
|
-
// Add beforeunload and page hide handlers to write out key properties that we want to survive a
|
|
807
|
-
// browser reload
|
|
808
|
-
if (!__classPrivateFieldGet(this, _AuthManager_beforeUnloadAdded, "f") && (!__classPrivateFieldGet(this, _AuthManager_usePASS, "f") || __classPrivateFieldGet(this, _AuthManager_tokenStorage, "f") !== 'always')) {
|
|
809
|
-
window.addEventListener('beforeunload', __classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_doBeforeUnload).bind(this));
|
|
810
|
-
window.addEventListener('pagehide', __classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_doPageHide).bind(this));
|
|
811
|
-
__classPrivateFieldSet(this, _AuthManager_beforeUnloadAdded, true, "f");
|
|
812
|
-
}
|
|
813
|
-
// Initialize PegaAuth OAuth 2.0 client library
|
|
814
|
-
if (__classPrivateFieldGet(this, _AuthManager_usePASS, "f")) {
|
|
815
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_setStorage).call(this, __classPrivateFieldGet(this, _AuthManager_ssKeyConfigInfo, "f"), __classPrivateFieldGet(this, _AuthManager_authConfig, "f"));
|
|
816
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_setStorage).call(this, __classPrivateFieldGet(this, _AuthManager_ssKeySessionInfo, "f"), __classPrivateFieldGet(this, _AuthManager_authDynState, "f"));
|
|
817
|
-
__classPrivateFieldSet(this, _AuthManager_pegaAuth, new PegaAuth(__classPrivateFieldGet(this, _AuthManager_ssKeyConfigInfo, "f"), __classPrivateFieldGet(this, _AuthManager_ssKeySessionInfo, "f")), "f");
|
|
818
|
-
}
|
|
819
|
-
else {
|
|
820
|
-
__classPrivateFieldGet(this, _AuthManager_authConfig, "f").fnDynStateChangedCB = __classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_doAuthDynStateChanged).bind(this);
|
|
821
|
-
__classPrivateFieldSet(this, _AuthManager_pegaAuth, new PegaAuth(__classPrivateFieldGet(this, _AuthManager_authConfig, "f"), __classPrivateFieldGet(this, _AuthManager_authDynState, "f")), "f");
|
|
822
|
-
}
|
|
823
|
-
this.initInProgress = false;
|
|
824
|
-
resolve(__classPrivateFieldGet(this, _AuthManager_pegaAuth, "f"));
|
|
825
|
-
});
|
|
826
|
-
}), "f");
|
|
827
|
-
return __classPrivateFieldGet(this, _AuthManager_promiseInitialize, "f");
|
|
828
|
-
}, _AuthManager_constellationInit = function _AuthManager_constellationInit(tokenInfo, authTokenUpdated, fnReauth) {
|
|
829
|
-
const constellationBootConfig = {};
|
|
830
|
-
const sdkConfigServer = SdkConfigAccess.getSdkConfigServer();
|
|
831
|
-
const sdkConfigAuth = SdkConfigAccess.getSdkConfigAuth();
|
|
832
|
-
const authConfig = __classPrivateFieldGet(this, _AuthManager_authConfig, "f");
|
|
833
|
-
// Set up constellationConfig with data that bootstrapWithAuthHeader expects
|
|
834
|
-
constellationBootConfig.customRendering = true;
|
|
835
|
-
constellationBootConfig.restServerUrl = sdkConfigServer.infinityRestServerUrl;
|
|
836
|
-
// NOTE: Needs a trailing slash! So add one if not provided
|
|
837
|
-
if (!sdkConfigServer.sdkContentServerUrl.endsWith('/')) {
|
|
838
|
-
sdkConfigServer.sdkContentServerUrl = `${sdkConfigServer.sdkContentServerUrl}/`;
|
|
839
|
-
}
|
|
840
|
-
constellationBootConfig.staticContentServerUrl = `${sdkConfigServer.sdkContentServerUrl}constellation/`;
|
|
841
|
-
if (!constellationBootConfig.staticContentServerUrl.endsWith('/')) {
|
|
842
|
-
constellationBootConfig.staticContentServerUrl = `${constellationBootConfig.staticContentServerUrl}/`;
|
|
843
|
-
}
|
|
844
|
-
// If appAlias specified, use it
|
|
845
|
-
if (sdkConfigServer.appAlias) {
|
|
846
|
-
constellationBootConfig.appAlias = sdkConfigServer.appAlias;
|
|
847
|
-
}
|
|
848
|
-
// Determine whether to send credentials with DX API transactions
|
|
849
|
-
if (sdkConfigAuth.customCookies) {
|
|
850
|
-
constellationBootConfig.customCookies = true;
|
|
851
|
-
}
|
|
852
|
-
if (__classPrivateFieldGet(this, _AuthManager_bOAuthCustom, "f") || !tokenInfo) {
|
|
853
|
-
if (tokenInfo) {
|
|
854
|
-
__classPrivateFieldSet(this, _AuthManager_authHeader, `${tokenInfo.token_type} ${tokenInfo.access_token}`, "f");
|
|
855
|
-
}
|
|
856
|
-
if (__classPrivateFieldGet(this, _AuthManager_authHeader, "f")) {
|
|
857
|
-
constellationBootConfig.authorizationHeader = __classPrivateFieldGet(this, _AuthManager_authHeader, "f");
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
else {
|
|
861
|
-
// Pass in auth info to Constellation
|
|
862
|
-
constellationBootConfig.authInfo = {
|
|
863
|
-
authType: 'OAuth2.0',
|
|
864
|
-
tokenInfo,
|
|
865
|
-
// Set whether we want constellation to try to do a full re-Auth or not ()
|
|
866
|
-
// true doesn't seem to be working in SDK scenario so always passing false for now
|
|
867
|
-
popupReauth: false /* !this.noInitialRedirect */,
|
|
868
|
-
client_id: authConfig.clientId,
|
|
869
|
-
client_secret: authConfig.clientSecret,
|
|
870
|
-
authentication_service: authConfig.authService,
|
|
871
|
-
redirect_uri: authConfig.redirectUri,
|
|
872
|
-
endPoints: {
|
|
873
|
-
authorize: authConfig.authorizeUri,
|
|
874
|
-
token: authConfig.tokenUri,
|
|
875
|
-
revoke: authConfig.revokeUri
|
|
876
|
-
},
|
|
877
|
-
secureCookie: authConfig.secureCookie,
|
|
878
|
-
onTokenRetrieval: authTokenUpdated
|
|
879
|
-
};
|
|
880
|
-
}
|
|
881
|
-
// Turn off dynamic load components (should be able to do it here instead of after load?)
|
|
882
|
-
constellationBootConfig.dynamicLoadComponents = false;
|
|
883
|
-
// Set envType if appropriate
|
|
884
|
-
if (authConfig.serverType === 'launchpad') {
|
|
885
|
-
constellationBootConfig.envType = 'LAUNCHPAD';
|
|
886
|
-
}
|
|
887
|
-
// Set locale override if specified
|
|
888
|
-
const localeOverride = this.locale;
|
|
889
|
-
if (localeOverride) {
|
|
890
|
-
constellationBootConfig.locale = localeOverride;
|
|
891
|
-
}
|
|
892
|
-
// Set additional headers if specified
|
|
893
|
-
const additionalHeaders = __classPrivateFieldGet(this, _AuthManager_loginProps, "f").additionalHeaders;
|
|
894
|
-
if (additionalHeaders) {
|
|
895
|
-
constellationBootConfig.additionalHeaders = additionalHeaders;
|
|
896
|
-
}
|
|
897
|
-
if (this.bC11NBootstrapInProgress) {
|
|
898
|
-
return;
|
|
899
|
-
}
|
|
900
|
-
this.bC11NBootstrapInProgress = true;
|
|
901
|
-
// Note that staticContentServerUrl already ends with a slash (see above), so no slash added.
|
|
902
|
-
// In order to have this import succeed needed to use the webpackIgnore magic comment tag.
|
|
903
|
-
// See: https://webpack.js.org/api/module-methods/
|
|
904
|
-
import(
|
|
905
|
-
/* webpackIgnore: true */ `${constellationBootConfig.staticContentServerUrl}bootstrap-shell.js?v=${Date.now()}`).then(bootstrapShell => {
|
|
906
|
-
// NOTE: once this callback is done, we lose the ability to access loadMashup.
|
|
907
|
-
// So, create a reference to it
|
|
908
|
-
window.myLoadMashup = bootstrapShell.loadMashup;
|
|
909
|
-
window.myLoadPortal = bootstrapShell.loadPortal;
|
|
910
|
-
window.myLoadDefaultPortal = bootstrapShell.loadDefaultPortal;
|
|
911
|
-
bootstrapShell
|
|
912
|
-
.bootstrapWithAuthHeader(constellationBootConfig, 'pega-root')
|
|
913
|
-
.then(() => {
|
|
914
|
-
// eslint-disable-next-line no-console
|
|
915
|
-
console.log('ConstellationJS bootstrap successful!');
|
|
916
|
-
this.bC11NBootstrapInProgress = false;
|
|
917
|
-
// Setup listener for the reauth event
|
|
918
|
-
if (!__classPrivateFieldGet(this, _AuthManager_bOAuthCustom, "f") && tokenInfo) {
|
|
919
|
-
PCore.getPubSubUtils().subscribe(PCore.getConstants().PUB_SUB_EVENTS.EVENT_FULL_REAUTH, fnReauth, 'authFullReauth');
|
|
920
|
-
}
|
|
921
|
-
else {
|
|
922
|
-
// customReauth event introduced with 8.8
|
|
923
|
-
const sEvent = PCore.getConstants().PUB_SUB_EVENTS.EVENT_CUSTOM_REAUTH;
|
|
924
|
-
if (sEvent) {
|
|
925
|
-
PCore.getPubSubUtils().subscribe(sEvent, fnReauth, 'doReauth');
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
// Fire SdkConstellationReady event so bridge and app route can do expected post PCore initializations
|
|
929
|
-
const event = new CustomEvent('SdkConstellationReady', {});
|
|
930
|
-
document.dispatchEvent(event);
|
|
931
|
-
})
|
|
932
|
-
.catch(e => {
|
|
933
|
-
// Assume error caught is because token is not valid and attempt a full reauth
|
|
934
|
-
// eslint-disable-next-line no-console
|
|
935
|
-
console.error(`ConstellationJS bootstrap failed. ${e}`);
|
|
936
|
-
this.bC11NBootstrapInProgress = false;
|
|
937
|
-
fnReauth();
|
|
938
|
-
});
|
|
939
|
-
});
|
|
940
|
-
/* Ends here */
|
|
941
|
-
}, _AuthManager_customConstellationInit = function _AuthManager_customConstellationInit(fnReauth) {
|
|
942
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_constellationInit).call(this, null, null, fnReauth);
|
|
943
|
-
}, _AuthManager_fireTokenAvailable = function _AuthManager_fireTokenAvailable(token, bLoadC11N = true) {
|
|
944
|
-
if (!token) {
|
|
945
|
-
// This is used on page reload to load the token from sessionStorage and carry on
|
|
946
|
-
token = __classPrivateFieldGet(this, _AuthManager_tokenInfo, "f");
|
|
947
|
-
if (!token) {
|
|
948
|
-
return;
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
__classPrivateFieldSet(this, _AuthManager_tokenInfo, token, "f");
|
|
952
|
-
if (__classPrivateFieldGet(this, _AuthManager_tokenStorage, "f") === 'always') {
|
|
953
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_setStorage).call(this, __classPrivateFieldGet(this, _AuthManager_ssKeyTokenInfo, "f"), __classPrivateFieldGet(this, _AuthManager_tokenInfo, "f"));
|
|
954
|
-
}
|
|
955
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_updateLoginStatus).call(this);
|
|
956
|
-
// this.isLoggedIn is getting updated in updateLoginStatus
|
|
957
|
-
this.isLoggedIn = true;
|
|
958
|
-
this.usePopupForRestOfSession = true;
|
|
959
|
-
if (!window.PCore && bLoadC11N) {
|
|
960
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_constellationInit).call(this, token, __classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_authTokenUpdated).bind(this), __classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_authFullReauth).bind(this));
|
|
961
|
-
}
|
|
962
|
-
/*
|
|
963
|
-
// Create and dispatch the SdkLoggedIn event to trigger constellationInit
|
|
964
|
-
const event = new CustomEvent('SdkLoggedIn', { detail: { authConfig, tokenInfo: token } });
|
|
965
|
-
document.dispatchEvent(event);
|
|
966
|
-
*/
|
|
967
|
-
}, _AuthManager_processTokenOnLogin = function _AuthManager_processTokenOnLogin(token, bLoadC11N = true) {
|
|
968
|
-
__classPrivateFieldSet(this, _AuthManager_tokenInfo, token, "f");
|
|
969
|
-
if (__classPrivateFieldGet(this, _AuthManager_tokenStorage, "f") === 'always') {
|
|
970
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_setStorage).call(this, __classPrivateFieldGet(this, _AuthManager_ssKeyTokenInfo, "f"), __classPrivateFieldGet(this, _AuthManager_tokenInfo, "f"));
|
|
971
|
-
}
|
|
972
|
-
if (__classPrivateFieldGet(this, _AuthManager_bOAuthCustom, "f")) {
|
|
973
|
-
// authHeader setter will also set #authHeader and invoke getAuthUtils().setAuthorizationHeader
|
|
974
|
-
this.authHeader = `${token.token_type} ${token.access_token}`;
|
|
975
|
-
}
|
|
976
|
-
if (window.PCore && !__classPrivateFieldGet(this, _AuthManager_authHeader, "f")) {
|
|
977
|
-
PCore.getAuthUtils().setTokens(token);
|
|
978
|
-
}
|
|
979
|
-
else {
|
|
980
|
-
__classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_fireTokenAvailable).call(this, token, bLoadC11N);
|
|
981
|
-
}
|
|
982
|
-
}, _AuthManager_doCustomTokenParamsCB = function _AuthManager_doCustomTokenParamsCB() {
|
|
983
|
-
if (__classPrivateFieldGet(this, _AuthManager_authConfig, "f").grantType === 'customBearer' && __classPrivateFieldGet(this, _AuthManager_customTokenParamsCB, "f")) {
|
|
984
|
-
try {
|
|
985
|
-
const customTokenParams = __classPrivateFieldGet(this, _AuthManager_customTokenParamsCB, "f").call(this);
|
|
986
|
-
if (customTokenParams) {
|
|
987
|
-
__classPrivateFieldGet(this, _AuthManager_authConfig, "f").customTokenParams = customTokenParams;
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
catch (e) {
|
|
991
|
-
// eslint-disable-next-line no-console
|
|
992
|
-
console.error(`Error on customTokenParams callback. ${e}`);
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
}, _AuthManager_updateLoginStatus = function _AuthManager_updateLoginStatus() {
|
|
996
|
-
if (!__classPrivateFieldGet(this, _AuthManager_authHeader, "f") && __classPrivateFieldGet(this, _AuthManager_tokenInfo, "f")?.access_token) {
|
|
997
|
-
// Use setter to set this securely
|
|
998
|
-
this.authHeader = `${__classPrivateFieldGet(this, _AuthManager_tokenInfo, "f").token_type} ${__classPrivateFieldGet(this, _AuthManager_tokenInfo, "f").access_token}`;
|
|
999
|
-
}
|
|
1000
|
-
this.isLoggedIn =
|
|
1001
|
-
!!(__classPrivateFieldGet(this, _AuthManager_authHeader, "f") && __classPrivateFieldGet(this, _AuthManager_authHeader, "f").length > 0) ||
|
|
1002
|
-
(__classPrivateFieldGet(this, _AuthManager_authConfig, "f").secureCookie && Object.keys(__classPrivateFieldGet(this, _AuthManager_tokenInfo, "f") || {}).length > 0);
|
|
1003
|
-
}, _AuthManager_authFullReauth = function _AuthManager_authFullReauth() {
|
|
1004
|
-
const bHandleHere = true; // Other alternative is to raise an event and have someone else handle it
|
|
1005
|
-
if (this.reauthStart) {
|
|
1006
|
-
const reauthIgnoreInterval = 300000; // 5 minutes
|
|
1007
|
-
const currTime = Date.now();
|
|
1008
|
-
const bReauthInProgress = currTime - this.reauthStart <= reauthIgnoreInterval;
|
|
1009
|
-
if (bReauthInProgress) {
|
|
1010
|
-
return;
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
if (bHandleHere) {
|
|
1014
|
-
// Don't want to do a full clear of authMgr as will loose state props (like sessionIndex). Rather just clear the tokens
|
|
1015
|
-
this.clear(true);
|
|
1016
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
1017
|
-
login(true);
|
|
1018
|
-
}
|
|
1019
|
-
else {
|
|
1020
|
-
// Fire the SdkFullReauth event to indicate a new token is needed (PCore.getAuthUtils.setTokens method
|
|
1021
|
-
// should be used to communicate the new token to Constellation JS Engine.
|
|
1022
|
-
const event = new CustomEvent('SdkFullReauth', {
|
|
1023
|
-
detail: __classPrivateFieldGet(this, _AuthManager_instances, "m", _AuthManager_processTokenOnLogin).bind(this)
|
|
1024
|
-
});
|
|
1025
|
-
document.dispatchEvent(event);
|
|
1026
|
-
}
|
|
1027
|
-
}, _AuthManager_authTokenUpdated = function _AuthManager_authTokenUpdated(tokenInfo) {
|
|
1028
|
-
__classPrivateFieldSet(this, _AuthManager_tokenInfo, tokenInfo, "f");
|
|
1029
|
-
};
|
|
1030
1044
|
const gAuthMgr = new AuthManager();
|
|
1031
1045
|
// TODO: Cope with 401 and refresh token if possible (or just hope that it succeeds during login)
|
|
1032
1046
|
/**
|