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.
- package/backend.d.ts +27 -6
- package/backend.js +124 -139
- package/backend.js.map +1 -1
- package/core/Oidc.d.ts +28 -4
- package/core/createOidc.d.ts +12 -3
- package/core/createOidc.js +1 -1
- package/core/createOidc.js.map +1 -1
- package/core/earlyInit.d.ts +1 -0
- package/core/earlyInit.js +11 -4
- package/core/earlyInit.js.map +1 -1
- package/core/iframeMessageProtection.js +16 -18
- package/core/iframeMessageProtection.js.map +1 -1
- package/core/loginOrGoToAuthServer.js +8 -3
- package/core/loginOrGoToAuthServer.js.map +1 -1
- package/core/loginSilent.js +4 -0
- package/core/loginSilent.js.map +1 -1
- package/core/oidcClientTsUserToTokens.d.ts +1 -1
- package/core/oidcClientTsUserToTokens.js.map +1 -1
- package/core/requiredPostHydrationReplaceNavigationUrl.d.ts +6 -0
- package/core/requiredPostHydrationReplaceNavigationUrl.js +12 -0
- package/core/requiredPostHydrationReplaceNavigationUrl.js.map +1 -0
- package/entrypoint.d.ts +1 -0
- package/entrypoint.js +3 -1
- package/entrypoint.js.map +1 -1
- package/esm/angular.d.ts +14 -4
- package/esm/angular.js +155 -10
- package/esm/angular.js.map +1 -1
- package/esm/backend.d.ts +48 -0
- package/esm/backend.js +259 -0
- package/esm/backend.js.map +1 -0
- package/esm/core/Oidc.d.ts +28 -4
- package/esm/core/createOidc.d.ts +12 -3
- package/esm/core/createOidc.js +1 -1
- package/esm/core/createOidc.js.map +1 -1
- package/esm/core/earlyInit.d.ts +1 -0
- package/esm/core/earlyInit.js +11 -4
- package/esm/core/earlyInit.js.map +1 -1
- package/esm/core/iframeMessageProtection.js +16 -18
- package/esm/core/iframeMessageProtection.js.map +1 -1
- package/esm/core/loginOrGoToAuthServer.js +8 -3
- package/esm/core/loginOrGoToAuthServer.js.map +1 -1
- package/esm/core/loginSilent.js +4 -0
- package/esm/core/loginSilent.js.map +1 -1
- package/esm/core/oidcClientTsUserToTokens.d.ts +1 -1
- package/esm/core/oidcClientTsUserToTokens.js.map +1 -1
- package/esm/core/requiredPostHydrationReplaceNavigationUrl.d.ts +6 -0
- package/esm/core/requiredPostHydrationReplaceNavigationUrl.js +8 -0
- package/esm/core/requiredPostHydrationReplaceNavigationUrl.js.map +1 -0
- package/esm/entrypoint.d.ts +1 -0
- package/esm/entrypoint.js +1 -0
- package/esm/entrypoint.js.map +1 -1
- package/esm/mock/oidc.d.ts +1 -1
- package/esm/mock/oidc.js.map +1 -1
- package/esm/react/react.d.ts +1 -1
- package/esm/tanstack-start/react/accessTokenValidation_rfc9068.d.ts +12 -0
- package/esm/tanstack-start/react/accessTokenValidation_rfc9068.js +95 -0
- package/esm/tanstack-start/react/accessTokenValidation_rfc9068.js.map +1 -0
- package/esm/tanstack-start/react/apiBuilder.d.ts +27 -0
- package/esm/tanstack-start/react/apiBuilder.js +58 -0
- package/esm/tanstack-start/react/apiBuilder.js.map +1 -0
- package/esm/tanstack-start/react/createOidcSpaApi.d.ts +9 -0
- package/esm/tanstack-start/react/createOidcSpaApi.js +678 -0
- package/esm/tanstack-start/react/createOidcSpaApi.js.map +1 -0
- package/esm/tanstack-start/react/index.d.ts +3 -0
- package/esm/tanstack-start/react/index.js +4 -0
- package/esm/tanstack-start/react/index.js.map +1 -0
- package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/UnifiedClientRetryForSsrLoadersError.d.ts +4 -0
- package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/UnifiedClientRetryForSsrLoadersError.js +8 -0
- package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/UnifiedClientRetryForSsrLoadersError.js.map +1 -0
- package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/enableUnifiedClientRetryForSsrLoaders.d.ts +4 -0
- package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/enableUnifiedClientRetryForSsrLoaders.js +76 -0
- package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/enableUnifiedClientRetryForSsrLoaders.js.map +1 -0
- package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/entrypoint.d.ts +1 -0
- package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/entrypoint.js +11 -0
- package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/entrypoint.js.map +1 -0
- package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/index.d.ts +2 -0
- package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/index.js +3 -0
- package/esm/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/index.js.map +1 -0
- package/esm/tanstack-start/react/types.d.ts +355 -0
- package/esm/tanstack-start/react/types.js +2 -0
- package/esm/tanstack-start/react/types.js.map +1 -0
- package/esm/tanstack-start/react/withHandlingOidcPostLoginNavigation.d.ts +2 -0
- package/esm/tanstack-start/react/withHandlingOidcPostLoginNavigation.js +25 -0
- package/esm/tanstack-start/react/withHandlingOidcPostLoginNavigation.js.map +1 -0
- package/esm/tools/GetterOrDirectValue.d.ts +1 -0
- package/esm/tools/GetterOrDirectValue.js +2 -0
- package/esm/tools/GetterOrDirectValue.js.map +1 -0
- package/esm/tools/ZodSchemaLike.d.ts +3 -0
- package/esm/tools/ZodSchemaLike.js +2 -0
- package/esm/tools/ZodSchemaLike.js.map +1 -0
- package/esm/tools/inferIsViteDev.d.ts +1 -0
- package/esm/tools/inferIsViteDev.js +6 -0
- package/esm/tools/inferIsViteDev.js.map +1 -0
- package/esm/tools/infer_import_meta_env_BASE_URL.d.ts +1 -0
- package/esm/tools/infer_import_meta_env_BASE_URL.js +15 -0
- package/esm/tools/infer_import_meta_env_BASE_URL.js.map +1 -0
- package/esm/tools/tsafe/uncapitalize.d.ts +2 -0
- package/esm/tools/tsafe/uncapitalize.js +5 -0
- package/esm/tools/tsafe/uncapitalize.js.map +1 -0
- package/esm/vendor/backend/evt.d.ts +2 -0
- package/esm/vendor/backend/evt.js +3286 -0
- package/esm/vendor/backend/jose.d.ts +1 -0
- package/esm/vendor/backend/jose.js +3546 -0
- package/esm/vendor/backend/tsafe.d.ts +5 -0
- package/esm/vendor/backend/tsafe.js +68 -0
- package/esm/vendor/backend/zod.d.ts +1 -0
- package/esm/vendor/backend/zod.js +4023 -0
- package/esm/vendor/frontend/worker-timers.js +261 -1
- package/mock/oidc.d.ts +1 -1
- package/mock/oidc.js.map +1 -1
- package/package.json +40 -4
- package/react/react.d.ts +1 -1
- package/src/angular.ts +224 -9
- package/src/backend.ts +201 -166
- package/src/core/Oidc.ts +41 -11
- package/src/core/createOidc.ts +12 -3
- package/src/core/earlyInit.ts +19 -4
- package/src/core/iframeMessageProtection.ts +14 -15
- package/src/core/loginOrGoToAuthServer.ts +11 -3
- package/src/core/loginSilent.ts +5 -0
- package/src/core/oidcClientTsUserToTokens.ts +2 -2
- package/src/core/requiredPostHydrationReplaceNavigationUrl.ts +11 -0
- package/src/entrypoint.ts +1 -0
- package/src/mock/oidc.ts +2 -2
- package/src/react/react.tsx +1 -1
- package/src/tanstack-start/react/accessTokenValidation_rfc9068.ts +135 -0
- package/src/tanstack-start/react/apiBuilder.ts +151 -0
- package/src/tanstack-start/react/createOidcSpaApi.tsx +1009 -0
- package/src/tanstack-start/react/index.ts +5 -0
- package/src/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/UnifiedClientRetryForSsrLoadersError.ts +8 -0
- package/src/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/enableUnifiedClientRetryForSsrLoaders.tsx +110 -0
- package/src/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/entrypoint.ts +13 -0
- package/src/tanstack-start/react/rfcUnifiedClientRetryForSsrLoaders/index.ts +2 -0
- package/src/tanstack-start/react/types.tsx +415 -0
- package/src/tanstack-start/react/withHandlingOidcPostLoginNavigation.tsx +35 -0
- package/src/tools/GetterOrDirectValue.ts +1 -0
- package/src/tools/ZodSchemaLike.ts +3 -0
- package/src/tools/getThisCodebaseRootDirPath_cjs.ts +19 -0
- package/src/tools/inferIsViteDev.ts +6 -0
- package/src/tools/infer_import_meta_env_BASE_URL.ts +19 -0
- package/src/tools/tsafe/uncapitalize.ts +4 -0
- package/src/vendor/backend/jose.ts +1 -0
- package/src/vendor/build-runtime/babel.ts +6 -0
- package/src/vendor/build-runtime/magic-string.ts +3 -0
- package/src/vite-plugin/detectProjectType.ts +20 -0
- package/src/vite-plugin/excludeModuleExportFromOptimizedDeps.ts +20 -0
- package/src/vite-plugin/handleClientEntrypoint.ts +260 -0
- package/src/vite-plugin/index.ts +1 -0
- package/src/vite-plugin/transformCreateFileRoute.ts +240 -0
- package/src/vite-plugin/vite-plugin.ts +54 -0
- package/tools/GetterOrDirectValue.d.ts +1 -0
- package/tools/GetterOrDirectValue.js +3 -0
- package/tools/GetterOrDirectValue.js.map +1 -0
- package/tools/ZodSchemaLike.d.ts +3 -0
- package/tools/ZodSchemaLike.js +3 -0
- package/tools/ZodSchemaLike.js.map +1 -0
- package/tools/getThisCodebaseRootDirPath_cjs.d.ts +2 -0
- package/tools/getThisCodebaseRootDirPath_cjs.js +53 -0
- package/tools/getThisCodebaseRootDirPath_cjs.js.map +1 -0
- package/tools/tsafe/uncapitalize.d.ts +2 -0
- package/tools/tsafe/uncapitalize.js +8 -0
- package/tools/tsafe/uncapitalize.js.map +1 -0
- package/vendor/backend/jose.d.ts +1 -0
- package/vendor/backend/jose.js +3 -0
- package/vendor/build-runtime/babel.d.ts +6 -0
- package/vendor/build-runtime/babel.js +3 -0
- package/vendor/build-runtime/magic-string.d.ts +2 -0
- package/vendor/build-runtime/magic-string.js +2 -0
- package/vendor/frontend/oidc-client-ts.js +0 -2
- package/vite-plugin/detectProjectType.d.ts +10 -0
- package/vite-plugin/detectProjectType.js +15 -0
- package/vite-plugin/detectProjectType.js.map +1 -0
- package/vite-plugin/excludeModuleExportFromOptimizedDeps.d.ts +4 -0
- package/vite-plugin/excludeModuleExportFromOptimizedDeps.js +50 -0
- package/vite-plugin/excludeModuleExportFromOptimizedDeps.js.map +1 -0
- package/vite-plugin/handleClientEntrypoint.d.ts +10 -0
- package/vite-plugin/handleClientEntrypoint.js +211 -0
- package/vite-plugin/handleClientEntrypoint.js.map +1 -0
- package/vite-plugin/index.d.ts +1 -0
- package/vite-plugin/index.js +6 -0
- package/vite-plugin/index.js.map +1 -0
- package/vite-plugin/transformCreateFileRoute.d.ts +10 -0
- package/vite-plugin/transformCreateFileRoute.js +173 -0
- package/vite-plugin/transformCreateFileRoute.js.map +1 -0
- package/vite-plugin/vite-plugin.d.ts +5 -0
- package/vite-plugin/vite-plugin.js +46 -0
- package/vite-plugin/vite-plugin.js.map +1 -0
- package/src/vendor/backend/jsonwebtoken.ts +0 -1
- package/src/vendor/backend/node-fetch.ts +0 -2
- package/src/vendor/backend/node-jose.ts +0 -1
- package/vendor/backend/jsonwebtoken.d.ts +0 -1
- package/vendor/backend/jsonwebtoken.js +0 -3
- package/vendor/backend/node-fetch.d.ts +0 -2
- package/vendor/backend/node-fetch.js +0 -2
- package/vendor/backend/node-jose.d.ts +0 -1
- 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 {
|
|
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.
|
|
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: (
|
|
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
|
-
?
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
+
}
|