@angular-helpers/security 21.3.0 → 21.4.1

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 CHANGED
@@ -76,6 +76,19 @@ Security package for Angular applications that prevents common attacks like ReDo
76
76
  - **Verified auto-clear**: reads back the clipboard before clearing to avoid clobbering unrelated content.
77
77
  - **Password-manager semantics**: default 15-second clear, configurable.
78
78
 
79
+ ### **Session Inactivity Monitor**
80
+
81
+ - **NgZone-optimized**: DOM events tracked outside Angular change detection.
82
+ - **Security interop**: Can automatically clear SecureStorage and SensitiveClipboard upon timeout.
83
+ - **Warning states**: Configurable thresholds to warn users before expiration.
84
+
85
+ ### **Secure Cross-Window Messaging**
86
+
87
+ - **HMAC-SHA-256 signatures**: Every message is signed; tampered payloads are discarded.
88
+ - **Origin whitelist**: Messages from non-allowed origins are rejected before any crypto work.
89
+ - **Anti-replay protection**: Envelope includes `timestamp + nonce`; messages older than 30s are discarded.
90
+ - **SSR-safe**: No-op on the server — no `window` access.
91
+
79
92
  ### **Builder Pattern**
80
93
 
81
94
  - **Fluent API**: Intuitively build regular expressions.
@@ -568,6 +581,87 @@ export class ApiKeyPanel {
568
581
  The service reads the clipboard before clearing and skips the clear if the content no longer
569
582
  matches what was copied — so third-party copies by the user are never overwritten.
570
583
 
584
+ ### **SessionIdleService**
585
+
586
+ ```typescript
587
+ import { SessionIdleService } from '@angular-helpers/security';
588
+
589
+ export class AppComponent {
590
+ private sessionIdle = inject(SessionIdleService);
591
+
592
+ ngOnInit() {
593
+ this.sessionIdle.start({
594
+ timeoutMs: 15 * 60 * 1000, // 15 minutes
595
+ warningThresholdMs: 60 * 1000, // 1 minute warning
596
+ autoClearStorage: true,
597
+ autoClearClipboard: true,
598
+ });
599
+
600
+ // React to states
601
+ effect(() => {
602
+ if (this.sessionIdle.isWarning()) {
603
+ console.warn(`Session will expire in ${this.sessionIdle.timeRemaining()}ms`);
604
+ }
605
+ });
606
+
607
+ // React to timeout
608
+ this.sessionIdle.onTimeout.subscribe(() => {
609
+ this.authService.logout();
610
+ });
611
+ }
612
+ }
613
+ ```
614
+
615
+ The service tracks DOM events (`mousemove`, `keydown`, etc.) outside the Angular Zone to prevent change detection spam. It can automatically clear `SecureStorageService` and `SensitiveClipboardService` when the session times out.
616
+
617
+ ### **SecureMessageService**
618
+
619
+ ```typescript
620
+ import { SecureMessageService, provideSecureMessage } from '@angular-helpers/security';
621
+
622
+ // app.config.ts
623
+ bootstrapApplication(AppComponent, {
624
+ providers: [provideSecureMessage()],
625
+ });
626
+
627
+ // parent-app.component.ts
628
+ export class ParentComponent {
629
+ private channel = inject(SecureMessageService);
630
+
631
+ async ngOnInit() {
632
+ // 1. Generate a shared key (transport it to the iframe via a secure channel)
633
+ const key = await this.channel.generateChannelKey();
634
+
635
+ // 2. Configure: only accept messages from the iframe origin
636
+ this.channel.configure({
637
+ allowedOrigins: ['https://child-app.example.com'],
638
+ signingKey: key,
639
+ });
640
+
641
+ // 3. React to incoming messages
642
+ this.channel.messages$<{ type: string; payload: unknown }>().subscribe(({ data, origin }) => {
643
+ console.log('Verified message from', origin, data);
644
+ });
645
+
646
+ // 4. Or use the Signal for reactive UI
647
+ effect(() => {
648
+ const msg = this.channel.lastMessage()();
649
+ if (msg) console.log('Last message:', msg.data);
650
+ });
651
+ }
652
+
653
+ async sendToChild(iframe: HTMLIFrameElement) {
654
+ await this.channel.send(
655
+ iframe.contentWindow!,
656
+ { type: 'INIT', payload: { userId: 42 } },
657
+ 'https://child-app.example.com', // targetOrigin — never '*'
658
+ );
659
+ }
660
+ }
661
+ ```
662
+
663
+ > **Key exchange**: `SecureMessageService` does not perform automatic key negotiation — transport the `CryptoKey` to the other context via a secure out-of-band channel (e.g., derive it from a shared secret using `WebCryptoService.generateHmacKey()` seeded by a passphrase). Once both sides share the key, all message integrity is handled automatically.
664
+
571
665
  ## 🔧 Advanced Configuration
572
666
 
573
667
  ### **Security Options**
@@ -1,7 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, DestroyRef, Injectable, PLATFORM_ID, InjectionToken, signal, computed, makeEnvironmentProviders } from '@angular/core';
3
- import { isPlatformBrowser } from '@angular/common';
4
- import { Observable } from 'rxjs';
2
+ import { inject, DestroyRef, Injectable, PLATFORM_ID, InjectionToken, signal, computed, NgZone, Injector, makeEnvironmentProviders } from '@angular/core';
3
+ import { isPlatformBrowser, DOCUMENT } from '@angular/common';
4
+ import { Observable, Subject, fromEvent, merge } from 'rxjs';
5
+ import { throttleTime } from 'rxjs/operators';
5
6
 
