oidc-spa 7.3.0 → 8.0.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.
Files changed (89) hide show
  1. package/core/AuthResponse.d.ts +5 -0
  2. package/core/AuthResponse.js +25 -0
  3. package/core/AuthResponse.js.map +1 -1
  4. package/core/StateData.d.ts +2 -6
  5. package/core/StateData.js +0 -13
  6. package/core/StateData.js.map +1 -1
  7. package/core/createOidc.d.ts +2 -2
  8. package/core/createOidc.js +70 -19
  9. package/core/createOidc.js.map +1 -1
  10. package/core/diagnostic.js +3 -3
  11. package/core/earlyInit.d.ts +16 -0
  12. package/core/earlyInit.js +157 -0
  13. package/core/earlyInit.js.map +1 -0
  14. package/core/index.d.ts +0 -1
  15. package/core/index.js +1 -3
  16. package/core/index.js.map +1 -1
  17. package/core/loginOrGoToAuthServer.js +19 -6
  18. package/core/loginOrGoToAuthServer.js.map +1 -1
  19. package/entrypoint.d.ts +1 -7
  20. package/entrypoint.js +3 -46
  21. package/entrypoint.js.map +1 -1
  22. package/esm/core/AuthResponse.d.ts +5 -0
  23. package/esm/core/AuthResponse.js +23 -0
  24. package/esm/core/AuthResponse.js.map +1 -1
  25. package/esm/core/StateData.d.ts +2 -6
  26. package/esm/core/StateData.js +0 -12
  27. package/esm/core/StateData.js.map +1 -1
  28. package/esm/core/createOidc.d.ts +2 -2
  29. package/esm/core/createOidc.js +72 -21
  30. package/esm/core/createOidc.js.map +1 -1
  31. package/esm/core/diagnostic.js +3 -3
  32. package/esm/core/earlyInit.d.ts +16 -0
  33. package/esm/core/earlyInit.js +152 -0
  34. package/esm/core/earlyInit.js.map +1 -0
  35. package/esm/core/index.d.ts +0 -1
  36. package/esm/core/index.js +0 -1
  37. package/esm/core/index.js.map +1 -1
  38. package/esm/core/loginOrGoToAuthServer.js +19 -6
  39. package/esm/core/loginOrGoToAuthServer.js.map +1 -1
  40. package/esm/entrypoint.d.ts +1 -7
  41. package/esm/entrypoint.js +1 -45
  42. package/esm/entrypoint.js.map +1 -1
  43. package/esm/keycloak/keycloak-js/Keycloak.d.ts +4 -0
  44. package/esm/keycloak/keycloak-js/Keycloak.js +148 -173
  45. package/esm/keycloak/keycloak-js/Keycloak.js.map +1 -1
  46. package/esm/mock/oidc.js +15 -4
  47. package/esm/mock/oidc.js.map +1 -1
  48. package/esm/mock/react.d.ts +1 -1
  49. package/esm/mock/react.js +1 -1
  50. package/esm/react/react.d.ts +1 -1
  51. package/esm/react/react.js +2 -10
  52. package/esm/react/react.js.map +1 -1
  53. package/keycloak/keycloak-js/Keycloak.d.ts +4 -0
  54. package/keycloak/keycloak-js/Keycloak.js +148 -173
  55. package/keycloak/keycloak-js/Keycloak.js.map +1 -1
  56. package/mock/oidc.js +15 -4
  57. package/mock/oidc.js.map +1 -1
  58. package/mock/react.d.ts +1 -1
  59. package/mock/react.js +1 -1
  60. package/package.json +1 -1
  61. package/react/react.d.ts +1 -1
  62. package/react/react.js +1 -9
  63. package/react/react.js.map +1 -1
  64. package/src/core/AuthResponse.ts +36 -0
  65. package/src/core/StateData.ts +2 -22
  66. package/src/core/createOidc.ts +108 -24
  67. package/src/core/diagnostic.ts +3 -3
  68. package/src/core/earlyInit.ts +213 -0
  69. package/src/core/index.ts +0 -1
  70. package/src/core/loginOrGoToAuthServer.ts +24 -6
  71. package/src/entrypoint.ts +1 -69
  72. package/src/keycloak/keycloak-js/Keycloak.ts +167 -228
  73. package/src/mock/oidc.ts +15 -4
  74. package/src/mock/react.tsx +1 -1
  75. package/src/react/react.tsx +2 -18
  76. package/core/handleOidcCallback.d.ts +0 -13
  77. package/core/handleOidcCallback.js +0 -228
  78. package/core/handleOidcCallback.js.map +0 -1
  79. package/core/initialLocationHref.d.ts +0 -1
  80. package/core/initialLocationHref.js +0 -8
  81. package/core/initialLocationHref.js.map +0 -1
  82. package/esm/core/handleOidcCallback.d.ts +0 -13
  83. package/esm/core/handleOidcCallback.js +0 -223
  84. package/esm/core/handleOidcCallback.js.map +0 -1
  85. package/esm/core/initialLocationHref.d.ts +0 -1
  86. package/esm/core/initialLocationHref.js +0 -5
  87. package/esm/core/initialLocationHref.js.map +0 -1
  88. package/src/core/handleOidcCallback.ts +0 -318
  89. package/src/core/initialLocationHref.ts +0 -5
