oidc-spa 8.1.9 → 8.1.11

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 (196) hide show
  1. package/backend.d.ts +27 -6
  2. package/backend.js +124 -139
  3. package/backend.js.map +1 -1
  4. package/core/Oidc.d.ts +28 -4
  5. package/core/createOidc.d.ts +12 -3
  6. package/core/createOidc.js +1 -1
  7. package/core/createOidc.js.map +1 -1
  8. package/core/earlyInit.d.ts +1 -0
  9. package/core/earlyInit.js +11 -4
  10. package/core/earlyInit.js.map +1 -1
  11. package/core/iframeMessageProtection.js +16 -18
  12. package/core/iframeMessageProtection.js.map +1 -1
  13. package/core/loginOrGoToAuthServer.js +8 -3
  14. package/core/loginOrGoToAuthServer.js.map +1 -1
  15. package/core/loginSilent.js +4 -0
  16. package/core/loginSilent.js.map +1 -1
  17. package/core/oidcClientTsUserToTokens.d.ts +1 -1
  18. package/core/oidcClientTsUserToTokens.js.map +1 -1
  19. package/core/requiredPostHydrationReplaceNavigationUrl.d.ts +6 -0
  20. package/core/requiredPostHydrationReplaceNavigationUrl.js +12 -0
  21. package/core/requiredPostHydrationReplaceNavigationUrl.js.map +1 -0
  22. package/entrypoint.d.ts +1 -0
  23. package/entrypoint.js +3 -1
  24. package/entrypoint.js.map +1 -1
  25. package/esm/angular.d.ts +14 -4
  26. package/esm/angular.js +155 -10
  27. package/esm/angular.js.map +1 -1
  28. package/esm/backend.d.ts +48 -0
  29. package/esm/backend.js +259 -0
  30. package/esm/backend.js.map +1 -0
  31. package/esm/core/Oidc.d.ts +28 -4
  32. package/esm/core/createOidc.d.ts +12 -3
  33. package/esm/core/createOidc.js +1 -1
  34. package/esm/core/createOidc.js.map +1 -1
  35. package/esm/core/earlyInit.d.ts +1 -0
  36. package/esm/core/earlyInit.js +11 -4
  37. package/esm/core/earlyInit.js.map +1 -1
  38. package/esm/core/iframeMessageProtection.js +16 -18
  39. package/esm/core/iframeMessageProtection.js.map +1 -1
  40. package/esm/core/loginOrGoToAuthServer.js +8 -3
  41. package/esm/core/loginOrGoToAuthServer.js.map +1 -1
  42. package/esm/core/loginSilent.js +4 -0
  43. package/esm/core/loginSilent.js.map +1 -1
  44. package/esm/core/oidcClientTsUserToTokens.d.ts +1 -1
  45. package/esm/core/oidcClientTsUserToTokens.js.map +1 -1
  46. package/esm/core/requiredPostHydrationReplaceNavigationUrl.d.ts +6 -0
  47. package/esm/core/requiredPostHydrationReplaceNavigationUrl.js +8 -0
  48. package/esm/core/requiredPostHydrationReplaceNavigationUrl.js.map +1 -0
  49. package/esm/entrypoint.d.ts +1 -0
  50. package/esm/entrypoint.js +1 -0
  51. package/esm/entrypoint.js.map +1 -1
  52. package/esm/mock/oidc.d.ts +1 -1
  53. package/esm/mock/oidc.js.map +1 -1
  54. package/esm/react/react.d.ts +1 -1
  55. package/esm/tanstack-start/react/accessTokenValidation_rfc9068.d.ts +12 -0
  56. package/esm/tanstack-start/react/accessTokenValidation_rfc9068.js +95 -0
  57. package/esm/tanstack-start/react/accessTokenValidation_rfc9068.js.map +1 -0
  58. package/esm/tanstack-start/react/apiBuilder.d.ts +27 -0
  59. package/esm/tanstack-start/react/apiBuilder.js +58 -0
  60. package/esm/tanstack-start/react/apiBuilder.js.map +1 -0
  61. package/esm/tanstack-start/react/createOidcSpaApi.d.ts +9 -0
  62. package/esm/tanstack-start/react/createOidcSpaApi.js +678 -0
  63. package/esm/tanstack-start/react/createOidcSpaApi.js.map +1 -0
  64. package/esm/tanstack-start/react/index.d.ts +3 -0
  65. package/esm/tanstack-start/react/index.js +4 -0
  66. package/esm/tanstack-start/react/index.js.map +1 -0
  67. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/UnifiedClientRetryForSsrLoadersError.d.ts +4 -0
  68. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/UnifiedClientRetryForSsrLoadersError.js +8 -0
  69. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/UnifiedClientRetryForSsrLoadersError.js.map +1 -0
  70. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/enableUnifiedClientRetryForSsrLoaders.d.ts +4 -0
  71. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/enableUnifiedClientRetryForSsrLoaders.js +76 -0
  72. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/enableUnifiedClientRetryForSsrLoaders.js.map +1 -0
  73. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/entrypoint.d.ts +1 -0
  74. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/entrypoint.js +11 -0
  75. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/entrypoint.js.map +1 -0
  76. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/index.d.ts +2 -0
  77. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/index.js +3 -0
  78. package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/index.js.map +1 -0
  79. package/esm/tanstack-start/react/types.d.ts +355 -0
  80. package/esm/tanstack-start/react/types.js +2 -0
  81. package/esm/tanstack-start/react/types.js.map +1 -0
  82. package/esm/tanstack-start/react/withHandlingOidcPostLoginNavigation.d.ts +2 -0
  83. package/esm/tanstack-start/react/withHandlingOidcPostLoginNavigation.js +25 -0
  84. package/esm/tanstack-start/react/withHandlingOidcPostLoginNavigation.js.map +1 -0
  85. package/esm/tools/GetterOrDirectValue.d.ts +1 -0
  86. package/esm/tools/GetterOrDirectValue.js +2 -0
  87. package/esm/tools/GetterOrDirectValue.js.map +1 -0
  88. package/esm/tools/ZodSchemaLike.d.ts +3 -0
  89. package/esm/tools/ZodSchemaLike.js +2 -0
  90. package/esm/tools/ZodSchemaLike.js.map +1 -0
  91. package/esm/tools/inferIsViteDev.d.ts +1 -0
  92. package/esm/tools/inferIsViteDev.js +6 -0
  93. package/esm/tools/inferIsViteDev.js.map +1 -0
  94. package/esm/tools/infer_import_meta_env_BASE_URL.d.ts +1 -0
  95. package/esm/tools/infer_import_meta_env_BASE_URL.js +15 -0
  96. package/esm/tools/infer_import_meta_env_BASE_URL.js.map +1 -0
  97. package/esm/tools/tsafe/uncapitalize.d.ts +2 -0
  98. package/esm/tools/tsafe/uncapitalize.js +5 -0
  99. package/esm/tools/tsafe/uncapitalize.js.map +1 -0
  100. package/esm/vendor/backend/evt.d.ts +2 -0
  101. package/esm/vendor/backend/evt.js +3286 -0
  102. package/esm/vendor/backend/jose.d.ts +1 -0
  103. package/esm/vendor/backend/jose.js +3546 -0
  104. package/esm/vendor/backend/tsafe.d.ts +5 -0
  105. package/esm/vendor/backend/tsafe.js +68 -0
  106. package/esm/vendor/backend/zod.d.ts +1 -0
  107. package/esm/vendor/backend/zod.js +4023 -0
  108. package/esm/vendor/frontend/worker-timers.js +261 -1
  109. package/mock/oidc.d.ts +1 -1
  110. package/mock/oidc.js.map +1 -1
  111. package/package.json +40 -4
  112. package/react/react.d.ts +1 -1
  113. package/src/angular.ts +224 -9
  114. package/src/backend.ts +201 -166
  115. package/src/core/Oidc.ts +41 -11
  116. package/src/core/createOidc.ts +12 -3
  117. package/src/core/earlyInit.ts +19 -4
  118. package/src/core/iframeMessageProtection.ts +14 -15
  119. package/src/core/loginOrGoToAuthServer.ts +11 -3
  120. package/src/core/loginSilent.ts +5 -0
  121. package/src/core/oidcClientTsUserToTokens.ts +2 -2
  122. package/src/core/requiredPostHydrationReplaceNavigationUrl.ts +11 -0
  123. package/src/entrypoint.ts +1 -0
  124. package/src/mock/oidc.ts +2 -2
  125. package/src/react/react.tsx +1 -1
  126. package/src/tanstack-start/react/accessTokenValidation_rfc9068.ts +135 -0
  127. package/src/tanstack-start/react/apiBuilder.ts +151 -0
  128. package/src/tanstack-start/react/createOidcSpaApi.tsx +1009 -0
  129. package/src/tanstack-start/react/index.ts +5 -0
  130. package/src/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/UnifiedClientRetryForSsrLoadersError.ts +8 -0
  131. package/src/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/enableUnifiedClientRetryForSsrLoaders.tsx +110 -0
  132. package/src/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/entrypoint.ts +13 -0
  133. package/src/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/index.ts +2 -0
  134. package/src/tanstack-start/react/types.tsx +415 -0
  135. package/src/tanstack-start/react/withHandlingOidcPostLoginNavigation.tsx +35 -0
  136. package/src/tools/GetterOrDirectValue.ts +1 -0
  137. package/src/tools/ZodSchemaLike.ts +3 -0
  138. package/src/tools/getThisCodebaseRootDirPath_cjs.ts +19 -0
  139. package/src/tools/inferIsViteDev.ts +6 -0
  140. package/src/tools/infer_import_meta_env_BASE_URL.ts +19 -0
  141. package/src/tools/tsafe/uncapitalize.ts +4 -0
  142. package/src/vendor/backend/jose.ts +1 -0
  143. package/src/vendor/build-runtime/babel.ts +6 -0
  144. package/src/vendor/build-runtime/magic-string.ts +3 -0
  145. package/src/vite-plugin/detectProjectType.ts +20 -0
  146. package/src/vite-plugin/excludeModuleExportFromOptimizedDeps.ts +20 -0
  147. package/src/vite-plugin/handleClientEntrypoint.ts +260 -0
  148. package/src/vite-plugin/index.ts +1 -0
  149. package/src/vite-plugin/transformCreateFileRoute.ts +240 -0
  150. package/src/vite-plugin/vite-plugin.ts +54 -0
  151. package/tools/GetterOrDirectValue.d.ts +1 -0
  152. package/tools/GetterOrDirectValue.js +3 -0
  153. package/tools/GetterOrDirectValue.js.map +1 -0
  154. package/tools/ZodSchemaLike.d.ts +3 -0
  155. package/tools/ZodSchemaLike.js +3 -0
  156. package/tools/ZodSchemaLike.js.map +1 -0
  157. package/tools/getThisCodebaseRootDirPath_cjs.d.ts +2 -0
  158. package/tools/getThisCodebaseRootDirPath_cjs.js +53 -0
  159. package/tools/getThisCodebaseRootDirPath_cjs.js.map +1 -0
  160. package/tools/tsafe/uncapitalize.d.ts +2 -0
  161. package/tools/tsafe/uncapitalize.js +8 -0
  162. package/tools/tsafe/uncapitalize.js.map +1 -0
  163. package/vendor/backend/jose.d.ts +1 -0
  164. package/vendor/backend/jose.js +3 -0
  165. package/vendor/build-runtime/babel.d.ts +6 -0
  166. package/vendor/build-runtime/babel.js +3 -0
  167. package/vendor/build-runtime/magic-string.d.ts +2 -0
  168. package/vendor/build-runtime/magic-string.js +2 -0
  169. package/vendor/frontend/oidc-client-ts.js +0 -2
  170. package/vite-plugin/detectProjectType.d.ts +10 -0
  171. package/vite-plugin/detectProjectType.js +15 -0
  172. package/vite-plugin/detectProjectType.js.map +1 -0
  173. package/vite-plugin/excludeModuleExportFromOptimizedDeps.d.ts +4 -0
  174. package/vite-plugin/excludeModuleExportFromOptimizedDeps.js +50 -0
  175. package/vite-plugin/excludeModuleExportFromOptimizedDeps.js.map +1 -0
  176. package/vite-plugin/handleClientEntrypoint.d.ts +10 -0
  177. package/vite-plugin/handleClientEntrypoint.js +211 -0
  178. package/vite-plugin/handleClientEntrypoint.js.map +1 -0
  179. package/vite-plugin/index.d.ts +1 -0
  180. package/vite-plugin/index.js +6 -0
  181. package/vite-plugin/index.js.map +1 -0
  182. package/vite-plugin/transformCreateFileRoute.d.ts +10 -0
  183. package/vite-plugin/transformCreateFileRoute.js +173 -0
  184. package/vite-plugin/transformCreateFileRoute.js.map +1 -0
  185. package/vite-plugin/vite-plugin.d.ts +5 -0
  186. package/vite-plugin/vite-plugin.js +46 -0
  187. package/vite-plugin/vite-plugin.js.map +1 -0
  188. package/src/vendor/backend/jsonwebtoken.ts +0 -1
  189. package/src/vendor/backend/node-fetch.ts +0 -2
  190. package/src/vendor/backend/node-jose.ts +0 -1
  191. package/vendor/backend/jsonwebtoken.d.ts +0 -1
  192. package/vendor/backend/jsonwebtoken.js +0 -3
  193. package/vendor/backend/node-fetch.d.ts +0 -2
  194. package/vendor/backend/node-fetch.js +0 -2
  195. package/vendor/backend/node-jose.d.ts +0 -1
  196. package/vendor/backend/node-jose.js +0 -3