6
7
  /**
7
8
  * Security service for regular expressions that prevents ReDoS
@@ -1349,6 +1350,20 @@ class SensitiveClipboardService {
1349
1350
  return 'read-denied';
1350
1351
  }
1351
1352
  }
1353
+ /**
1354
+ * Forcefully clears the clipboard unconditionally.
1355
+ */
1356
+ async clear() {
1357
+ if (!this.isSupported())
1358
+ return;
1359
+ this.cancelPendingClear();
1360
+ try {
1361
+ await navigator.clipboard.writeText('');
1362
+ }
1363
+ catch {
1364
+ // ignore
1365
+ }
1366
+ }
1352
1367
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: SensitiveClipboardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1353
1368
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: SensitiveClipboardService });
1354
1369
  }
@@ -1716,6 +1731,221 @@ function withCsrfHeader(options = {}) {
1716
1731
  };
1717
1732
  }
1718
1733
 
1734
+ const DEFAULT_EVENTS = ['mousemove', 'keydown', 'mousedown', 'touchstart', 'scroll'];
1735
+ class SessionIdleService {
1736
+ ngZone = inject(NgZone);
1737
+ document = inject(DOCUMENT);
1738
+ injector = inject(Injector);
1739
+ destroyRef = inject(DestroyRef);
1740
+ _isIdle = signal(false, ...(ngDevMode ? [{ debugName: "_isIdle" }] : /* istanbul ignore next */ []));
1741
+ _isWarning = signal(false, ...(ngDevMode ? [{ debugName: "_isWarning" }] : /* istanbul ignore next */ []));
1742
+ _timeRemaining = signal(null, ...(ngDevMode ? [{ debugName: "_timeRemaining" }] : /* istanbul ignore next */ []));
1743
+ _timeoutSubject = new Subject();
1744
+ isIdle = this._isIdle.asReadonly();
1745
+ isWarning = this._isWarning.asReadonly();
1746
+ timeRemaining = this._timeRemaining.asReadonly();
1747
+ onTimeout = this._timeoutSubject.asObservable();
1748
+ config = null;
1749
+ lastActivityTime = 0;
1750
+ timerInterval = null;
1751
+ eventSubscription;
1752
+ constructor() {
1753
+ this.destroyRef.onDestroy(() => this.stop());
1754
+ }
1755
+ start(config) {
1756
+ this.stop();
1757
+ this.config = config;
1758
+ this._isIdle.set(false);
1759
+ this._isWarning.set(false);
1760
+ this._timeRemaining.set(config.timeoutMs);
1761
+ this.lastActivityTime = Date.now();
1762
+ const eventsToTrack = config.events || DEFAULT_EVENTS;
1763
+ this.ngZone.runOutsideAngular(() => {
1764
+ const observables = eventsToTrack.map((ev) => fromEvent(this.document, ev));
1765
+ this.eventSubscription = merge(...observables)
1766
+ .pipe(throttleTime(500))
1767
+ .subscribe(() => {
1768
+ this.lastActivityTime = Date.now();
1769
+ });
1770
+ this.timerInterval = setInterval(() => this.checkIdle(), 1000);
1771
+ });
1772
+ }
1773
+ stop() {
1774
+ if (this.timerInterval) {
1775
+ clearInterval(this.timerInterval);
1776
+ this.timerInterval = null;
1777
+ }
1778
+ if (this.eventSubscription) {
1779
+ this.eventSubscription.unsubscribe();
1780
+ this.eventSubscription = undefined;
1781
+ }
1782
+ this.config = null;
1783
+ this._timeRemaining.set(null);
1784
+ this._isIdle.set(false);
1785
+ this._isWarning.set(false);
1786
+ }
1787
+ reset() {
1788
+ if (!this.config)
1789
+ return;
1790
+ this.lastActivityTime = Date.now();
1791
+ this._timeRemaining.set(this.config.timeoutMs);
1792
+ this._isIdle.set(false);
1793
+ this._isWarning.set(false);
1794
+ }
1795
+ checkIdle() {
1796
+ if (!this.config || this._isIdle())
1797
+ return;
1798
+ const elapsed = Date.now() - this.lastActivityTime;
1799
+ const remaining = Math.max(0, this.config.timeoutMs - elapsed);
1800
+ if (remaining === 0) {
1801
+ this.triggerTimeout();
1802
+ }
1803
+ else {
1804
+ const warningThreshold = this.config.warningThresholdMs || 0;
1805
+ const shouldBeWarning = remaining <= warningThreshold;
1806
+ this.ngZone.run(() => {
1807
+ this._timeRemaining.set(remaining);
1808
+ if (this._isWarning() !== shouldBeWarning) {
1809
+ this._isWarning.set(shouldBeWarning);
1810
+ }
1811
+ });
1812
+ }
1813
+ }
1814
+ triggerTimeout() {
1815
+ const config = this.config;
1816
+ this.stop();
1817
+ // Restore config temporarily to check for autoClear flags
1818
+ this.config = config;
1819
+ this.ngZone.run(() => {
1820
+ this._timeRemaining.set(0);
1821
+ this._isIdle.set(true);
1822
+ this._timeoutSubject.next();
1823
+ if (this.config?.autoClearStorage) {
1824
+ const storage = this.injector.get(SecureStorageService, null);
1825
+ if (storage)
1826
+ storage.clear();
1827
+ }
1828
+ if (this.config?.autoClearClipboard) {
1829
+ const clipboard = this.injector.get(SensitiveClipboardService, null);
1830
+ if (clipboard)
1831
+ clipboard.clear();
1832
+ }
1833
+ this.config = null;
1834
+ });
1835
+ }
1836
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: SessionIdleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1837
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: SessionIdleService, providedIn: 'root' });
1838
+ }
1839
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: SessionIdleService, decorators: [{
1840
+ type: Injectable,
1841
+ args: [{
1842
+ providedIn: 'root',
1843
+ }]
1844
+ }], ctorParameters: () => [] });
1845
+
1846
+ const REPLAY_WINDOW_MS = 30_000;
1847
+ class SecureMessageService {
1848
+ ngZone = inject(NgZone);
1849
+ platformId = inject(PLATFORM_ID);
1850
+ document = inject(DOCUMENT);
1851
+ crypto = inject(WebCryptoService);
1852
+ config = null;
1853
+ _lastMessage = signal(null, ...(ngDevMode ? [{ debugName: "_lastMessage" }] : /* istanbul ignore next */ []));
1854
+ _messages$ = new Subject();
1855
+ messageHandler = null;
1856
+ get targetWindow() {
1857
+ return this.document.defaultView;
1858
+ }
1859
+ /** Returns a new HMAC-SHA-256 CryptoKey ready to use in `configure()`. */
1860
+ generateChannelKey() {
1861
+ return this.crypto.generateHmacKey('HMAC-SHA-256');
1862
+ }
1863
+ /**
1864
+ * Configures the service with a signing key and allowed origins.
1865
+ * Starts listening for incoming messages.
1866
+ */
1867
+ configure(config) {
1868
+ this.destroy();
1869
+ this.config = config;
1870
+ if (!isPlatformBrowser(this.platformId))
1871
+ return;
1872
+ this.ngZone.runOutsideAngular(() => {
1873
+ this.messageHandler = (event) => this.handleMessage(event);
1874
+ this.targetWindow.addEventListener('message', this.messageHandler);
1875
+ });
1876
+ }
1877
+ /**
1878
+ * Signs and sends a payload to a target window.
1879
+ * @throws if `targetOrigin` is `'*'`
1880
+ */
1881
+ async send(target, payload, targetOrigin) {
1882
+ if (targetOrigin === '*') {
1883
+ throw new Error('SecureMessageService: targetOrigin must be an explicit origin, not "*".');
1884
+ }
1885
+ if (!this.config) {
1886
+ throw new Error('SecureMessageService: call configure() before send().');
1887
+ }
1888
+ const timestamp = Date.now();
1889
+ const nonce = this.targetWindow.crypto.randomUUID();
1890
+ const body = { payload, timestamp, nonce };
1891
+ const signature = await this.crypto.sign(this.config.signingKey, JSON.stringify(body));
1892
+ const envelope = { __signed: true, ...body, signature };
1893
+ target.postMessage(envelope, targetOrigin);
1894
+ }
1895
+ /** Observable of verified incoming messages. */
1896
+ messages$() {
1897
+ return this._messages$.asObservable();
1898
+ }
1899
+ /** Signal with the last verified incoming message (null before first message). */
1900
+ lastMessage() {
1901
+ return this._lastMessage;
1902
+ }
1903
+ /** Removes the window listener and completes the internal Subject. */
1904
+ destroy() {
1905
+ if (this.messageHandler && isPlatformBrowser(this.platformId)) {
1906
+ this.targetWindow.removeEventListener('message', this.messageHandler);
1907
+ this.messageHandler = null;
1908
+ }
1909
+ this.config = null;
1910
+ }
1911
+ async handleMessage(event) {
1912
+ if (!this.config)
1913
+ return;
1914
+ // 1. Origin whitelist
1915
+ if (!this.config.allowedOrigins.includes(event.origin))
1916
+ return;
1917
+ // 2. Envelope shape
1918
+ const env = event.data;
1919
+ if (env?.__signed !== true)
1920
+ return;
1921
+ const { payload, timestamp, nonce, signature } = env;
1922
+ if (!payload || !timestamp || !nonce || !signature)
1923
+ return;
1924
+ // 3. Replay window
1925
+ if (Date.now() - timestamp > REPLAY_WINDOW_MS)
1926
+ return;
1927
+ // 4. Signature verification
1928
+ const body = { payload, timestamp, nonce };
1929
+ const valid = await this.crypto.verify(this.config.signingKey, JSON.stringify(body), signature);
1930
+ if (!valid)
1931
+ return;
1932
+ // 5. Emit inside NgZone so signals trigger CD
1933
+ this.ngZone.run(() => {
1934
+ const message = { data: payload, origin: event.origin, timestamp };
1935
+ this._lastMessage.set(message);
1936
+ this._messages$.next(message);
1937
+ });
1938
+ }
1939
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: SecureMessageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1940
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: SecureMessageService, providedIn: 'root' });
1941
+ }
1942
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: SecureMessageService, decorators: [{
1943
+ type: Injectable,
1944
+ args: [{
1945
+ providedIn: 'root',
1946
+ }]
1947
+ }] });
1948
+
1719
1949
  const defaultSecurityConfig = {
1720
1950
  enableRegexSecurity: true,
1721
1951
  enableWebCrypto: true,
@@ -1727,6 +1957,8 @@ const defaultSecurityConfig = {
1727
1957
  enableHibp: false,
1728
1958
  enableRateLimiter: false,
1729
1959
  enableCsrf: false,
1960
+ enableSessionIdle: false,
1961
+ enableSecureMessage: false,
1730
1962
  defaultTimeout: 5000,
1731
1963
  safeMode: false,
1732
1964
  };
@@ -1755,6 +1987,10 @@ function provideSecurity(config = {}) {
1755
1987
  if (mergedConfig.enableCsrf) {
1756
1988
  providers.push(WebCryptoService, CsrfService);
1757
1989
  }
1990
+ if (mergedConfig.enableSessionIdle)
1991
+ providers.push(SessionIdleService);
1992
+ if (mergedConfig.enableSecureMessage)
1993
+ providers.push(SecureMessageService);
1758
1994
  return makeEnvironmentProviders(providers);
1759
1995
  }
1760
1996
  function provideRegexSecurity() {
@@ -1804,9 +2040,15 @@ function provideCsrf(config) {
1804
2040
  ...(config ? [{ provide: CSRF_CONFIG, useValue: config }] : []),
1805
2041
  ]);
1806
2042
  }