@@ -1,318 +0,0 @@
1
- import {
2
- getStateData,
3
- markStateDataAsProcessedByCallback,
4
- getIsStatQueryParamValue,
5
- type StateData
6
- } from "./StateData";
7
- import { assert, id } from "../vendor/frontend/tsafe";
8
- import type { AuthResponse } from "./AuthResponse";
9
- import { initialLocationHref } from "./initialLocationHref";
10
- import { encryptAuthResponse } from "./iframeMessageProtection";
11
-
12
- const globalContext = {
13
- previousCall: id<{ isHandled: boolean } | undefined>(undefined)
14
- };
15
-
16
- export function handleOidcCallback(): { isHandled: boolean } {
17
- if (globalContext.previousCall !== undefined) {
18
- return globalContext.previousCall;
19
- }
20
-
21
- return (globalContext.previousCall = handleOidcCallback_nonMemoized());
22
- }
23
-
24
- function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
25
- const location_urlObj = new URL(initialLocationHref);
26
-
27
- const stateUrlParamValue_wrap = (() => {
28
- fragment: {
29
- const stateUrlParamValue = new URLSearchParams(location_urlObj.hash.replace(/^#/, "")).get(
30
- "state"
31
- );
32
-
33
- if (stateUrlParamValue === null) {
34
- break fragment;
35
- }
36
-
37
- if (!getIsStatQueryParamValue({ maybeStateUrlParamValue: stateUrlParamValue })) {
38
- break fragment;
39
- }
40
-
41
- return { stateUrlParamValue, isFragment: true };
42
- }
43
-
44
- query: {
45
- const stateUrlParamValue = location_urlObj.searchParams.get("state");
46
-
47
- if (stateUrlParamValue === null) {
48
- break query;
49
- }
50
-
51
- if (!getIsStatQueryParamValue({ maybeStateUrlParamValue: stateUrlParamValue })) {
52
- break query;
53
- }
54
-
55
- if (
56
- location_urlObj.searchParams.get("client_id") !== null &&
57
- location_urlObj.searchParams.get("response_type") !== null &&
58
- location_urlObj.searchParams.get("redirect_uri") !== null
59
- ) {
60
- // NOTE: We are probably in a Keycloakify theme and oidc-spa was loaded by mistake.
61
- break query;
62
- }
63
-
64
- return { stateUrlParamValue, isFragment: false };
65
- }
66
-
67
- return undefined;
68
- })();
69
-
70
- if (stateUrlParamValue_wrap === undefined) {
71
- const backForwardTracker = readBackForwardTracker();
72
-
73
- if (backForwardTracker !== undefined) {
74
- writeBackForwardTracker({
75
- backForwardTracker: {
76
- ...backForwardTracker,
77
- hasExitedCallback: true
78
- }
79
- });
80
- }
81
-
82
- return { isHandled: false };
83
- }
84
-
85
- const isHandled = true;
86
-
87
- const { stateUrlParamValue, isFragment } = stateUrlParamValue_wrap;
88
-
89
- console.log = () => {};
90
- console.warn = () => {};
91
- console.error = () => {};
92
- console.debug = () => {};
93
-
94
- const stateData = getStateData({ stateUrlParamValue });
95
-
96
- if (
97
- stateData === undefined ||
98
- (stateData.context === "redirect" && stateData.hasBeenProcessedByCallback)
99
- ) {
100
- const historyMethod: "back" | "forward" = (() => {
101
- const backForwardTracker = readBackForwardTracker();
102
-
103
- if (backForwardTracker === undefined) {
104
- return "back";
105
- }
106
-
107
- if (!backForwardTracker.hasExitedCallback) {
108
- return backForwardTracker.previousHistoryMethod;
109
- }
110
-
111
- switch (backForwardTracker.previousHistoryMethod) {
112
- case "back":
113
- return "forward";
114
- case "forward":
115
- return "back";
116
- }
117
- })();
118
-
119
- writeBackForwardTracker({
120
- backForwardTracker: {
121
- previousHistoryMethod: historyMethod,
122
- hasExitedCallback: false
123
- }
124
- });
125
-
126
- setTimeout(() => {
127
- reloadOnBfCacheNavigation();
128
-
129
- window.history[historyMethod]();
130
-
131
- // NOTE: This is a "better than nothing" approach.
132
- // Under some circumstances it's possible to get stuck on this url
133
- // if there is no "next" page in the history for example, navigating
134
- // forward is a NoOp. So in that case it's better to reload the same route
135
- // with just the authResponse removed from the url to avoid re-entering here.
136
- setTimeout(() => {
137
- const { protocol, host, pathname, hash } = window.location;
138
- window.location.href = `${protocol}//${host}${pathname}${hash}`;
139
- }, 350);
140
- }, 0);
141
-
142
- return { isHandled };
143
- }
144
-
145
- const authResponse: AuthResponse = { state: "" };
146
-
147
- for (const [key, value] of isFragment
148
- ? new URLSearchParams(location_urlObj.hash.replace(/^#/, ""))
149
- : location_urlObj.searchParams) {
150
- authResponse[key] = value;
151
- }
152
-
153
- assert(authResponse.state !== "", "063965");
154
-
155
- switch (stateData.context) {
156
- case "iframe":
157
- encryptAuthResponse({
158
- authResponse
159
- }).then(({ encryptedMessage }) => parent.postMessage(encryptedMessage, location.origin));
160
- break;
161
- case "redirect":
162
- markStateDataAsProcessedByCallback({ stateUrlParamValue });
163
- clearBackForwardTracker();
164
- writeRedirectAuthResponses({
165
- authResponses: [...readRedirectAuthResponses(), authResponse]
166
- });
167
- reloadOnBfCacheNavigation();
168
- setTimeout(() => {
169
- const href = (() => {
170
- if (stateData.action === "login" && authResponse.error === "consent_required") {
171
- return stateData.redirectUrl_consentRequiredCase;
172
- }
173
-
174
- return stateData.redirectUrl;
175
- })();
176
-
177
- location.href = href;
178
- }, 0);
179
- break;
180
- }
181
-
182
- return { isHandled };
183
- }
184
-
185
- const {
186
- readRedirectAuthResponses,
187
- writeRedirectAuthResponses,
188
- moveRedirectAuthResponseFromSessionStorageToMemory
189
- } = (() => {
190
- const AUTH_RESPONSES_KEY = "oidc-spa:authResponses";
191
-
192
- let authResponses_movedToMemoryFromSessionStorage: AuthResponse[] | undefined = undefined;
193
-
194
- // NOTE: Here we note that we can re-write on session storage some auth response
195
- // after earlyInit in retrieveRedirectAuthResponseAndStateData
196
- // In situation where there are more than one client in the same app and we can't use iframe,
197
- // we can have one client that has to redirect before the response has been dealt with.
198
- // In most case it won't happen if the init sequence is deterministic but the client
199
- // can be instantiated at any time really.
200
- // So the move to memory of the response is fully effective only when theres one client.
201
- function writeRedirectAuthResponses(params: { authResponses: AuthResponse[] }): void {
202
- const { authResponses } = params;
203
-
204
- authResponses_movedToMemoryFromSessionStorage = undefined;
205
-
206
- if (authResponses.length === 0) {
207
- sessionStorage.removeItem(AUTH_RESPONSES_KEY);
208
- return;
209
- }
210
- sessionStorage.setItem(AUTH_RESPONSES_KEY, JSON.stringify(authResponses));
211
- }
212
-
213
- function readRedirectAuthResponses(): AuthResponse[] {
214
- if (authResponses_movedToMemoryFromSessionStorage !== undefined) {
215
- return authResponses_movedToMemoryFromSessionStorage;
216
- }
217
-
218
- const raw = sessionStorage.getItem(AUTH_RESPONSES_KEY);
219
-
220
- if (raw === null) {
221
- return [];
222
- }
223
-
224
- return JSON.parse(raw);
225
- }
226
-
227
- function moveRedirectAuthResponseFromSessionStorageToMemory() {
228
- const authResponses = readRedirectAuthResponses();
229
-
230
- writeRedirectAuthResponses({ authResponses: [] });
231
-
232
- authResponses_movedToMemoryFromSessionStorage = authResponses;
233
- }
234
-
235
- return {
236
- writeRedirectAuthResponses,
237
- readRedirectAuthResponses,
238
- moveRedirectAuthResponseFromSessionStorageToMemory
239
- };
240
- })();
241
-
242
- export { moveRedirectAuthResponseFromSessionStorageToMemory };
243
-
244
- export function retrieveRedirectAuthResponseAndStateData(params: {
245
- configId: string;
246
- }): { authResponse: AuthResponse; stateData: StateData.Redirect } | undefined {
247
- const { configId } = params;
248
-
249
- const authResponses = readRedirectAuthResponses();
250
-
251
- let authResponseAndStateData:
252
- | { authResponse: AuthResponse; stateData: StateData.Redirect }
253
- | undefined = undefined;
254
-
255
- for (const authResponse of [...authResponses]) {
256
- const stateData = getStateData({ stateUrlParamValue: authResponse.state });
257
-
258
- if (stateData === undefined) {
259
- // NOTE: We do not understand how this can happen but it can.
260
- authResponses.splice(authResponses.indexOf(authResponse), 1);
261
- continue;
262
- }
263
-
264
- assert(stateData.context === "redirect", "474728");
265
-
266
- if (stateData.configId !== configId) {
267
- continue;
268
- }
269
-
270
- authResponses.splice(authResponses.indexOf(authResponse), 1);
271
-
272
- authResponseAndStateData = { authResponse, stateData };
273
- }
274
-
275
- writeRedirectAuthResponses({ authResponses });
276
-
277
- return authResponseAndStateData;
278
- }
279
-
280
- function reloadOnBfCacheNavigation() {
281
- window.addEventListener("pageshow", event => {
282
- if (!event.persisted) {
283
- return;
284
- }
285
- location.reload();
286
- });
287
- }
288
-
289
- const { writeBackForwardTracker, readBackForwardTracker, clearBackForwardTracker } = (() => {
290
- const BACK_NAVIGATION_TRACKER_KEY = "oidc-spa:callback-back-forward-tracker";
291
-
292
- type BackForwardTracker = {
293
- previousHistoryMethod: "back" | "forward";
294
- hasExitedCallback: boolean;
295
- };
296
-
297
- function writeBackForwardTracker(params: { backForwardTracker: BackForwardTracker }): void {
298
- const { backForwardTracker } = params;
299
-
300
- sessionStorage.setItem(BACK_NAVIGATION_TRACKER_KEY, JSON.stringify(backForwardTracker));
301
- }
302
-
303
- function readBackForwardTracker(): BackForwardTracker | undefined {
304
- const raw = sessionStorage.getItem(BACK_NAVIGATION_TRACKER_KEY);
305
-
306
- if (raw === null) {
307
- return undefined;
308
- }
309
-
310
- return JSON.parse(raw);
311
- }
312
-
313
- function clearBackForwardTracker(): void {
314
- sessionStorage.removeItem(BACK_NAVIGATION_TRACKER_KEY);
315
- }
316
-
317
- return { writeBackForwardTracker, readBackForwardTracker, clearBackForwardTracker };
318
- })();
@@ -1,5 +0,0 @@
1
- const globalContext = {
2
- initialLocationHref: window.location.href
3
- };
4
-
5
- export const { initialLocationHref } = globalContext;