package/src/angular.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { BehaviorSubject } from "rxjs";
1
+ import { BehaviorSubject, from, switchMap, Subject } from "rxjs";
2
2
  import type { Oidc, OidcInitializationError, ParamsOfCreateOidc } from "./core";
3
3
  import type { OidcMetadata } from "./core/OidcMetadata";
4
4
  import { Deferred } from "./tools/Deferred";
5
5
  import { assert, type Equals, is } from "./tools/tsafe/assert";
6
- import { createObjectThatThrowsIfAccessed } from "./tools/createObjectThatThrowsIfAccessed";
6
+ import { uncapitalize } from "./tools/tsafe/uncapitalize";
7
+ import { createObjectThatThrowsIfAccessed, AccessError } from "./tools/createObjectThatThrowsIfAccessed";
7
8
  import {
8
9
  type Signal,
9
10
  inject,
@@ -11,6 +12,7 @@ import {
11
12
  makeEnvironmentProviders,
12
13
  provideAppInitializer
13
14
  } from "@angular/core";
15
+ import type { HttpInterceptorFn, HttpRequest } from "@angular/common/http";
14
16
  import { toSignal } from "@angular/core/rxjs-interop";
15
17
  import type { ReadonlyBehaviorSubject } from "./tools/ReadonlyBehaviorSubject";
16
18
  import { Router, type CanActivateFn } from "@angular/router";
@@ -160,13 +162,15 @@ export type ParamsOfProvideMock = {
160
162
  };
161
163
 
162
164
  export abstract class AbstractOidcService<
163
- T_DecodedIdToken extends Record<string, unknown> = Oidc.Tokens.DecodedIdToken_base
165
+ T_DecodedIdToken extends Record<string, unknown> = Oidc.Tokens.DecodedIdToken_OidcCoreSpec
164
166
  > {
165
167
  protected autoLogin: boolean = false;
166
168
  protected providerAwaitsInitialization: boolean = true;
167
169
  protected decodedIdTokenSchema:
168
170
  | {
169
- parse: (decodedIdToken_original: Oidc.Tokens.DecodedIdToken_base) => T_DecodedIdToken;
171
+ parse: (
172
+ decodedIdToken_original: Oidc.Tokens.DecodedIdToken_OidcCoreSpec
173
+ ) => T_DecodedIdToken;
170
174
  }
171
175
  | undefined = undefined;
172
176
 
@@ -175,6 +179,8 @@ export abstract class AbstractOidcService<
175
179
 
176
180
  #autoLogoutWarningDurationSeconds = 45;
177
181
 
182
+ #isRunningGetParams = false;
183
+
178
184
  static provide(params: ValueOrAsyncGetter<ParamsOfProvide>): EnvironmentProviders {
179
185
  const paramsOrGetParams = params;
180
186
 
@@ -191,7 +197,12 @@ export abstract class AbstractOidcService<
191
197
  await Promise.all([
192
198
  import("./core"),
193
199
  typeof paramsOrGetParams === "function"
194
- ? paramsOrGetParams()
200
+ ? (async () => {
201
+ instance.#isRunningGetParams = true;
202
+ const params = await paramsOrGetParams();
203
+ instance.#isRunningGetParams = false;
204
+ return params;
205
+ })()
195
206
  : paramsOrGetParams
196
207
  ]);
197
208
 
@@ -264,6 +275,178 @@ export abstract class AbstractOidcService<
264
275
  ]);
265
276
  }
