@securitydept/token-set-context-client-angular 0.3.0-beta.3 → 0.3.0-beta.6
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/README.md +6 -0
- package/fesm2022/securitydept-token-set-context-client-angular.mjs +240 -1108
- package/fesm2022/securitydept-token-set-context-client-angular.mjs.map +1 -1
- package/package.json +4 -4
- package/types/securitydept-token-set-context-client-angular.d.ts +97 -932
- package/types/securitydept-token-set-context-client-angular.d.ts.map +1 -1
|
@@ -1,966 +1,131 @@
|
|
|
1
|
-
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
|
|
2
1
|
import * as i0 from '@angular/core';
|
|
3
|
-
import {
|
|
2
|
+
import { EnvironmentProviders, InjectionToken, Provider, Signal } from '@angular/core';
|
|
3
|
+
import * as _securitydept_client from '@securitydept/client';
|
|
4
|
+
import { RouteBehaviourContextExtra, RequirementsComposition, ResourceSnapshot } from '@securitydept/client';
|
|
5
|
+
import { BaseOidcModeClient, OidcModeCallbackHandlingResult, TokenSetAuthSnapshot } from '@securitydept/token-set-context-client/orchestration';
|
|
6
|
+
import { TokenSetClientRegistryRequirementBehaviourOptions, TokenSetClientRegistryAuthRequirement, TokenSetClientRegistry, ProvideTokenSetClientRegistryOptions, TokenSetCallbackClientQuery, TokenSetCallbackClientSelectionSnapshot } from '@securitydept/token-set-context-client/registry';
|
|
7
|
+
export { ProvideTokenSetClientRegistryOptions } from '@securitydept/token-set-context-client/registry';
|
|
8
|
+
import { CanActivateFn, CanActivateChildFn, Route } from '@angular/router';
|
|
9
|
+
import { CreateAngularGuardOptions, SecureRouteConfig } from '@securitydept/client-angular';
|
|
10
|
+
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpInterceptorFn } from '@angular/common/http';
|
|
4
11
|
import { Observable } from 'rxjs';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { TokenSetResumeReconciliationOptions, AuthSnapshot, TokenSetAuthEvent, EnsureFreshAuthStateOptions, EnsureAuthForResourceOptions, EnsureAuthForResourceResult, EnsureAuthorizationHeaderOptions } from '@securitydept/token-set-context-client/orchestration';
|
|
8
|
-
import { OidcModeClient, OidcCallbackClient, TokenSetClientEntry as TokenSetClientEntry$1, ClientInitializationPriority, TokenSetAuthRegistry as TokenSetAuthRegistry$1, ClientMeta, ClientKeySelector, ClientFilter, ClientQueryOptions, EnsureRegistryAuthForResourceOptions, TokenSetCallbackResumeState, TokenSetCallbackResumeOptions, TokenSetCallbackResumeResult } from '@securitydept/token-set-context-client/registry';
|
|
9
|
-
export { ClientFilter, ClientInitializationPriority, ClientKeySelector, ClientMeta, ClientQueryOptions, EnsureRegistryAuthForResourceOptions, OidcCallbackClient, OidcModeClient, OidcRedirectLoginClient, OidcRedirectLoginOptions } from '@securitydept/token-set-context-client/registry';
|
|
10
|
-
import { ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, CanActivateFn, Route } from '@angular/router';
|
|
11
|
-
import { AuthRequirement, PlannerHost, RequirementsClientSetComposition } from '@securitydept/client/auth-coordination';
|
|
12
|
-
import { PageClientEnvironmentSource } from '@securitydept/client-angular';
|
|
12
|
+
import { BackendOidcModeClient } from '@securitydept/token-set-context-client/backend-oidc-mode';
|
|
13
|
+
import { FrontendOidcModeClient, FrontendOidcModeCallbackResult } from '@securitydept/token-set-context-client/frontend-oidc-mode';
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
/** Options for {@link provideTokenSetRequirementPlannerHost}. */
|
|
16
|
+
type ProvideTokenSetRequirementPlannerHostOptions = TokenSetClientRegistryRequirementBehaviourOptions<BaseOidcModeClient, RouteBehaviourContextExtra>;
|
|
15
17
|
/**
|
|
16
|
-
*
|
|
18
|
+
* Provide registry-backed requirement behaviour for Angular guards.
|
|
17
19
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* ## Sync vs Async client factory
|
|
23
|
-
*
|
|
24
|
-
* `clientFactory` supports both synchronous and asynchronous materialization:
|
|
25
|
-
*
|
|
26
|
-
* - **Sync** (`() => OidcModeClient`): The client config is available at
|
|
27
|
-
* registration time. Classic inline config or pre-resolved projections.
|
|
28
|
-
*
|
|
29
|
-
* - **Async** (`() => Promise<OidcModeClient>`): The client config must be
|
|
30
|
-
* resolved asynchronously (e.g. fetched from a backend config projection
|
|
31
|
-
* endpoint). The registry tracks readiness state and provides `whenReady()`
|
|
32
|
-
* for guards/interceptors that need to wait.
|
|
33
|
-
*
|
|
34
|
-
* When `clientFactory` returns a Promise, the registry enters
|
|
35
|
-
* `ClientReadinessState.Initializing` for this key and transitions to
|
|
36
|
-
* `Ready` or `Failed` when the promise settles.
|
|
37
|
-
*
|
|
38
|
-
* Two additional discrimination axes are supported:
|
|
39
|
-
* - `requirementKind`: maps a RequirementKind (or custom string) → this client.
|
|
40
|
-
* Guards and resolvers can look up the client for a pending requirement without
|
|
41
|
-
* knowing the concrete key.
|
|
42
|
-
* - `providerFamily`: maps a named provider family (e.g. "google", "internal-sso")
|
|
43
|
-
* → this client. Useful when multiple clients share the same kind but differ
|
|
44
|
-
* by provider / audience.
|
|
20
|
+
* This is intentionally a thin adapter over the framework-neutral registry
|
|
21
|
+
* auth-coordination layer. Route requirements must carry
|
|
22
|
+
* `attributes.query: TokenSetClientQueryOptions`.
|
|
45
23
|
*/
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Factory that creates the OIDC mode client.
|
|
49
|
-
*
|
|
50
|
-
* May return the client synchronously (inline config) or a Promise
|
|
51
|
-
* (async config projection resolution). When a Promise is returned,
|
|
52
|
-
* the registry tracks initialization readiness automatically.
|
|
53
|
-
*/
|
|
54
|
-
clientFactory: () => TokenSetAngularClient | Promise<TokenSetAngularClient>;
|
|
55
|
-
/**
|
|
56
|
-
* When true (default), adapter-managed browser clients install the token-set
|
|
57
|
-
* page-resume reconciler during materialization.
|
|
58
|
-
*
|
|
59
|
-
* Disable only when the host intentionally owns browser lifecycle wiring for
|
|
60
|
-
* this client and can prove an equivalent resume trigger path.
|
|
61
|
-
*
|
|
62
|
-
* @default true
|
|
63
|
-
*/
|
|
64
|
-
resumeReconciliation?: boolean;
|
|
65
|
-
/**
|
|
66
|
-
* Browser lifecycle options forwarded to the default token-set resume
|
|
67
|
-
* reconciler when `resumeReconciliation !== false`.
|
|
68
|
-
*/
|
|
69
|
-
resumeReconciliationOptions?: TokenSetResumeReconciliationOptions;
|
|
70
|
-
/**
|
|
71
|
-
* Initialization priority. Defaults to `"primary"` (eager). Set to
|
|
72
|
-
* `"lazy"` to defer clientFactory execution until the registry is asked
|
|
73
|
-
* for this key via `whenReady(key)` / `preload(key)` / `idleWarmup()`.
|
|
74
|
-
*/
|
|
75
|
-
priority?: ClientInitializationPriority;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Per-client Angular service that bridges a single OIDC mode client to
|
|
80
|
-
* Angular signals + RxJS.
|
|
81
|
-
*
|
|
82
|
-
* Lifecycle teardown is explicit. Construct with
|
|
83
|
-
* `new TokenSetAuthService(client, autoRestore)` and call `.dispose()` when
|
|
84
|
-
* the service owner tears down. The shared registry core handles this
|
|
85
|
-
* automatically — adopters that wire the service directly (rare) must call
|
|
86
|
-
* `dispose()` themselves, typically bound to a `DestroyRef.onDestroy`.
|
|
87
|
-
*/
|
|
88
|
-
declare class TokenSetAuthService {
|
|
89
|
-
/** The underlying SDK client instance. */
|
|
90
|
-
readonly client: TokenSetAngularClient;
|
|
91
|
-
/** Current auth snapshot as an Angular signal. */
|
|
92
|
-
readonly authState: WritableSignal<AuthSnapshot | null>;
|
|
93
|
-
/** Current auth snapshot as an RxJS Observable. */
|
|
94
|
-
readonly authState$: Observable<AuthSnapshot | null>;
|
|
95
|
-
/** Promise that resolves when initial state restore completes (or null if skipped). */
|
|
96
|
-
readonly restorePromise: Promise<AuthSnapshot | null> | null;
|
|
97
|
-
readonly authEvents: EventStreamTrait<TokenSetAuthEvent>;
|
|
98
|
-
private readonly cleanup;
|
|
99
|
-
private disposed;
|
|
100
|
-
constructor(
|
|
101
|
-
/** The underlying SDK client instance. */
|
|
102
|
-
client: TokenSetAngularClient, autoRestore: boolean);
|
|
103
|
-
/** Whether the user is currently authenticated. */
|
|
104
|
-
isAuthenticated(): boolean;
|
|
105
|
-
/** Current access token, or null. */
|
|
106
|
-
accessToken(): string | null;
|
|
107
|
-
ensureFreshAuthState(options?: EnsureFreshAuthStateOptions): Promise<AuthSnapshot | null>;
|
|
108
|
-
ensureAuthForResource(options?: EnsureAuthForResourceOptions): Promise<EnsureAuthForResourceResult>;
|
|
109
|
-
ensureAccessToken(options?: EnsureFreshAuthStateOptions): Promise<string | null>;
|
|
110
|
-
ensureAuthorizationHeader(options?: EnsureAuthorizationHeaderOptions): Promise<string | null>;
|
|
111
|
-
/**
|
|
112
|
-
* Release all resources owned by this service.
|
|
113
|
-
*
|
|
114
|
-
* - Unsubscribes the SDK state bridge
|
|
115
|
-
* - Calls `client.dispose()`
|
|
116
|
-
*
|
|
117
|
-
* Idempotent: subsequent calls are no-ops. Called by the shared registry
|
|
118
|
-
* at teardown; adopters invoking TokenSetAuthService directly must call
|
|
119
|
-
* this themselves (typically bound to `DestroyRef.onDestroy`).
|
|
120
|
-
*/
|
|
121
|
-
dispose(): void;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
type AngularClient = TokenSetAngularClient;
|
|
125
|
-
declare class TokenSetAuthRegistry {
|
|
126
|
-
/**
|
|
127
|
-
* Shared framework-neutral registry core. Angular consumers rarely need
|
|
128
|
-
* direct access, but this is exposed so adapter-internal helpers
|
|
129
|
-
* (`CallbackResumeService`, `bearer-interceptor`) can query the core
|
|
130
|
-
* directly when they don't need Angular-specific behaviour.
|
|
131
|
-
*/
|
|
132
|
-
readonly core: TokenSetAuthRegistry$1<AngularClient, TokenSetAuthService>;
|
|
133
|
-
readonly authEvents: EventStreamTrait<TokenSetAuthEvent>;
|
|
134
|
-
constructor();
|
|
135
|
-
/**
|
|
136
|
-
* Register a client entry. Supports sync / async / lazy priority.
|
|
137
|
-
*
|
|
138
|
-
* The second `destroyRef` argument is no longer
|
|
139
|
-
* required — the registry pulls its own `DestroyRef` via injection and
|
|
140
|
-
* binds teardown once per Angular scope.
|
|
141
|
-
*/
|
|
142
|
-
register(entry: TokenSetClientEntry & {
|
|
143
|
-
priority?: "primary" | "lazy";
|
|
144
|
-
clientFactory: () => AngularClient;
|
|
145
|
-
}): TokenSetAuthService;
|
|
146
|
-
register(entry: TokenSetClientEntry & {
|
|
147
|
-
priority?: "primary" | "lazy";
|
|
148
|
-
clientFactory: () => Promise<AngularClient>;
|
|
149
|
-
}): Promise<TokenSetAuthService>;
|
|
150
|
-
register(entry: TokenSetClientEntry): TokenSetAuthService | Promise<TokenSetAuthService> | undefined;
|
|
151
|
-
/**
|
|
152
|
-
* Manually dispose the registry. Normally bound to the ambient
|
|
153
|
-
* `DestroyRef` at construction; call this explicitly when instantiating
|
|
154
|
-
* the registry outside of an Angular injection context (e.g. in unit
|
|
155
|
-
* tests).
|
|
156
|
-
*/
|
|
157
|
-
dispose(): void;
|
|
158
|
-
isReady(key: string): boolean;
|
|
159
|
-
readinessState(key: string): ClientReadinessState;
|
|
160
|
-
whenReady(key: string): Promise<TokenSetAuthService>;
|
|
161
|
-
/**
|
|
162
|
-
* Preload a lazy client without throwing on rejection. Callers are
|
|
163
|
-
* expected to attach `.catch` handlers for fire-and-forget usage.
|
|
164
|
-
*/
|
|
165
|
-
preload(key: string): Promise<TokenSetAuthService>;
|
|
166
|
-
/**
|
|
167
|
-
* Schedule preload for every lazy+not-initialized client using
|
|
168
|
-
* `requestIdleCallback` / `setTimeout` fallback.
|
|
169
|
-
*/
|
|
170
|
-
idleWarmup(): () => void;
|
|
171
|
-
reset(key: string): void;
|
|
172
|
-
metaFor(clientKey: string): ClientMeta | undefined;
|
|
173
|
-
get(key: string): TokenSetAuthService | undefined;
|
|
174
|
-
require(key: string): TokenSetAuthService;
|
|
175
|
-
keys(): string[];
|
|
176
|
-
entries(): Array<[string, TokenSetAuthService]>;
|
|
177
|
-
clientKeyGenForUrl(url: string): Generator<string, void, unknown>;
|
|
178
|
-
clientKeyGenForCallback(url: string): Generator<string, void, unknown>;
|
|
179
|
-
clientKeyGenForRequirement(requirementKind: string): Generator<string, void, unknown>;
|
|
180
|
-
clientKeyGenForProviderFamily(providerFamily: string): Generator<string, void, unknown>;
|
|
181
|
-
clientKeyListForUrl(url: string): string[];
|
|
182
|
-
clientKeyListForCallback(url: string): string[];
|
|
183
|
-
clientKeyListForRequirement(requirementKind: string): string[];
|
|
184
|
-
clientKeyListForProviderFamily(providerFamily: string): string[];
|
|
185
|
-
clientKeyForUrl(url: string, selector?: ClientKeySelector): string | undefined;
|
|
186
|
-
clientKeyForCallback(url: string, selector?: ClientKeySelector): string | undefined;
|
|
187
|
-
clientKeyForRequirement(requirementKind: string, selector?: ClientKeySelector): string | undefined;
|
|
188
|
-
clientKeyForProviderFamily(providerFamily: string, selector?: ClientKeySelector): string | undefined;
|
|
189
|
-
requireForRequirement(requirementKind: string, selector?: ClientKeySelector): TokenSetAuthService;
|
|
190
|
-
requireForProviderFamily(providerFamily: string, selector?: ClientKeySelector): TokenSetAuthService;
|
|
191
|
-
clientKeyGenForFilter(filter: ClientFilter): Generator<string, void, unknown>;
|
|
192
|
-
clientKeyGenForOptions(options: ClientQueryOptions): Generator<string, void, unknown>;
|
|
193
|
-
clientKeysForOptions(options: ClientQueryOptions): string[];
|
|
194
|
-
accessToken(key?: string): string | null;
|
|
195
|
-
ensureAccessToken(key?: string): Promise<string | null>;
|
|
196
|
-
ensureAuthorizationHeader(key?: string): Promise<string | null>;
|
|
197
|
-
ensureAuthForResource(options?: EnsureRegistryAuthForResourceOptions): Promise<EnsureAuthForResourceResult | null>;
|
|
198
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<TokenSetAuthRegistry, never>;
|
|
199
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<TokenSetAuthRegistry>;
|
|
200
|
-
}
|
|
24
|
+
declare function provideTokenSetRequirementPlannerHost(options?: ProvideTokenSetRequirementPlannerHostOptions): EnvironmentProviders;
|
|
201
25
|
|
|
202
|
-
/**
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
* patterns they registered with `provideTokenSetAuth({ clients: [...] })`.
|
|
209
|
-
*/
|
|
210
|
-
interface BearerInterceptorOptions {
|
|
211
|
-
/**
|
|
212
|
-
* When `true`, the interceptor injects a bearer header ONLY for requests
|
|
213
|
-
* whose URL matches a registered client's `urlPatterns`. Requests with no
|
|
214
|
-
* matching client receive no `Authorization` header even when a token is
|
|
215
|
-
* available elsewhere in the registry.
|
|
216
|
-
*
|
|
217
|
-
* When `false` (default, single-client convenience), the interceptor
|
|
218
|
-
* falls back to `registry.accessToken()` for unmatched URLs — useful only
|
|
219
|
-
* when the host issues all HTTP traffic to one already-known backend.
|
|
220
|
-
*
|
|
221
|
-
* Adopters with more than one backend, more than one OIDC audience, or
|
|
222
|
-
* any third-party HTTP traffic from the same Angular host MUST set this
|
|
223
|
-
* to `true` to prevent cross-origin token leakage.
|
|
224
|
-
*
|
|
225
|
-
* @default false
|
|
226
|
-
*/
|
|
227
|
-
strictUrlMatch?: boolean;
|
|
26
|
+
/** Serializable token-set security declaration for a child route. */
|
|
27
|
+
interface TokenSetSecureRouteSecurityOptions {
|
|
28
|
+
/** Requirements declared at this route segment. */
|
|
29
|
+
requirements?: readonly TokenSetClientRegistryAuthRequirement[];
|
|
30
|
+
/** Composition strategy against ancestor requirements (default `merge`). */
|
|
31
|
+
composition?: RequirementsComposition;
|
|
228
32
|
}
|
|
229
|
-
/**
|
|
230
|
-
|
|
231
|
-
* options via `provideTokenSetBearerInterceptor({ ... })`; the token is
|
|
232
|
-
* exported for advanced cases where the options need to be supplied or
|
|
233
|
-
* overridden separately (for example, in tests).
|
|
234
|
-
*/
|
|
235
|
-
declare const TOKEN_SET_BEARER_INTERCEPTOR_OPTIONS: InjectionToken<BearerInterceptorOptions>;
|
|
236
|
-
/**
|
|
237
|
-
* Angular class-based bearer-token interceptor (`HTTP_INTERCEPTORS` style).
|
|
238
|
-
*
|
|
239
|
-
* Selects the correct access token from the multi-client registry by URL
|
|
240
|
-
* pattern. Behaviour for unmatched URLs is governed by
|
|
241
|
-
* {@link BearerInterceptorOptions.strictUrlMatch}.
|
|
242
|
-
*
|
|
243
|
-
* Prefer the functional version via `createTokenSetBearerInterceptor()` +
|
|
244
|
-
* `withInterceptors()` when using `provideHttpClient`. Use this class-based
|
|
245
|
-
* version when you need classic `HTTP_INTERCEPTORS` multi-provider style
|
|
246
|
-
* (e.g. NgModule apps).
|
|
247
|
-
*
|
|
248
|
-
* @example
|
|
249
|
-
* ```ts
|
|
250
|
-
* // NgModule providers:
|
|
251
|
-
* provideTokenSetBearerInterceptor({ strictUrlMatch: true })
|
|
252
|
-
* ```
|
|
253
|
-
*/
|
|
254
|
-
declare class TokenSetBearerInterceptor implements HttpInterceptor {
|
|
255
|
-
private readonly registry;
|
|
256
|
-
private readonly options;
|
|
257
|
-
intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>>;
|
|
258
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<TokenSetBearerInterceptor, never>;
|
|
259
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<TokenSetBearerInterceptor>;
|
|
33
|
+
/** Root-level token-set security: metadata plus registry behaviour hooks. */
|
|
34
|
+
interface TokenSetSecureRouteRootSecurityOptions extends TokenSetSecureRouteSecurityOptions, ProvideTokenSetRequirementPlannerHostOptions {
|
|
260
35
|
}
|
|
36
|
+
/** Guard factory options specialized to token-set registry requirements. */
|
|
37
|
+
type TokenSetAngularGuardOptions = CreateAngularGuardOptions<TokenSetClientRegistryAuthRequirement>;
|
|
261
38
|
/**
|
|
262
|
-
* Create
|
|
263
|
-
*
|
|
264
|
-
* Returns a single `Provider` object that registers {@link TokenSetBearerInterceptor}
|
|
265
|
-
* as a class-based HTTP interceptor. Suitable for NgModule `providers` arrays.
|
|
266
|
-
*
|
|
267
|
-
* For functional-interceptor style (standalone apps using `provideHttpClient`),
|
|
268
|
-
* use `createTokenSetBearerInterceptor()` with `withInterceptors()` instead.
|
|
269
|
-
*
|
|
270
|
-
* @example
|
|
271
|
-
* ```ts
|
|
272
|
-
* @NgModule({
|
|
273
|
-
* providers: [
|
|
274
|
-
* provideTokenSetAuth({ clients: [...] }),
|
|
275
|
-
* provideTokenSetBearerInterceptor(), // <— replaces hand-written AuthInterceptor
|
|
276
|
-
* provideHttpClient(withInterceptorsFromDi()),
|
|
277
|
-
* ],
|
|
278
|
-
* })
|
|
279
|
-
* export class AppModule {}
|
|
280
|
-
* ```
|
|
39
|
+
* Create a token-set `CanActivateFn`. The behaviour host is resolved from DI
|
|
40
|
+
* (provided by {@link provideTokenSetRequirementPlannerHost}).
|
|
281
41
|
*/
|
|
42
|
+
declare function createTokenSetCanActivate(options?: TokenSetAngularGuardOptions): CanActivateFn;
|
|
282
43
|
/**
|
|
283
|
-
* Create
|
|
284
|
-
*
|
|
285
|
-
* Returns Angular providers that register {@link TokenSetBearerInterceptor}
|
|
286
|
-
* as a class-based HTTP interceptor and (optionally) the
|
|
287
|
-
* {@link BearerInterceptorOptions} that govern its URL-match behaviour.
|
|
288
|
-
* Suitable for NgModule `providers` arrays.
|
|
289
|
-
*
|
|
290
|
-
* For functional-interceptor style (standalone apps using `provideHttpClient`),
|
|
291
|
-
* use `createTokenSetBearerInterceptor()` with `withInterceptors()` instead.
|
|
292
|
-
*
|
|
293
|
-
* @example
|
|
294
|
-
* ```ts
|
|
295
|
-
* @NgModule({
|
|
296
|
-
* providers: [
|
|
297
|
-
* provideTokenSetAuth({ clients: [...] }),
|
|
298
|
-
* // Adopters with multiple backends or any third-party HTTP traffic
|
|
299
|
-
* // MUST opt into strictUrlMatch to prevent token leakage.
|
|
300
|
-
* provideTokenSetBearerInterceptor({ strictUrlMatch: true }),
|
|
301
|
-
* provideHttpClient(withInterceptorsFromDi()),
|
|
302
|
-
* ],
|
|
303
|
-
* })
|
|
304
|
-
* export class AppModule {}
|
|
305
|
-
* ```
|
|
44
|
+
* Create a token-set `CanActivateChildFn`. The behaviour host is resolved from
|
|
45
|
+
* DI (provided by {@link provideTokenSetRequirementPlannerHost}).
|
|
306
46
|
*/
|
|
307
|
-
declare function
|
|
47
|
+
declare function createTokenSetCanActivateChild(options?: TokenSetAngularGuardOptions): CanActivateChildFn;
|
|
308
48
|
/**
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
* If no URL pattern matches, falls back to the first available token
|
|
314
|
-
* (single-client convenience).
|
|
315
|
-
*
|
|
316
|
-
* ## Async client readiness
|
|
317
|
-
*
|
|
318
|
-
* The interceptor does **not** block or delay the HTTP request waiting for
|
|
319
|
-
* an async client to materialize. If a client is still initializing when the
|
|
320
|
-
* request fires, the request proceeds without an Authorization header.
|
|
321
|
-
*
|
|
322
|
-
* This is intentional: blocking HTTP for client initialization would deadlock
|
|
323
|
-
* apps that make HTTP requests during initialization itself. Route guards
|
|
324
|
-
* (which use `registry.whenReady()`) are the correct place to enforce
|
|
325
|
-
* "client must be ready before user reaches this route".
|
|
326
|
-
*
|
|
327
|
-
* For NgModule-style apps using `HTTP_INTERCEPTORS`, use
|
|
328
|
-
* `provideTokenSetBearerInterceptor()` instead.
|
|
329
|
-
*
|
|
330
|
-
* @example
|
|
331
|
-
* ```ts
|
|
332
|
-
* import { provideHttpClient, withInterceptors } from "@angular/common/http";
|
|
333
|
-
* import { createTokenSetBearerInterceptor } from "@securitydept/token-set-context-client-angular";
|
|
334
|
-
*
|
|
335
|
-
* provideHttpClient(withInterceptors([
|
|
336
|
-
* createTokenSetBearerInterceptor(registry),
|
|
337
|
-
* ]));
|
|
338
|
-
* ```
|
|
49
|
+
* Declare a secured child route. Writes token-set registry requirement
|
|
50
|
+
* metadata only; enforcement is owned by a guarded
|
|
51
|
+
* {@link secureTokenSetRouteRoot} ancestor.
|
|
339
52
|
*/
|
|
53
|
+
declare function secureTokenSetRoute(path: string, security?: TokenSetSecureRouteSecurityOptions, routeOptions?: SecureRouteConfig): Route;
|
|
340
54
|
/**
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
* based on URL pattern matching.
|
|
344
|
-
*
|
|
345
|
-
* If no URL pattern matches, the unmatched-URL behaviour is governed by
|
|
346
|
-
* {@link BearerInterceptorOptions.strictUrlMatch}: the default falls back
|
|
347
|
-
* to `registry.accessToken()` (single-client convenience), while
|
|
348
|
-
* `strictUrlMatch: true` returns no token, ensuring bearer headers are
|
|
349
|
-
* never injected for URLs outside the registered patterns.
|
|
350
|
-
*
|
|
351
|
-
* ## Async client readiness
|
|
352
|
-
*
|
|
353
|
-
* The interceptor does **not** block or delay the HTTP request waiting for
|
|
354
|
-
* an async client to materialize. If a client is still initializing when the
|
|
355
|
-
* request fires, the request proceeds without an Authorization header.
|
|
356
|
-
*
|
|
357
|
-
* This is intentional: blocking HTTP for client initialization would deadlock
|
|
358
|
-
* apps that make HTTP requests during initialization itself. Route guards
|
|
359
|
-
* (which use `registry.whenReady()`) are the correct place to enforce
|
|
360
|
-
* "client must be ready before user reaches this route".
|
|
361
|
-
*
|
|
362
|
-
* For NgModule-style apps using `HTTP_INTERCEPTORS`, use
|
|
363
|
-
* `provideTokenSetBearerInterceptor()` instead.
|
|
364
|
-
*
|
|
365
|
-
* @example
|
|
366
|
-
* ```ts
|
|
367
|
-
* import { provideHttpClient, withInterceptors } from "@angular/common/http";
|
|
368
|
-
* import { createTokenSetBearerInterceptor } from "@securitydept/token-set-context-client-angular";
|
|
369
|
-
*
|
|
370
|
-
* provideHttpClient(withInterceptors([
|
|
371
|
-
* createTokenSetBearerInterceptor(registry, { strictUrlMatch: true }),
|
|
372
|
-
* ]));
|
|
373
|
-
* ```
|
|
55
|
+
* Declare a guarded token-set route root. Delegates guard assembly to the
|
|
56
|
+
* client-angular base helper and mounts registry-backed behaviour hooks.
|
|
374
57
|
*/
|
|
375
|
-
declare function
|
|
58
|
+
declare function secureTokenSetRouteRoot(path: string, security?: TokenSetSecureRouteRootSecurityOptions, routeOptions?: SecureRouteConfig): Route;
|
|
59
|
+
|
|
60
|
+
declare const TOKEN_SET_CLIENT_REGISTRY: InjectionToken<TokenSetClientRegistry<BaseOidcModeClient>>;
|
|
61
|
+
|
|
62
|
+
declare function provideTokenSetClientRegistry(options?: ProvideTokenSetClientRegistryOptions): Provider[];
|
|
63
|
+
|
|
64
|
+
interface TokenSetClientRegistryAuthorizationRequest {
|
|
376
65
|
url: string;
|
|
377
66
|
clone(update: {
|
|
378
67
|
setHeaders?: Record<string, string>;
|
|
379
68
|
}): unknown;
|
|
380
|
-
}, next: (req: unknown) => Observable<unknown>) => Observable<unknown>;
|
|
381
|
-
|
|
382
|
-
/**
|
|
383
|
-
* Angular-native service for handling OIDC redirect callbacks,
|
|
384
|
-
* with multi-client discrimination support.
|
|
385
|
-
*
|
|
386
|
-
* The post-authentication redirect URI is propagated automatically through
|
|
387
|
-
* the core client's pending state (set via `loginWithRedirect({ postAuthRedirectUri })`
|
|
388
|
-
* and recovered in `handleCallback()`). No manual URL storage is required.
|
|
389
|
-
*
|
|
390
|
-
* @example
|
|
391
|
-
* ```ts
|
|
392
|
-
* @Component({ ... })
|
|
393
|
-
* export class AuthCallbackComponent {
|
|
394
|
-
* private readonly callbackService = inject(CallbackResumeService);
|
|
395
|
-
* private readonly router = inject(Router);
|
|
396
|
-
*
|
|
397
|
-
* async ngOnInit() {
|
|
398
|
-
* const result = await this.callbackService.handleCallback(
|
|
399
|
-
* window.location.href,
|
|
400
|
-
* );
|
|
401
|
-
* this.router.navigateByUrl(result.resumeUrl, { replaceUrl: true });
|
|
402
|
-
* }
|
|
403
|
-
* }
|
|
404
|
-
* ```
|
|
405
|
-
*/
|
|
406
|
-
declare class CallbackResumeService {
|
|
407
|
-
private readonly registry;
|
|
408
|
-
private readonly destroyRef;
|
|
409
|
-
private readonly controller;
|
|
410
|
-
readonly state: WritableSignal<TokenSetCallbackResumeState>;
|
|
411
|
-
readonly state$: Observable<TokenSetCallbackResumeState>;
|
|
412
|
-
constructor();
|
|
413
|
-
/**
|
|
414
|
-
* Check whether a URL is an OIDC authorization callback for any registered
|
|
415
|
-
* client in this registry.
|
|
416
|
-
*
|
|
417
|
-
* This is a convenience wrapper over `clientKeyForCallback()`. Use it for
|
|
418
|
-
* programmatic early-exit guards (e.g. in a service constructor) before
|
|
419
|
-
* calling `handleCallback()`.
|
|
420
|
-
*
|
|
421
|
-
* @param url - The full URL to check (e.g. `window.location.href`).
|
|
422
|
-
* @returns `true` when the URL matches a registered callback path and
|
|
423
|
-
* contains an `code` or `error` query parameter.
|
|
424
|
-
*/
|
|
425
|
-
isCallback(url: string): boolean;
|
|
426
|
-
getState(): TokenSetCallbackResumeState;
|
|
427
|
-
resume(options: TokenSetCallbackResumeOptions): Promise<TokenSetCallbackResumeResult>;
|
|
428
|
-
resume(callbackUrl: string, explicitClientKey?: string): Promise<TokenSetCallbackResumeResult>;
|
|
429
|
-
/**
|
|
430
|
-
* Handle the OIDC callback, auto-detecting which client the callback
|
|
431
|
-
* belongs to via registered callback paths.
|
|
432
|
-
*
|
|
433
|
-
* The `resumeUrl` in the result is taken directly from the core client's
|
|
434
|
-
* pending state (`postAuthRedirectUri` set at `loginWithRedirect()` time),
|
|
435
|
-
* falling back to `"/"` when no redirect URI was recorded.
|
|
436
|
-
*
|
|
437
|
-
* @param callbackUrl - The full current URL (e.g. `window.location.href`).
|
|
438
|
-
* @param explicitClientKey - Optional: force-select a client key instead of
|
|
439
|
-
* auto-detecting from registered callback paths.
|
|
440
|
-
*/
|
|
441
|
-
handleCallback(callbackUrl: string, explicitClientKey?: string): Promise<{
|
|
442
|
-
clientKey: string;
|
|
443
|
-
snapshot: AuthSnapshot;
|
|
444
|
-
/** The URL to navigate to after a successful callback. */
|
|
445
|
-
resumeUrl: string;
|
|
446
|
-
}>;
|
|
447
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<CallbackResumeService, never>;
|
|
448
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<CallbackResumeService>;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/**
|
|
452
|
-
* A failing entry returned to `onUnauthenticated` when one or more clients
|
|
453
|
-
* could not be verified as authenticated.
|
|
454
|
-
*/
|
|
455
|
-
interface UnauthenticatedEntry {
|
|
456
|
-
/** The unauthenticated `TokenSetAuthService`. */
|
|
457
|
-
readonly service: TokenSetAuthService;
|
|
458
|
-
/** The client key for this service. */
|
|
459
|
-
readonly clientKey: string;
|
|
460
|
-
/** Full client metadata (urlPatterns, callbackPath, requirementKind, providerFamily). */
|
|
461
|
-
readonly meta: ClientMeta;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* Check whether the current URL is an OIDC authorization callback.
|
|
466
|
-
*/
|
|
467
|
-
declare function isOidcCallback(options: {
|
|
468
|
-
currentUrl: string;
|
|
469
|
-
callbackPath: string;
|
|
470
|
-
}): boolean;
|
|
471
|
-
|
|
472
|
-
/**
|
|
473
|
-
* Options for {@link provideTokenSetAuth}.
|
|
474
|
-
*/
|
|
475
|
-
interface ProvideTokenSetAuthOptions {
|
|
476
|
-
/**
|
|
477
|
-
* Adapter/host registration entries.
|
|
478
|
-
*
|
|
479
|
-
* Each entry must have a unique `key`. The entry itself owns how one client
|
|
480
|
-
* composes auth-context config and runtime capabilities; Angular DI here only
|
|
481
|
-
* owns host registration, readiness wiring, and lifecycle.
|
|
482
|
-
*/
|
|
483
|
-
clients: TokenSetClientEntry[];
|
|
484
|
-
/**
|
|
485
|
-
* When true (default), schedule `registry.idleWarmup()` during Angular
|
|
486
|
-
* environment initialization so `priority: "lazy"` clients get
|
|
487
|
-
* preloaded in the browser's idle callback.
|
|
488
|
-
*
|
|
489
|
-
* Disable for tests that want deterministic, manual materialization
|
|
490
|
-
* control.
|
|
491
|
-
*
|
|
492
|
-
* @default true
|
|
493
|
-
*/
|
|
494
|
-
idleWarmup?: boolean;
|
|
495
69
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
*
|
|
499
|
-
* Registers all services into Angular DI so adopters can directly inject
|
|
500
|
-
* `TokenSetAuthRegistry`, `CallbackResumeService`, and look up individual
|
|
501
|
-
* `TokenSetAuthService` instances by key.
|
|
502
|
-
*
|
|
503
|
-
* ## Async client initialization
|
|
504
|
-
*
|
|
505
|
-
* When a client's `clientFactory` returns a `Promise` (e.g. because it
|
|
506
|
-
* needs to fetch a config projection from a backend endpoint), the
|
|
507
|
-
* registry tracks its initialization state automatically. Guards and
|
|
508
|
-
* interceptors should use `registry.whenReady(key)` to await
|
|
509
|
-
* materialization before accessing the service.
|
|
510
|
-
*
|
|
511
|
-
* Adapter-managed browser clients also install token-set page-resume
|
|
512
|
-
* reconciliation by default during materialization. Set
|
|
513
|
-
* `resumeReconciliation: false` on an individual client entry only when the
|
|
514
|
-
* host intentionally owns equivalent browser lifecycle wiring.
|
|
515
|
-
*
|
|
516
|
-
* @example
|
|
517
|
-
* ```ts
|
|
518
|
-
* import { provideTokenSetAuth } from "@securitydept/token-set-context-client-angular";
|
|
519
|
-
* import { resolveConfigProjection, networkConfigSource, createFrontendOidcModeClient }
|
|
520
|
-
* from "@securitydept/token-set-context-client/frontend-oidc-mode";
|
|
521
|
-
*
|
|
522
|
-
* export const appConfig = {
|
|
523
|
-
* providers: [
|
|
524
|
-
* provideTokenSetAuth({
|
|
525
|
-
* clients: [
|
|
526
|
-
* {
|
|
527
|
-
* key: "main",
|
|
528
|
-
* // Async clientFactory: fetches config projection from backend
|
|
529
|
-
* clientFactory: async () => {
|
|
530
|
-
* const resolved = await resolveConfigProjection([
|
|
531
|
-
* networkConfigSource({
|
|
532
|
-
* apiEndpoint: "https://api.example.com/api",
|
|
533
|
-
* redirectUri: `${location.origin}/auth/callback`,
|
|
534
|
-
* }),
|
|
535
|
-
* ]);
|
|
536
|
-
* return createFrontendOidcModeClient(resolved.config, runtime);
|
|
537
|
-
* },
|
|
538
|
-
* urlPatterns: ["/api/"],
|
|
539
|
-
* callbackPath: "/auth/callback",
|
|
540
|
-
* // Optional: opt out only if the host already wires equivalent
|
|
541
|
-
* // resume reconciliation for this browser client.
|
|
542
|
-
* // resumeReconciliation: false,
|
|
543
|
-
* },
|
|
544
|
-
* ],
|
|
545
|
-
* }),
|
|
546
|
-
* ],
|
|
547
|
-
* };
|
|
548
|
-
* ```
|
|
549
|
-
*/
|
|
550
|
-
declare function provideTokenSetAuth(options: ProvideTokenSetAuthOptions): (Provider | EnvironmentProviders)[];
|
|
551
|
-
|
|
552
|
-
/**
|
|
553
|
-
* How to select a token-set client from the registry for a specific requirement.
|
|
554
|
-
*
|
|
555
|
-
* Choose exactly one:
|
|
556
|
-
* - `clientKey` — direct key lookup (explicit, single client)
|
|
557
|
-
* - `query` — composite filter query ({@link ClientQueryOptions})
|
|
558
|
-
*/
|
|
559
|
-
type TokenSetClientSelector = {
|
|
560
|
-
clientKey: string;
|
|
561
|
-
query?: never;
|
|
562
|
-
} | {
|
|
563
|
-
clientKey?: never;
|
|
564
|
-
query: ClientQueryOptions;
|
|
565
|
-
};
|
|
566
|
-
/**
|
|
567
|
-
* Runtime context passed to unauthenticated route handlers.
|
|
568
|
-
*
|
|
569
|
-
* `attemptedUrl` is the Angular Router target URL for the navigation being
|
|
570
|
-
* guarded. Use it as `postAuthRedirectUri`; do not read `Router.url` for this,
|
|
571
|
-
* because Angular still exposes the currently active URL while a guard is
|
|
572
|
-
* deciding whether the attempted navigation may proceed.
|
|
573
|
-
*/
|
|
574
|
-
interface TokenSetRouteUnauthenticatedContext {
|
|
575
|
-
readonly route: ActivatedRouteSnapshot;
|
|
576
|
-
readonly state: RouterStateSnapshot;
|
|
577
|
-
readonly attemptedUrl: string;
|
|
578
|
-
}
|
|
579
|
-
type TokenSetRouteUnauthenticatedHandler = (unauthenticated: ReadonlyArray<UnauthenticatedEntry>, requirement: AuthRequirement, context: TokenSetRouteUnauthenticatedContext) => boolean | string | UrlTree | Promise<boolean | string | UrlTree>;
|
|
580
|
-
/**
|
|
581
|
-
* Policy override for a specific requirement ID in
|
|
582
|
-
* {@link CreateTokenSetRouteAggregationGuardOptions.requirementPolicies}.
|
|
583
|
-
*
|
|
584
|
-
* Allows fine-grained control per declared requirement:
|
|
585
|
-
* - `selector` overrides the default kind→client registry lookup (use when
|
|
586
|
-
* you need a specific client key or a query instead of all clients of that kind).
|
|
587
|
-
* - `onUnauthenticated` overrides both `requirementHandlers[kind]` and
|
|
588
|
-
* `defaultOnUnauthenticated` for this exact requirement.
|
|
589
|
-
*
|
|
590
|
-
* @example
|
|
591
|
-
* ```ts
|
|
592
|
-
* createTokenSetRouteAggregationGuard({
|
|
593
|
-
* requirementPolicies: {
|
|
594
|
-
* "confluence-oidc": {
|
|
595
|
-
* selector: { clientKey: "confluence" },
|
|
596
|
-
* onUnauthenticated: (_failing, _req, context) => {
|
|
597
|
-
* inject(AuthService)
|
|
598
|
-
* .redirectToLogin("confluence", context.attemptedUrl)
|
|
599
|
-
* .subscribe();
|
|
600
|
-
* return false;
|
|
601
|
-
* },
|
|
602
|
-
* },
|
|
603
|
-
* "admin-oidc": {
|
|
604
|
-
* selector: { query: { providerFamily: "internal-sso" } },
|
|
605
|
-
* onUnauthenticated: () => "/admin/login",
|
|
606
|
-
* },
|
|
607
|
-
* },
|
|
608
|
-
* })
|
|
609
|
-
* ```
|
|
610
|
-
*/
|
|
611
|
-
interface TokenSetRequirementPolicy {
|
|
612
|
-
/**
|
|
613
|
-
* Override the default kind→client registry lookup for this requirement.
|
|
614
|
-
*
|
|
615
|
-
* When omitted, the guard resolves clients via
|
|
616
|
-
* `registry.clientKeyListForRequirement(requirement.kind)`.
|
|
617
|
-
*/
|
|
618
|
-
selector?: TokenSetClientSelector;
|
|
619
|
-
/**
|
|
620
|
-
* Handler called when this requirement is selected as pending by the planner.
|
|
621
|
-
*
|
|
622
|
-
* Takes precedence over `requirementHandlers[kind]` and
|
|
623
|
-
* `defaultOnUnauthenticated`.
|
|
624
|
-
*
|
|
625
|
-
* Return:
|
|
626
|
-
* - `true` — allow navigation
|
|
627
|
-
* - `false` — block navigation
|
|
628
|
-
* - `string` — redirect URL path
|
|
629
|
-
* - `UrlTree` — Angular router tree
|
|
630
|
-
*/
|
|
631
|
-
onUnauthenticated: TokenSetRouteUnauthenticatedHandler;
|
|
632
|
-
}
|
|
633
|
-
/**
|
|
634
|
-
* Options for {@link createTokenSetRouteAggregationGuard}.
|
|
635
|
-
*/
|
|
636
|
-
interface CreateTokenSetRouteAggregationGuardOptions {
|
|
637
|
-
/**
|
|
638
|
-
* Per-requirement-id policies.
|
|
639
|
-
*
|
|
640
|
-
* Keys are `AuthRequirement.id` strings (not kind). Policies declared here
|
|
641
|
-
* take precedence over {@link requirementHandlers} and
|
|
642
|
-
* {@link defaultOnUnauthenticated}.
|
|
643
|
-
*
|
|
644
|
-
* Use this for fine-grained control:
|
|
645
|
-
* - override client selection (specific key or composite query)
|
|
646
|
-
* - per-requirement redirect behaviour
|
|
647
|
-
* - multi-client / providerFamily selection per requirement
|
|
648
|
-
*
|
|
649
|
-
* @example
|
|
650
|
-
* ```ts
|
|
651
|
-
* createTokenSetRouteAggregationGuard({
|
|
652
|
-
* requirementPolicies: {
|
|
653
|
-
* "confluence-oidc": {
|
|
654
|
-
* selector: { clientKey: "confluence" },
|
|
655
|
-
* onUnauthenticated: () => "/auth/confluence",
|
|
656
|
-
* },
|
|
657
|
-
* "admin-oidc": {
|
|
658
|
-
* selector: { query: { providerFamily: "internal-sso" } },
|
|
659
|
-
* onUnauthenticated: () => "/auth/admin",
|
|
660
|
-
* },
|
|
661
|
-
* },
|
|
662
|
-
* })
|
|
663
|
-
* ```
|
|
664
|
-
*/
|
|
665
|
-
requirementPolicies?: Record<string, TokenSetRequirementPolicy>;
|
|
666
|
-
/**
|
|
667
|
-
* Per-requirement-kind handlers.
|
|
668
|
-
*
|
|
669
|
-
* When the planner selects a pending requirement whose `kind` maps to an
|
|
670
|
-
* entry here (and no `requirementPolicies[id]` is set), that handler is
|
|
671
|
-
* called instead of `defaultOnUnauthenticated`.
|
|
672
|
-
*
|
|
673
|
-
* Keys are `AuthRequirement.kind` strings.
|
|
674
|
-
*
|
|
675
|
-
* @example
|
|
676
|
-
* ```ts
|
|
677
|
-
* createTokenSetRouteAggregationGuard({
|
|
678
|
-
* requirementHandlers: {
|
|
679
|
-
* frontend_oidc: (failing, _req, context) => {
|
|
680
|
-
* inject(AuthService)
|
|
681
|
-
* .redirectToLogin(failing[0].clientKey, context.attemptedUrl)
|
|
682
|
-
* .subscribe();
|
|
683
|
-
* return false;
|
|
684
|
-
* },
|
|
685
|
-
* },
|
|
686
|
-
* })
|
|
687
|
-
* ```
|
|
688
|
-
*/
|
|
689
|
-
requirementHandlers?: Record<string, TokenSetRouteUnauthenticatedHandler>;
|
|
690
|
-
/**
|
|
691
|
-
* Fallback handler used when no `requirementPolicies[id]` or
|
|
692
|
-
* `requirementHandlers[kind]` is found for the pending requirement.
|
|
693
|
-
*/
|
|
694
|
-
defaultOnUnauthenticated?: TokenSetRouteUnauthenticatedHandler;
|
|
695
|
-
/**
|
|
696
|
-
* Custom route data key for reading requirements from route segments.
|
|
697
|
-
* @default "authRequirements"
|
|
698
|
-
*/
|
|
699
|
-
requirementsKey?: string;
|
|
700
|
-
/**
|
|
701
|
-
* Inline planner-host instance. If provided, used instead of injecting
|
|
702
|
-
* `AUTH_PLANNER_HOST` from Angular DI.
|
|
703
|
-
*/
|
|
704
|
-
plannerHost?: PlannerHost;
|
|
705
|
-
/**
|
|
706
|
-
* Resolve the planner-host for the current target route chain.
|
|
707
|
-
*
|
|
708
|
-
* Use this when planner-host selection depends on route metadata or other
|
|
709
|
-
* route-tree state. Takes precedence over `plannerHost` and DI lookup.
|
|
710
|
-
*/
|
|
711
|
-
plannerHostResolver?: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => PlannerHost | undefined;
|
|
712
|
-
}
|
|
713
|
-
/**
|
|
714
|
-
* Create an Angular `CanActivateFn` that performs full-route requirement
|
|
715
|
-
* aggregation and single-pass planner evaluation.
|
|
716
|
-
*
|
|
717
|
-
* **Canonical Angular Router auth pattern** (route-metadata driven):
|
|
718
|
-
* 1. Requirements are declared in route `data` using `withRouteRequirements()`.
|
|
719
|
-
* 2. When the guard runs, it walks `route.pathFromRoot` to collect ALL
|
|
720
|
-
* requirements from every ancestor segment in a single pass.
|
|
721
|
-
* 3. Each requirement's `kind` is mapped to one or more registry clients,
|
|
722
|
-
* unless overridden by a `requirementPolicies[id].selector`.
|
|
723
|
-
* 4. The complete candidate set is handed to the `PlannerHost` for a
|
|
724
|
-
* single `evaluate()` call — the planner selects the first unresolved
|
|
725
|
-
* requirement and calls the matching handler.
|
|
726
|
-
*
|
|
727
|
-
* **Handler resolution order** (most specific wins):
|
|
728
|
-
* 1. `requirementPolicies[requirement.id].onUnauthenticated`
|
|
729
|
-
* 2. `requirementHandlers[requirement.kind]`
|
|
730
|
-
* 3. `defaultOnUnauthenticated`
|
|
731
|
-
* 4. Block navigation (`false`) if none of the above is provided.
|
|
732
|
-
*
|
|
733
|
-
* **Client resolution order** for a requirement:
|
|
734
|
-
* 1. `requirementPolicies[requirement.id].selector.clientKey` — single explicit key
|
|
735
|
-
* 2. `requirementPolicies[requirement.id].selector.query` — composite query
|
|
736
|
-
* 3. `registry.clientKeyListForRequirement(requirement.kind)` — default mapping
|
|
737
|
-
*
|
|
738
|
-
* This model enables:
|
|
739
|
-
* - One-pass requirement collection (no per-segment DI scope accumulation)
|
|
740
|
-
* - One-call planner evaluation (chooser sees the full set at once)
|
|
741
|
-
* - One redirect decision (no per-segment guard coordination needed)
|
|
742
|
-
* - Fine-grained per-requirement policy via `requirementPolicies`
|
|
743
|
-
*
|
|
744
|
-
* @example
|
|
745
|
-
* ```ts
|
|
746
|
-
* // routes.ts — declare requirements in route data
|
|
747
|
-
* import { createBrowserPageClientEnvironment } from "@securitydept/client/web";
|
|
748
|
-
* import {
|
|
749
|
-
* providePageClientEnvironment,
|
|
750
|
-
* withRouteRequirements,
|
|
751
|
-
* } from "@securitydept/client-angular";
|
|
752
|
-
* import {
|
|
753
|
-
* createTokenSetOidcLoginRedirectHandler,
|
|
754
|
-
* createTokenSetRouteAggregationGuard,
|
|
755
|
-
* } from "@securitydept/token-set-context-client-angular";
|
|
756
|
-
*
|
|
757
|
-
* export const appConfig = {
|
|
758
|
-
* providers: [
|
|
759
|
-
* providePageClientEnvironment({
|
|
760
|
-
* environment: createBrowserPageClientEnvironment(),
|
|
761
|
-
* }),
|
|
762
|
-
* ],
|
|
763
|
-
* };
|
|
764
|
-
*
|
|
765
|
-
* // Simple — kind-level handler
|
|
766
|
-
* const guard = createTokenSetRouteAggregationGuard({
|
|
767
|
-
* requirementHandlers: {
|
|
768
|
-
* frontend_oidc: createTokenSetOidcLoginRedirectHandler({
|
|
769
|
-
* clientKey: "confluence",
|
|
770
|
-
* }),
|
|
771
|
-
* },
|
|
772
|
-
* });
|
|
773
|
-
*
|
|
774
|
-
* // Fine-grained — per-requirement policy
|
|
775
|
-
* const guard = createTokenSetRouteAggregationGuard({
|
|
776
|
-
* requirementPolicies: {
|
|
777
|
-
* "confluence-oidc": {
|
|
778
|
-
* selector: { clientKey: "confluence" },
|
|
779
|
-
* onUnauthenticated: () => "/auth/confluence",
|
|
780
|
-
* },
|
|
781
|
-
* "admin-oidc": {
|
|
782
|
-
* selector: { query: { providerFamily: "internal-sso" } },
|
|
783
|
-
* onUnauthenticated: (failing) => "/auth/admin",
|
|
784
|
-
* },
|
|
785
|
-
* },
|
|
786
|
-
* });
|
|
787
|
-
*
|
|
788
|
-
* export const routes: Routes = [
|
|
789
|
-
* {
|
|
790
|
-
* path: "",
|
|
791
|
-
* data: withRouteRequirements([{ id: "session", kind: "session" }]),
|
|
792
|
-
* children: [
|
|
793
|
-
* {
|
|
794
|
-
* path: "confluence",
|
|
795
|
-
* data: withRouteRequirements([{ id: "confluence-oidc", kind: "frontend_oidc" }]),
|
|
796
|
-
* canActivate: [guard],
|
|
797
|
-
* },
|
|
798
|
-
* ],
|
|
799
|
-
* },
|
|
800
|
-
* ];
|
|
801
|
-
* ```
|
|
802
|
-
*/
|
|
803
|
-
declare function createTokenSetRouteAggregationGuard(options?: CreateTokenSetRouteAggregationGuardOptions): CanActivateFn;
|
|
804
|
-
/**
|
|
805
|
-
* Build an Angular route-security handler that starts OIDC redirect login and
|
|
806
|
-
* records the attempted navigation URL as `postAuthRedirectUri`.
|
|
807
|
-
*
|
|
808
|
-
* Use this instead of reading `Router.url` inside a guard handler. During guard
|
|
809
|
-
* execution Angular has not committed the attempted navigation yet, so
|
|
810
|
-
* `Router.url` still points at the previously active page.
|
|
811
|
-
*
|
|
812
|
-
* After the browser redirect is started, the returned guard result intentionally
|
|
813
|
-
* never settles. That keeps Angular from finalizing the rejected in-app
|
|
814
|
-
* navigation while the page is already leaving for an external IdP.
|
|
815
|
-
*/
|
|
816
|
-
interface CreateTokenSetOidcLoginRedirectHandlerOptions {
|
|
70
|
+
type TokenSetClientRegistryAuthorizationForRequest = (registry: TokenSetClientRegistry<BaseOidcModeClient>, request: TokenSetClientRegistryAuthorizationRequest) => Promise<string | null | undefined> | string | null | undefined;
|
|
71
|
+
interface TokenSetClientRegistryAuthorizationInterceptorProviderOptions {
|
|
817
72
|
/**
|
|
818
|
-
*
|
|
819
|
-
* used, which is the common one-client-per-requirement case.
|
|
820
|
-
*/
|
|
821
|
-
clientKey?: string;
|
|
822
|
-
/**
|
|
823
|
-
* Optional stable page environment override.
|
|
73
|
+
* Resolves the Authorization header value for a request.
|
|
824
74
|
*
|
|
825
|
-
* The
|
|
826
|
-
*
|
|
827
|
-
* composition root with `providePageClientEnvironment(...)`, then let the
|
|
828
|
-
* redirect helper resolve it from Angular DI. Use this override only when a
|
|
829
|
-
* specific handler intentionally needs a different stable page environment
|
|
830
|
-
* source.
|
|
831
|
-
*/
|
|
832
|
-
environment?: PageClientEnvironmentSource;
|
|
833
|
-
/**
|
|
834
|
-
* Fallback used only when Angular does not provide a target URL.
|
|
835
|
-
* @default "/"
|
|
75
|
+
* The default implementation selects a registered client by request URL,
|
|
76
|
+
* initializes that client, and reads its replayed authorization header.
|
|
836
77
|
*/
|
|
837
|
-
|
|
78
|
+
authorizationForRequest?: TokenSetClientRegistryAuthorizationForRequest;
|
|
838
79
|
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
/**
|
|
842
|
-
* Route data key for choosing a planner-host registered at the route root.
|
|
843
|
-
*/
|
|
844
|
-
declare const TOKEN_SET_ROUTE_PLANNER_HOST_KEY_DATA_KEY = "tokenSetPlannerHostKey";
|
|
845
|
-
/**
|
|
846
|
-
* Serializable route-level security declaration.
|
|
847
|
-
*
|
|
848
|
-
* This object is safe to embed in Angular route metadata. Non-serializable
|
|
849
|
-
* runtime policy (planner host instances, callbacks, chooser implementations)
|
|
850
|
-
* belongs in {@link SecureRouteRootSecurityOptions}.
|
|
851
|
-
*/
|
|
852
|
-
interface SecureRouteSecurityOptions {
|
|
853
|
-
/**
|
|
854
|
-
* Requirements declared at this route segment.
|
|
855
|
-
* @default []
|
|
856
|
-
*/
|
|
857
|
-
requirements?: AuthRequirement[];
|
|
858
|
-
/**
|
|
859
|
-
* How this segment composes with ancestor route requirements.
|
|
860
|
-
* @default merge
|
|
861
|
-
*/
|
|
862
|
-
composition?: RequirementsClientSetComposition;
|
|
863
|
-
/**
|
|
864
|
-
* Serializable lookup key for a planner-host provided by the root route.
|
|
865
|
-
*
|
|
866
|
-
* The nearest declared key on the active route chain wins.
|
|
867
|
-
*/
|
|
868
|
-
plannerHostKey?: string;
|
|
80
|
+
interface TokenSetClientRegistryAuthorizationInterceptorOptions extends TokenSetClientRegistryAuthorizationInterceptorProviderOptions {
|
|
81
|
+
registry?: TokenSetClientRegistry<BaseOidcModeClient>;
|
|
869
82
|
}
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
interface SecureRouteRootSecurityOptions extends SecureRouteSecurityOptions, Omit<CreateTokenSetRouteAggregationGuardOptions, "plannerHost" | "plannerHostResolver"> {
|
|
878
|
-
/**
|
|
879
|
-
* Named planner-host instances available to the secured route tree.
|
|
880
|
-
*/
|
|
881
|
-
plannerHosts?: Record<string, PlannerHost>;
|
|
882
|
-
/**
|
|
883
|
-
* Fallback planner-host key when no route segment declares one.
|
|
884
|
-
*/
|
|
885
|
-
defaultPlannerHostKey?: string;
|
|
83
|
+
declare const TOKEN_SET_CLIENT_REGISTRY_AUTHORIZATION_FOR_REQUEST: InjectionToken<TokenSetClientRegistryAuthorizationForRequest>;
|
|
84
|
+
declare class TokenSetClientRegistryAuthorizationInterceptor implements HttpInterceptor {
|
|
85
|
+
private readonly registry;
|
|
86
|
+
private readonly authorizationForRequest;
|
|
87
|
+
intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>>;
|
|
88
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<TokenSetClientRegistryAuthorizationInterceptor, never>;
|
|
89
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<TokenSetClientRegistryAuthorizationInterceptor>;
|
|
886
90
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
/**
|
|
891
|
-
* Build a secured child route declaration.
|
|
892
|
-
*
|
|
893
|
-
* The returned route contains only serializable metadata:
|
|
894
|
-
* requirements, composition strategy, planner-host lookup key, and any extra
|
|
895
|
-
* route data the caller provides.
|
|
896
|
-
*/
|
|
897
|
-
declare function secureRoute(path: string, securityOptions?: SecureRouteSecurityOptions, routeOptions?: SecureRouteOptions): Route;
|
|
898
|
-
/**
|
|
899
|
-
* Build a secured route-tree root.
|
|
900
|
-
*
|
|
901
|
-
* This is the canonical Angular adopter entry for token-set route security:
|
|
902
|
-
* root-level runtime policy stays here, child routes use {@link secureRoute}
|
|
903
|
-
* for serializable declarations only.
|
|
904
|
-
*/
|
|
905
|
-
declare function secureRouteRoot(path: string, securityOptions?: SecureRouteRootSecurityOptions, routeOptions?: SecureRouteOptions): Route;
|
|
906
|
-
/**
|
|
907
|
-
* Alias with a token-set-specific name for callers who prefer explicit imports.
|
|
908
|
-
*/
|
|
909
|
-
declare const secureTokenSetRoute: typeof secureRoute;
|
|
910
|
-
/**
|
|
911
|
-
* Alias with a token-set-specific name for callers who prefer explicit imports.
|
|
912
|
-
*/
|
|
913
|
-
declare const secureTokenSetRouteRoot: typeof secureRouteRoot;
|
|
91
|
+
declare function provideTokenSetClientRegistryAuthorizationInterceptor(options?: TokenSetClientRegistryAuthorizationInterceptorProviderOptions): Provider[];
|
|
92
|
+
declare function createTokenSetClientRegistryAuthorizationInterceptor(options?: TokenSetClientRegistryAuthorizationInterceptorOptions): HttpInterceptorFn;
|
|
93
|
+
declare function defaultTokenSetClientRegistryAuthorizationForRequest(registry: TokenSetClientRegistry<BaseOidcModeClient>, request: TokenSetClientRegistryAuthorizationRequest): Promise<string | null>;
|
|
914
94
|
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
* ];
|
|
931
|
-
* ```
|
|
932
|
-
*
|
|
933
|
-
* Host policy can override `fallbackUrl`, `errorRedirectUrl`, and `onError`
|
|
934
|
-
* through `TOKEN_SET_CALLBACK_COMPONENT_OPTIONS`. For fully custom UI or
|
|
935
|
-
* orchestration, build your own component around `CallbackResumeService`.
|
|
936
|
-
*/
|
|
937
|
-
declare class TokenSetCallbackComponent implements OnInit {
|
|
938
|
-
private readonly callbackService;
|
|
939
|
-
private readonly router;
|
|
940
|
-
private readonly getCurrentUrl;
|
|
941
|
-
private readonly options;
|
|
942
|
-
ngOnInit(): void;
|
|
943
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<TokenSetCallbackComponent, never>;
|
|
944
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<TokenSetCallbackComponent, "token-set-callback", never, {}, {}, never, never, true, never>;
|
|
95
|
+
type BackendCallbackResult = OidcModeCallbackHandlingResult<TokenSetAuthSnapshot>;
|
|
96
|
+
declare class TokenSetBackendCallbackComponent {
|
|
97
|
+
readonly clientQuery: i0.InputSignal<TokenSetCallbackClientQuery | undefined>;
|
|
98
|
+
readonly autoInitialize: i0.InputSignal<boolean>;
|
|
99
|
+
private readonly environment;
|
|
100
|
+
private readonly registry;
|
|
101
|
+
private readonly destroyRef;
|
|
102
|
+
private readonly selectionSource;
|
|
103
|
+
private readonly selectionSignal;
|
|
104
|
+
readonly selection: Signal<TokenSetCallbackClientSelectionSnapshot<BackendOidcModeClient>>;
|
|
105
|
+
readonly resource: _securitydept_client.WithInteropObservableTraitCompat<_securitydept_client.ResourceTrait<BackendCallbackResult>, ResourceSnapshot<BackendCallbackResult>>;
|
|
106
|
+
readonly state: Signal<ResourceSnapshot<BackendCallbackResult>>;
|
|
107
|
+
constructor();
|
|
108
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<TokenSetBackendCallbackComponent, never>;
|
|
109
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<TokenSetBackendCallbackComponent, "sd-token-set-backend-callback", ["sdTokenSetBackendCallback"], { "clientQuery": { "alias": "clientQuery"; "required": false; "isSignal": true; }; "autoInitialize": { "alias": "autoInitialize"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
945
110
|
}
|
|
946
111
|
|
|
947
|
-
|
|
948
|
-
declare
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
112
|
+
type FrontendCallbackResult = OidcModeCallbackHandlingResult<FrontendOidcModeCallbackResult>;
|
|
113
|
+
declare class TokenSetFrontendCallbackComponent {
|
|
114
|
+
readonly clientQuery: i0.InputSignal<TokenSetCallbackClientQuery | undefined>;
|
|
115
|
+
readonly autoInitialize: i0.InputSignal<boolean>;
|
|
116
|
+
private readonly environment;
|
|
117
|
+
private readonly registry;
|
|
118
|
+
private readonly destroyRef;
|
|
119
|
+
private readonly selectionSource;
|
|
120
|
+
private readonly selectionSignal;
|
|
121
|
+
readonly selection: Signal<TokenSetCallbackClientSelectionSnapshot<FrontendOidcModeClient>>;
|
|
122
|
+
readonly resource: _securitydept_client.WithInteropObservableTraitCompat<_securitydept_client.ResourceTrait<FrontendCallbackResult>, ResourceSnapshot<FrontendCallbackResult>>;
|
|
123
|
+
readonly state: Signal<ResourceSnapshot<FrontendCallbackResult>>;
|
|
124
|
+
constructor();
|
|
125
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<TokenSetFrontendCallbackComponent, never>;
|
|
126
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<TokenSetFrontendCallbackComponent, "sd-token-set-frontend-callback", ["sdTokenSetFrontendCallback"], { "clientQuery": { "alias": "clientQuery"; "required": false; "isSignal": true; }; "autoInitialize": { "alias": "autoInitialize"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
954
127
|
}
|
|
955
|
-
/**
|
|
956
|
-
* InjectionToken for the current callback URL used by the drop-in callback component.
|
|
957
|
-
*
|
|
958
|
-
* Defaults to `window.location.href` in real page hosts and `undefined` in
|
|
959
|
-
* non-page or test hosts unless explicitly overridden.
|
|
960
|
-
*/
|
|
961
|
-
declare const TOKEN_SET_CALLBACK_CURRENT_URL: InjectionToken<TokenSetCallbackUrlSource>;
|
|
962
|
-
declare const TOKEN_SET_CALLBACK_COMPONENT_OPTIONS: InjectionToken<TokenSetCallbackComponentOptions>;
|
|
963
128
|
|
|
964
|
-
export {
|
|
965
|
-
export type {
|
|
129
|
+
export { TOKEN_SET_CLIENT_REGISTRY, TOKEN_SET_CLIENT_REGISTRY_AUTHORIZATION_FOR_REQUEST, TokenSetBackendCallbackComponent, TokenSetClientRegistryAuthorizationInterceptor, TokenSetFrontendCallbackComponent, createTokenSetCanActivate, createTokenSetCanActivateChild, createTokenSetClientRegistryAuthorizationInterceptor, defaultTokenSetClientRegistryAuthorizationForRequest, provideTokenSetClientRegistry, provideTokenSetClientRegistryAuthorizationInterceptor, provideTokenSetRequirementPlannerHost, secureTokenSetRoute, secureTokenSetRouteRoot };
|
|
130
|
+
export type { ProvideTokenSetRequirementPlannerHostOptions, TokenSetAngularGuardOptions, TokenSetClientRegistryAuthorizationForRequest, TokenSetClientRegistryAuthorizationInterceptorOptions, TokenSetClientRegistryAuthorizationInterceptorProviderOptions, TokenSetClientRegistryAuthorizationRequest, TokenSetSecureRouteRootSecurityOptions, TokenSetSecureRouteSecurityOptions };
|
|
966
131
|
//# sourceMappingURL=securitydept-token-set-context-client-angular.d.ts.map
|