2043
+ function provideSessionIdle() {
2044
+ return makeEnvironmentProviders([SessionIdleService]);
2045
+ }
2046
+ function provideSecureMessage() {
2047
+ return makeEnvironmentProviders([WebCryptoService, SecureMessageService]);
2048
+ }
1807
2049
 
1808
2050
  /**
1809
2051
  * Generated bundle index. Do not edit.
1810
2052
  */
1811
2053
 
1812
- export { CSRF_CONFIG, ClipboardUnsupportedError, CsrfService, DEFAULT_ALLOWED_ATTRIBUTES, DEFAULT_ALLOWED_TAGS, HIBP_CONFIG, HibpService, InputSanitizerService, InvalidJwtError, JwtService, PasswordStrengthService, RATE_LIMITER_CONFIG, RateLimitExceededError, RateLimiterService, RegexSecurityBuilder, RegexSecurityService, SANITIZER_CONFIG, SECURE_STORAGE_CONFIG, SecureStorageService, SensitiveClipboardService, WebCryptoService, assessPasswordStrength, containsScriptInjection, containsSqlInjectionHints, defaultSecurityConfig, isHtmlSafe, isUrlSafe, provideCsrf, provideHibp, provideInputSanitizer, provideJwt, providePasswordStrength, provideRateLimiter, provideRegexSecurity, provideSecureStorage, provideSecurity, provideSensitiveClipboard, provideWebCrypto, sanitizeHtmlString, sanitizeUrlString, withCsrfHeader };
2054
+ export { CSRF_CONFIG, ClipboardUnsupportedError, CsrfService, DEFAULT_ALLOWED_ATTRIBUTES, DEFAULT_ALLOWED_TAGS, HIBP_CONFIG, HibpService, InputSanitizerService, InvalidJwtError, JwtService, PasswordStrengthService, RATE_LIMITER_CONFIG, RateLimitExceededError, RateLimiterService, RegexSecurityBuilder, RegexSecurityService, SANITIZER_CONFIG, SECURE_STORAGE_CONFIG, SecureMessageService, SecureStorageService, SensitiveClipboardService, SessionIdleService, WebCryptoService, assessPasswordStrength, containsScriptInjection, containsSqlInjectionHints, defaultSecurityConfig, isHtmlSafe, isUrlSafe, provideCsrf, provideHibp, provideInputSanitizer, provideJwt, providePasswordStrength, provideRateLimiter, provideRegexSecurity, provideSecureMessage, provideSecureStorage, provideSecurity, provideSensitiveClipboard, provideSessionIdle, provideWebCrypto, sanitizeHtmlString, sanitizeUrlString, withCsrfHeader };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular-helpers/security",
3
- "version": "21.3.0",
3
+ "version": "21.4.1",
4
4
  "description": "Angular security helpers for preventing ReDoS and other security vulnerabilities",