266
277
 
278
+ protected allowDecodedIdTokenAccessInShouldInjectAccessToken = false;
279
+
280
+ #deadlockDetectionTimer: ReturnType<typeof setTimeout> | undefined = undefined;
281
+
282
+ static createBearerInterceptor(params: {
283
+ shouldInjectAccessToken: (req: HttpRequest<unknown>) => boolean;
284
+ }): HttpInterceptorFn {
285
+ const { shouldInjectAccessToken: getShouldInjectAccessToken } = params;
286
+
287
+ return (req, next) => {
288
+ const instance = inject(this);
289
+
290
+ let shouldInjectAccessToken: boolean | undefined = undefined;
291
+ const shouldInjectAccessTokenByState: {
292
+ isUserLoggedIn: boolean;
293
+ isNewBrowserSession: boolean | undefined;
294
+ shouldInjectAccessTokenOrError: boolean | { error: unknown };
295
+ }[] = [];
296
+
297
+ let isDecodedIdTokenAccessed = false;
298
+
299
+ (instance.decodedIdTokenAccess = new Subject()).subscribe(
300
+ () => (isDecodedIdTokenAccessed = true)
301
+ );
302
+
303
+ try {
304
+ shouldInjectAccessToken = getShouldInjectAccessToken(req);
305
+ } catch (error) {
306
+ if (!(error instanceof OidcAccessedTooEarlyError) && !(error instanceof AccessError)) {
307
+ throw error;
308
+ }
309
+ }
310
+
311
+ if (shouldInjectAccessToken === undefined) {
312
+ for (const isUserLoggedIn of [false, true]) {
313
+ for (const isNewBrowserSession of isUserLoggedIn ? [false, true] : [undefined]) {
314
+ let shouldInjectAccessTokenOrError: boolean | { error: unknown };
315
+
316
+ instance.#isUserLoggedIn_override = isUserLoggedIn;
317
+ instance.#isNewBrowserSession_override = isNewBrowserSession;
318
+
319
+ try {
320
+ shouldInjectAccessTokenOrError = getShouldInjectAccessToken(req);
321
+ } catch (error) {
322
+ shouldInjectAccessTokenOrError = { error };
323
+ }
324
+
325
+ instance.#isUserLoggedIn_override = undefined;
326
+ instance.#isNewBrowserSession_override = undefined;
327
+
328
+ shouldInjectAccessTokenByState.push({
329
+ isUserLoggedIn,
330
+ isNewBrowserSession,
331
+ shouldInjectAccessTokenOrError
332
+ });
333
+ }
334
+ }
335
+ }
336
+
337
+ instance.decodedIdTokenAccess = undefined;
338
+
339
+ if (
340
+ !instance.providerAwaitsInitialization &&
341
+ isDecodedIdTokenAccessed &&
342
+ !instance.allowDecodedIdTokenAccessInShouldInjectAccessToken
343
+ ) {
344
+ throw new Error(
345
+ "oidc-spa: See https://docs.oidc-spa.dev/release-notes/reading-decodedaccesstoken-within-shouldinjectaccesstoken"
346
+ );
347
+ }
348
+
349
+ if (
350
+ shouldInjectAccessToken === false ||
351
+ (shouldInjectAccessToken === undefined &&
352
+ shouldInjectAccessTokenByState.every(
353
+ ({ shouldInjectAccessTokenOrError }) => shouldInjectAccessTokenOrError === false
354
+ ))
355
+ ) {
356
+ return next(req);
357
+ }
358
+
359
+ if (instance.#isRunningGetParams && instance.#deadlockDetectionTimer === undefined) {
360
+ instance.#deadlockDetectionTimer = setTimeout(() => {
361
+ const name = this.name.replace(/^_/, "");
362
+
363
+ switch (shouldInjectAccessToken) {
364
+ case false:
365
+ assert(false);
366
+ case true:
367
+ console.warn(
368
+ [
369
+ "oidc-spa: Probable deadlock detected!",
370
+ `Request ${req.method} ${req.urlWithParams} requires an access token,`,
371
+ `but this request is probably being made inside the async callback of`,
372
+ `${name}.provide(async () => {...}).`,
373
+ "At this point the access token cannot exist yet, initialization depends on this request itself."
374
+ ].join(" ")
375
+ );
376
+ break;
377
+ case undefined:
378
+ console.warn(
379
+ [
380
+ "oidc-spa: Probable deadlock detected!",
381
+ `While evaluating shouldInjectAccessToken(req) for ${req.method} ${req.urlWithParams},`,
382
+ "you accessed synchronous properties of",
383
+ `\`${uncapitalize(name)} = inject(${name})\` that`,
384
+ "are only available after initialization completes.",
385
+ `Requests made inside the ${name}.provide(async () => {...}) callback`,
386
+ `(typically to fetch the params), should not trigger a read of `,
387
+ `${uncapitalize(
388
+ name
389
+ )}.isUserLoggedIn or other properties inside shouldInjectAccessToken()`,
390
+ "This creates a causality violation.",
391
+ "Reorganize your shouldInjectAccessToken implementation to exit early with `false` in those case,",
392
+ "before accessing the property."
393
+ ].join(" ")
394
+ );
395
+ break;
396
+ }
397
+ }, 4_000);
398
+ }
399
+
400
+ return from(instance.getAccessToken()).pipe(
401
+ switchMap(({ accessToken }) => {
402
+ if (instance.#deadlockDetectionTimer !== undefined) {
403
+ clearTimeout(instance.#deadlockDetectionTimer);
404
+ instance.#deadlockDetectionTimer = undefined;
405
+ }
406
+
407
+ if (shouldInjectAccessToken === undefined) {
408
+ const match = shouldInjectAccessTokenByState.find(
409
+ ({ isUserLoggedIn, isNewBrowserSession }) =>
410
+ isUserLoggedIn === instance.isUserLoggedIn &&
411
+ isNewBrowserSession ===
412
+ (instance.isUserLoggedIn ? instance.isNewBrowserSession : undefined)
413
+ );
414
+
415
+ assert(match !== undefined);
416
+
417
+ const { shouldInjectAccessTokenOrError } = match;
418
+
419
+ if (typeof shouldInjectAccessTokenOrError !== "boolean") {
420
+ const { error } = shouldInjectAccessTokenOrError;
421
+ throw error;
422
+ }
423
+
424
+ shouldInjectAccessToken = shouldInjectAccessTokenOrError;
425
+ }
426
+
427
+ if (!shouldInjectAccessToken) {
428
+ return next(req);
429
+ }
430
+
431
+ if (!instance.isUserLoggedIn) {
432
+ throw new OidcAccessedTooEarlyError(
433
+ [
434
+ `oidc-spa: attempted to inject an Authorization bearer token`,
435
+ `for ${req.method} ${req.urlWithParams} but the user is not logged in.`,
436
+ `You shouldn't be attempting to call API endpoint that require authentication`,
437
+ `when the user isn't logged in.`
438
+ ].join(" ")
439
+ );
440
+ }
441
+
442
+ assert(accessToken !== undefined);
443
+
444
+ return next(req.clone({ setHeaders: { Authorization: `Bearer ${accessToken}` } }));
445
+ })
446
+ );
447
+ };
448
+ }
449
+
267
450
  static get enforceLoginGuard() {
268
451
  const canActivateFn = (async route => {
269
452
  const instance = inject(this);
@@ -344,7 +527,9 @@ export abstract class AbstractOidcService<
344
527
  const { callerName } = params;
345
528
  const { hasResolved, value } = this.#dState.getState();
346
529
  if (!hasResolved) {
347
- throw new Error(this.#getPrInitializedNotResolvedErrorMessage({ callerName }));
530
+ throw new OidcAccessedTooEarlyError(
531
+ this.#getPrInitializedNotResolvedErrorMessage({ callerName })
532
+ );
348
533
  }
349
534
  return value;
350
535
  }
@@ -384,8 +569,13 @@ export abstract class AbstractOidcService<
384
569
  return this.#getOidc({ callerName: "clientId" }).params.clientId;
385
570
  }
386
571
 
572
+ #isUserLoggedIn_override: boolean | undefined = undefined;
573
+
387
574
  get isUserLoggedIn() {
388
- return this.#getOidc({ callerName: "isUserLoggedIn" }).isUserLoggedIn;
575
+ return (
576
+ this.#isUserLoggedIn_override ??
577
+ this.#getOidc({ callerName: "isUserLoggedIn" }).isUserLoggedIn
578
+ );
389
579
  }
390
580
 
391
581
  async login(params?: {
@@ -471,7 +661,14 @@ export abstract class AbstractOidcService<
471
661
  return oidc.goToAuthServer(params);
472
662
  }
473
663
 
474
- readonly decodedIdToken$: ReadonlyBehaviorSubject<T_DecodedIdToken> = (() => {
664
+ decodedIdTokenAccess: Subject<void> | undefined = undefined;
665
+
666
+ get decodedIdToken$(): ReadonlyBehaviorSubject<T_DecodedIdToken> {
667
+ this.decodedIdTokenAccess?.next();
668
+ return this.#decodedIdToken$;
669
+ }
670
+
671
+ readonly #decodedIdToken$: ReadonlyBehaviorSubject<T_DecodedIdToken> = (() => {
475
672
  const decodedIdToken$ = new BehaviorSubject<T_DecodedIdToken>(
476
673
  createObjectThatThrowsIfAccessed({
477
674
  debugMessage: this.#getPrInitializedNotResolvedErrorMessage({
@@ -527,7 +724,12 @@ export abstract class AbstractOidcService<
527
724
  return decodedIdToken$;
528
725
  })();
529
726
 
530
- readonly $decodedIdToken = toSignal(this.decodedIdToken$, { requireSync: true });
727
+ readonly #$decodedIdToken = toSignal(this.decodedIdToken$, { requireSync: true });
728
+
729
+ get $decodedIdToken(): Signal<T_DecodedIdToken> {
730
+ this.decodedIdTokenAccess?.next();
731
+ return this.#$decodedIdToken;
732
+ }
531
733
 
532
734
  async getAccessToken(): Promise<
533
735
  { isUserLoggedIn: false; accessToken?: never } | { isUserLoggedIn: true; accessToken: string }
@@ -571,7 +773,13 @@ export abstract class AbstractOidcService<
571
773
  return toSignal(secondsLeftBeforeAutoLogout$, { requireSync: true });
572
774
  })();
573
775
 
776
+ #isNewBrowserSession_override: boolean | undefined = undefined;
777
+
574
778
  get isNewBrowserSession() {
779
+ if (this.#isNewBrowserSession_override !== undefined) {
780
+ return this.#isNewBrowserSession_override;
781
+ }
782
+
575
783
  const oidc = this.#getOidc({ callerName: "isNewBrowserSession" });
576
784
 
577
785
  if (!oidc.isUserLoggedIn) {
@@ -581,3 +789,10 @@ export abstract class AbstractOidcService<
581
789
  return oidc.isNewBrowserSession;
582
790
  }
583
791
  }
792
+
793
+ export class OidcAccessedTooEarlyError extends Error {
794
+ constructor(message: string) {
795
+ super(message);
796
+ Object.setPrototypeOf(this, new.target.prototype);
797
+ }
798
+ }