5
5
  "keywords": [
6
6
  "angular",
@@ -16,7 +16,12 @@
16
16
  "xss",
17
17
  "sanitization",
18
18
  "password-strength",
19
- "secure-storage"
19
+ "secure-storage",
20
+ "session-idle",
21
+ "inactivity",
22
+ "postmessage",
23
+ "iframe",
24
+ "secure-channel"
20
25
  ],
21
26
  "author": "Angular Helpers Team",
22
27
  "license": "MIT",
@@ -64,5 +69,6 @@
64
69
  "default": "./fesm2022/angular-helpers-security-signal-forms.mjs"
65
70
  }
66
71
  },
67
- "sideEffects": false
72
+ "sideEffects": false,
73
+ "type": "module"
68
74
  }
@@ -537,6 +537,10 @@ declare class SensitiveClipboardService {
537
537
  */
538
538
  cancelPendingClear(): void;
539
539
  private safeClear;
540
+ /**
541
+ * Forcefully clears the clipboard unconditionally.
542
+ */
543
+ clear(): Promise<void>;
540
544
  static ɵfac: i0.ɵɵFactoryDeclaration<SensitiveClipboardService, never>;
541
545
  static ɵprov: i0.ɵɵInjectableDeclaration<SensitiveClipboardService>;
542
546
  }
@@ -745,6 +749,82 @@ interface CsrfHeaderOptions {
745
749
  */
746
750
  declare function withCsrfHeader(options?: CsrfHeaderOptions): HttpInterceptorFn;
747
751
 
752
+ interface SessionIdleConfig {
753
+ timeoutMs: number;
754
+ warningThresholdMs?: number;
755
+ autoClearStorage?: boolean;
756
+ autoClearClipboard?: boolean;
757
+ events?: string[];
758
+ }
759
+ declare class SessionIdleService {
760
+ private ngZone;
761
+ private document;
762
+ private injector;
763
+ private destroyRef;
764
+ private _isIdle;
765
+ private _isWarning;
766
+ private _timeRemaining;
767
+ private _timeoutSubject;
768
+ readonly isIdle: Signal<boolean>;
769
+ readonly isWarning: Signal<boolean>;
770
+ readonly timeRemaining: Signal<number | null>;
771
+ readonly onTimeout: Observable<void>;
772
+ private config;
773
+ private lastActivityTime;
774
+ private timerInterval;
775
+ private eventSubscription?;
776
+ constructor();
777
+ start(config: SessionIdleConfig): void;
778
+ stop(): void;
779
+ reset(): void;
780
+ private checkIdle;
781
+ private triggerTimeout;
782
+ static ɵfac: i0.ɵɵFactoryDeclaration<SessionIdleService, never>;
783
+ static ɵprov: i0.ɵɵInjectableDeclaration<SessionIdleService>;
784
+ }
785
+
786
+ interface SecureMessageConfig {
787
+ allowedOrigins: string[];
788
+ signingKey: CryptoKey;
789
+ }
790
+ interface SecureMessage<T = unknown> {
791
+ data: T;
792
+ origin: string;
793
+ timestamp: number;
794
+ }
795
+ declare class SecureMessageService {
796
+ private readonly ngZone;
797
+ private readonly platformId;
798
+ private readonly document;
799
+ private readonly crypto;
800
+ private config;
801
+ private _lastMessage;
802
+ private _messages$;
803
+ private messageHandler;
804
+ private get targetWindow();
805
+ /** Returns a new HMAC-SHA-256 CryptoKey ready to use in `configure()`. */
806
+ generateChannelKey(): Promise<CryptoKey>;
807
+ /**
808
+ * Configures the service with a signing key and allowed origins.
809
+ * Starts listening for incoming messages.
810
+ */
811
+ configure(config: SecureMessageConfig): void;
812
+ /**
813
+ * Signs and sends a payload to a target window.
814
+ * @throws if `targetOrigin` is `'*'`
815
+ */
816
+ send<T>(target: Window, payload: T, targetOrigin: string): Promise<void>;
817
+ /** Observable of verified incoming messages. */
818
+ messages$<T = unknown>(): Observable<SecureMessage<T>>;
819
+ /** Signal with the last verified incoming message (null before first message). */
820
+ lastMessage<T = unknown>(): Signal<SecureMessage<T> | null>;
821
+ /** Removes the window listener and completes the internal Subject. */
822
+ destroy(): void;
823
+ private handleMessage;
824
+ static ɵfac: i0.ɵɵFactoryDeclaration<SecureMessageService, never>;
825
+ static ɵprov: i0.ɵɵInjectableDeclaration<SecureMessageService>;
826
+ }
827
+
748
828
  interface SecurityConfig {
749
829
  enableRegexSecurity?: boolean;
750
830
  enableWebCrypto?: boolean;
@@ -756,6 +836,8 @@ interface SecurityConfig {
756
836
  enableHibp?: boolean;
757
837
  enableRateLimiter?: boolean;
758
838
  enableCsrf?: boolean;
839
+ enableSessionIdle?: boolean;
840
+ enableSecureMessage?: boolean;
759
841
  defaultTimeout?: number;
760
842
  safeMode?: boolean;
761
843
  }
@@ -771,6 +853,8 @@ declare function provideSensitiveClipboard(): EnvironmentProviders;
771
853
  declare function provideHibp(config?: HibpConfig): EnvironmentProviders;
772
854
  declare function provideRateLimiter(config?: RateLimiterConfig): EnvironmentProviders;
773
855
  declare function provideCsrf(config?: CsrfConfig): EnvironmentProviders;
856
+ declare function provideSessionIdle(): EnvironmentProviders;
857
+ declare function provideSecureMessage(): EnvironmentProviders;
774
858
 
775
- export { CSRF_CONFIG, ClipboardUnsupportedError, CsrfService, DEFAULT_ALLOWED_ATTRIBUTES, DEFAULT_ALLOWED_TAGS, HIBP_CONFIG, HibpService, InputSanitizerService, InvalidJwtError, JwtService, PasswordStrengthService, RATE_LIMITER_CONFIG, RateLimitExceededError, RateLimiterService, RegexSecurityBuilder, RegexSecurityService, SANITIZER_CONFIG, SECURE_STORAGE_CONFIG, SecureStorageService, SensitiveClipboardService, WebCryptoService, assessPasswordStrength, containsScriptInjection, containsSqlInjectionHints, defaultSecurityConfig, isHtmlSafe, isUrlSafe, provideCsrf, provideHibp, provideInputSanitizer, provideJwt, providePasswordStrength, provideRateLimiter, provideRegexSecurity, provideSecureStorage, provideSecurity, provideSensitiveClipboard, provideWebCrypto, sanitizeHtmlString, sanitizeUrlString, withCsrfHeader };
776
- export type { AesEncryptResult, AesKeyLength, CopyStatus, CsrfConfig, CsrfHeaderOptions, CsrfStorageTarget, HashAlgorithm, HibpConfig, HibpResult, HmacAlgorithm, HtmlSanitizerOptions, HttpMethod, JwtStandardClaims, PasswordAssessment, PasswordLabel, PasswordScore, PasswordStrengthResult, RateLimitPolicy, RateLimiterConfig, RegexBuilderOptions, RegexSecurityConfig, RegexSecurityResult, RegexTestResult, SanitizerConfig, SecureStorageConfig, SecurityConfig, SensitiveCopyOptions, StorageTarget };
859
+ export { CSRF_CONFIG, ClipboardUnsupportedError, CsrfService, DEFAULT_ALLOWED_ATTRIBUTES, DEFAULT_ALLOWED_TAGS, HIBP_CONFIG, HibpService, InputSanitizerService, InvalidJwtError, JwtService, PasswordStrengthService, RATE_LIMITER_CONFIG, RateLimitExceededError, RateLimiterService, RegexSecurityBuilder, RegexSecurityService, SANITIZER_CONFIG, SECURE_STORAGE_CONFIG, SecureMessageService, SecureStorageService, SensitiveClipboardService, SessionIdleService, WebCryptoService, assessPasswordStrength, containsScriptInjection, containsSqlInjectionHints, defaultSecurityConfig, isHtmlSafe, isUrlSafe, provideCsrf, provideHibp, provideInputSanitizer, provideJwt, providePasswordStrength, provideRateLimiter, provideRegexSecurity, provideSecureMessage, provideSecureStorage, provideSecurity, provideSensitiveClipboard, provideSessionIdle, provideWebCrypto, sanitizeHtmlString, sanitizeUrlString, withCsrfHeader };
860
+ export type { AesEncryptResult, AesKeyLength, CopyStatus, CsrfConfig, CsrfHeaderOptions, CsrfStorageTarget, HashAlgorithm, HibpConfig, HibpResult, HmacAlgorithm, HtmlSanitizerOptions, HttpMethod, JwtStandardClaims, PasswordAssessment, PasswordLabel, PasswordScore, PasswordStrengthResult, RateLimitPolicy, RateLimiterConfig, RegexBuilderOptions, RegexSecurityConfig, RegexSecurityResult, RegexTestResult, SanitizerConfig, SecureMessage, SecureMessageConfig, SecureStorageConfig, SecurityConfig, SensitiveCopyOptions, SessionIdleConfig, StorageTarget };