@nauth-toolkit/client-angular 0.1.56 → 0.1.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/esm2022/lib/auth.guard.mjs +83 -0
  2. package/esm2022/lib/auth.interceptor.mjs +158 -0
  3. package/esm2022/lib/social-redirect-callback.guard.mjs +81 -0
  4. package/esm2022/nauth-toolkit-client-angular.mjs +5 -0
  5. package/esm2022/ngmodule/auth.interceptor.class.mjs +109 -0
  6. package/esm2022/ngmodule/auth.service.mjs +777 -0
  7. package/esm2022/ngmodule/http-adapter.mjs +127 -0
  8. package/esm2022/ngmodule/nauth.module.mjs +65 -0
  9. package/esm2022/ngmodule/tokens.mjs +6 -0
  10. package/esm2022/public-api.mjs +19 -0
  11. package/esm2022/src/standalone/nauth-toolkit-client-angular-src-standalone.mjs +5 -0
  12. package/esm2022/src/standalone/public-api.mjs +12 -0
  13. package/esm2022/standalone/auth.guard.mjs +83 -0
  14. package/esm2022/standalone/auth.interceptor.mjs +158 -0
  15. package/esm2022/standalone/auth.service.mjs +777 -0
  16. package/esm2022/standalone/http-adapter.mjs +127 -0
  17. package/esm2022/standalone/nauth-toolkit-client-angular-standalone.mjs +5 -0
  18. package/esm2022/standalone/public-api.mjs +16 -0
  19. package/esm2022/standalone/social-redirect-callback.guard.mjs +81 -0
  20. package/esm2022/standalone/tokens.mjs +6 -0
  21. package/fesm2022/nauth-toolkit-client-angular-src-standalone.mjs +17 -0
  22. package/fesm2022/nauth-toolkit-client-angular-src-standalone.mjs.map +1 -0
  23. package/fesm2022/nauth-toolkit-client-angular-standalone.mjs +1229 -0
  24. package/fesm2022/nauth-toolkit-client-angular-standalone.mjs.map +1 -0
  25. package/fesm2022/nauth-toolkit-client-angular.mjs +1390 -0
  26. package/fesm2022/nauth-toolkit-client-angular.mjs.map +1 -0
  27. package/index.d.ts +5 -0
  28. package/{src/lib/auth.guard.ts → lib/auth.guard.d.ts} +15 -37
  29. package/lib/auth.interceptor.d.ts +15 -0
  30. package/lib/social-redirect-callback.guard.d.ts +25 -0
  31. package/ngmodule/auth.interceptor.class.d.ts +34 -0
  32. package/ngmodule/auth.service.d.ts +580 -0
  33. package/ngmodule/http-adapter.d.ts +53 -0
  34. package/ngmodule/nauth.module.d.ts +31 -0
  35. package/{src/ngmodule/tokens.ts → ngmodule/tokens.d.ts} +1 -2
  36. package/package.json +30 -20
  37. package/{src/public-api.ts → public-api.d.ts} +0 -6
  38. package/src/standalone/index.d.ts +5 -0
  39. package/src/standalone/{public-api.ts → public-api.d.ts} +0 -2
  40. package/standalone/{auth.guard.ts → auth.guard.d.ts} +15 -37
  41. package/standalone/auth.interceptor.d.ts +15 -0
  42. package/standalone/auth.service.d.ts +580 -0
  43. package/standalone/http-adapter.d.ts +53 -0
  44. package/standalone/index.d.ts +5 -0
  45. package/standalone/{public-api.ts → public-api.d.ts} +1 -6
  46. package/standalone/social-redirect-callback.guard.d.ts +25 -0
  47. package/standalone/{tokens.ts → tokens.d.ts} +1 -2
  48. package/ng-package.json +0 -12
  49. package/src/lib/auth.interceptor.ts +0 -194
  50. package/src/lib/social-redirect-callback.guard.ts +0 -87
  51. package/src/ngmodule/auth.interceptor.class.ts +0 -124
  52. package/src/ngmodule/auth.service.ts +0 -865
  53. package/src/ngmodule/http-adapter.ts +0 -79
  54. package/src/ngmodule/nauth.module.ts +0 -59
  55. package/src/package.json +0 -11
  56. package/src/standalone/ng-package.json +0 -7
  57. package/src/standalone/package.json +0 -8
  58. package/standalone/auth.interceptor.ts +0 -194
  59. package/standalone/auth.service.ts +0 -865
  60. package/standalone/http-adapter.ts +0 -79
  61. package/standalone/ng-package.json +0 -7
  62. package/standalone/package.json +0 -8
  63. package/standalone/social-redirect-callback.guard.ts +0 -87
  64. package/tsconfig.json +0 -10
  65. package/tsconfig.lib.json +0 -28
  66. package/tsconfig.lib.prod.json +0 -10
@@ -0,0 +1,83 @@
1
+ import { inject } from '@angular/core';
2
+ import { Router } from '@angular/router';
3
+ import { AuthService } from '../ngmodule/auth.service';
4
+ /**
5
+ * Functional route guard for authentication (Angular 17+).
6
+ *
7
+ * Protects routes by checking if user is authenticated.
8
+ * Redirects to login page if not authenticated.
9
+ *
10
+ * @param redirectTo - Path to redirect to if not authenticated (default: '/login')
11
+ * @returns CanActivateFn guard function
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // In route configuration
16
+ * const routes: Routes = [
17
+ * {
18
+ * path: 'home',
19
+ * component: HomeComponent,
20
+ * canActivate: [authGuard()]
21
+ * },
22
+ * {
23
+ * path: 'admin',
24
+ * component: AdminComponent,
25
+ * canActivate: [authGuard('/admin/login')]
26
+ * }
27
+ * ];
28
+ * ```
29
+ */
30
+ export function authGuard(redirectTo = '/login') {
31
+ return () => {
32
+ const auth = inject(AuthService);
33
+ const router = inject(Router);
34
+ if (auth.isAuthenticated()) {
35
+ return true;
36
+ }
37
+ return router.createUrlTree([redirectTo]);
38
+ };
39
+ }
40
+ /**
41
+ * Class-based authentication guard for NgModule compatibility.
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * // In route configuration (NgModule)
46
+ * const routes: Routes = [
47
+ * {
48
+ * path: 'home',
49
+ * component: HomeComponent,
50
+ * canActivate: [AuthGuard]
51
+ * }
52
+ * ];
53
+ *
54
+ * // In module providers
55
+ * @NgModule({
56
+ * providers: [AuthGuard]
57
+ * })
58
+ * ```
59
+ */
60
+ export class AuthGuard {
61
+ auth;
62
+ router;
63
+ /**
64
+ * @param auth - Authentication service
65
+ * @param router - Angular router
66
+ */
67
+ constructor(auth, router) {
68
+ this.auth = auth;
69
+ this.router = router;
70
+ }
71
+ /**
72
+ * Check if route can be activated.
73
+ *
74
+ * @returns True if authenticated, otherwise redirects to login
75
+ */
76
+ canActivate() {
77
+ if (this.auth.isAuthenticated()) {
78
+ return true;
79
+ }
80
+ return this.router.createUrlTree(['/login']);
81
+ }
82
+ }
83
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5ndWFyZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvYXV0aC5ndWFyZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZDLE9BQU8sRUFBaUIsTUFBTSxFQUFXLE1BQU0saUJBQWlCLENBQUM7QUFDakUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRXZEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBeUJHO0FBQ0gsTUFBTSxVQUFVLFNBQVMsQ0FBQyxVQUFVLEdBQUcsUUFBUTtJQUM3QyxPQUFPLEdBQXNCLEVBQUU7UUFDN0IsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2pDLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUU5QixJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUUsRUFBRSxDQUFDO1lBQzNCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUVELE9BQU8sTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFDNUMsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBQ0gsTUFBTSxPQUFPLFNBQVM7SUFNVjtJQUNBO0lBTlY7OztPQUdHO0lBQ0gsWUFDVSxJQUFpQixFQUNqQixNQUFjO1FBRGQsU0FBSSxHQUFKLElBQUksQ0FBYTtRQUNqQixXQUFNLEdBQU4sTUFBTSxDQUFRO0lBQ3JCLENBQUM7SUFFSjs7OztPQUlHO0lBQ0gsV0FBVztRQUNULElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsRUFBRSxDQUFDO1lBQ2hDLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQy9DLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ2FuQWN0aXZhdGVGbiwgUm91dGVyLCBVcmxUcmVlIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IEF1dGhTZXJ2aWNlIH0gZnJvbSAnLi4vbmdtb2R1bGUvYXV0aC5zZXJ2aWNlJztcblxuLyoqXG4gKiBGdW5jdGlvbmFsIHJvdXRlIGd1YXJkIGZvciBhdXRoZW50aWNhdGlvbiAoQW5ndWxhciAxNyspLlxuICpcbiAqIFByb3RlY3RzIHJvdXRlcyBieSBjaGVja2luZyBpZiB1c2VyIGlzIGF1dGhlbnRpY2F0ZWQuXG4gKiBSZWRpcmVjdHMgdG8gbG9naW4gcGFnZSBpZiBub3QgYXV0aGVudGljYXRlZC5cbiAqXG4gKiBAcGFyYW0gcmVkaXJlY3RUbyAtIFBhdGggdG8gcmVkaXJlY3QgdG8gaWYgbm90IGF1dGhlbnRpY2F0ZWQgKGRlZmF1bHQ6ICcvbG9naW4nKVxuICogQHJldHVybnMgQ2FuQWN0aXZhdGVGbiBndWFyZCBmdW5jdGlvblxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBJbiByb3V0ZSBjb25maWd1cmF0aW9uXG4gKiBjb25zdCByb3V0ZXM6IFJvdXRlcyA9IFtcbiAqICAge1xuICogICAgIHBhdGg6ICdob21lJyxcbiAqICAgICBjb21wb25lbnQ6IEhvbWVDb21wb25lbnQsXG4gKiAgICAgY2FuQWN0aXZhdGU6IFthdXRoR3VhcmQoKV1cbiAqICAgfSxcbiAqICAge1xuICogICAgIHBhdGg6ICdhZG1pbicsXG4gKiAgICAgY29tcG9uZW50OiBBZG1pbkNvbXBvbmVudCxcbiAqICAgICBjYW5BY3RpdmF0ZTogW2F1dGhHdWFyZCgnL2FkbWluL2xvZ2luJyldXG4gKiAgIH1cbiAqIF07XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGF1dGhHdWFyZChyZWRpcmVjdFRvID0gJy9sb2dpbicpOiBDYW5BY3RpdmF0ZUZuIHtcbiAgcmV0dXJuICgpOiBib29sZWFuIHwgVXJsVHJlZSA9PiB7XG4gICAgY29uc3QgYXV0aCA9IGluamVjdChBdXRoU2VydmljZSk7XG4gICAgY29uc3Qgcm91dGVyID0gaW5qZWN0KFJvdXRlcik7XG5cbiAgICBpZiAoYXV0aC5pc0F1dGhlbnRpY2F0ZWQoKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJvdXRlci5jcmVhdGVVcmxUcmVlKFtyZWRpcmVjdFRvXSk7XG4gIH07XG59XG5cbi8qKlxuICogQ2xhc3MtYmFzZWQgYXV0aGVudGljYXRpb24gZ3VhcmQgZm9yIE5nTW9kdWxlIGNvbXBhdGliaWxpdHkuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEluIHJvdXRlIGNvbmZpZ3VyYXRpb24gKE5nTW9kdWxlKVxuICogY29uc3Qgcm91dGVzOiBSb3V0ZXMgPSBbXG4gKiAgIHtcbiAqICAgICBwYXRoOiAnaG9tZScsXG4gKiAgICAgY29tcG9uZW50OiBIb21lQ29tcG9uZW50LFxuICogICAgIGNhbkFjdGl2YXRlOiBbQXV0aEd1YXJkXVxuICogICB9XG4gKiBdO1xuICpcbiAqIC8vIEluIG1vZHVsZSBwcm92aWRlcnNcbiAqIEBOZ01vZHVsZSh7XG4gKiAgIHByb3ZpZGVyczogW0F1dGhHdWFyZF1cbiAqIH0pXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIEF1dGhHdWFyZCB7XG4gIC8qKlxuICAgKiBAcGFyYW0gYXV0aCAtIEF1dGhlbnRpY2F0aW9uIHNlcnZpY2VcbiAgICogQHBhcmFtIHJvdXRlciAtIEFuZ3VsYXIgcm91dGVyXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGF1dGg6IEF1dGhTZXJ2aWNlLFxuICAgIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsXG4gICkge31cblxuICAvKipcbiAgICogQ2hlY2sgaWYgcm91dGUgY2FuIGJlIGFjdGl2YXRlZC5cbiAgICpcbiAgICogQHJldHVybnMgVHJ1ZSBpZiBhdXRoZW50aWNhdGVkLCBvdGhlcndpc2UgcmVkaXJlY3RzIHRvIGxvZ2luXG4gICAqL1xuICBjYW5BY3RpdmF0ZSgpOiBib29sZWFuIHwgVXJsVHJlZSB7XG4gICAgaWYgKHRoaXMuYXV0aC5pc0F1dGhlbnRpY2F0ZWQoKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucm91dGVyLmNyZWF0ZVVybFRyZWUoWycvbG9naW4nXSk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,158 @@
1
+ import { inject, PLATFORM_ID } from '@angular/core';
2
+ import { isPlatformBrowser } from '@angular/common';
3
+ import { HttpClient, HttpErrorResponse } from '@angular/common/http';
4
+ import { Router } from '@angular/router';
5
+ import { catchError, switchMap, throwError, filter, take, BehaviorSubject, from } from 'rxjs';
6
+ import { NAUTH_CLIENT_CONFIG } from '../ngmodule/tokens';
7
+ import { AuthService } from '../ngmodule/auth.service';
8
+ /**
9
+ * Refresh state management.
10
+ * BehaviorSubject pattern is the industry-standard for token refresh.
11
+ */
12
+ let isRefreshing = false;
13
+ const refreshTokenSubject = new BehaviorSubject(null);
14
+ /**
15
+ * Track retried requests to prevent infinite loops.
16
+ */
17
+ const retriedRequests = new WeakSet();
18
+ /**
19
+ * Get CSRF token from cookie.
20
+ */
21
+ function getCsrfToken(cookieName) {
22
+ if (typeof document === 'undefined')
23
+ return null;
24
+ const match = document.cookie.match(new RegExp(`(^| )${cookieName}=([^;]+)`));
25
+ return match ? decodeURIComponent(match[2]) : null;
26
+ }
27
+ /**
28
+ * Angular HTTP interceptor for nauth-toolkit.
29
+ *
30
+ * Handles:
31
+ * - Cookies mode: withCredentials + CSRF tokens + refresh via POST
32
+ * - JSON mode: refresh via SDK, retry with new token
33
+ */
34
+ export const authInterceptor = (req, next) => {
35
+ const config = inject(NAUTH_CLIENT_CONFIG);
36
+ const http = inject(HttpClient);
37
+ const authService = inject(AuthService);
38
+ const platformId = inject(PLATFORM_ID);
39
+ const router = inject(Router);
40
+ const isBrowser = isPlatformBrowser(platformId);
41
+ if (!isBrowser) {
42
+ return next(req);
43
+ }
44
+ const tokenDelivery = config.tokenDelivery;
45
+ const baseUrl = config.baseUrl;
46
+ const endpoints = config.endpoints ?? {};
47
+ const refreshPath = endpoints.refresh ?? '/refresh';
48
+ const loginPath = endpoints.login ?? '/login';
49
+ const signupPath = endpoints.signup ?? '/signup';
50
+ const socialExchangePath = endpoints.socialExchange ?? '/social/exchange';
51
+ const refreshUrl = `${baseUrl}${refreshPath}`;
52
+ const isAuthApiRequest = req.url.includes(baseUrl);
53
+ const isRefreshEndpoint = req.url.includes(refreshPath);
54
+ const isPublicEndpoint = req.url.includes(loginPath) || req.url.includes(signupPath) || req.url.includes(socialExchangePath);
55
+ // Build request with credentials (cookies mode only)
56
+ let authReq = req;
57
+ if (tokenDelivery === 'cookies') {
58
+ authReq = authReq.clone({ withCredentials: true });
59
+ if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)) {
60
+ const csrfCookieName = config.csrf?.cookieName ?? 'nauth_csrf_token';
61
+ const csrfHeaderName = config.csrf?.headerName ?? 'x-csrf-token';
62
+ const csrfToken = getCsrfToken(csrfCookieName);
63
+ if (csrfToken) {
64
+ authReq = authReq.clone({ setHeaders: { [csrfHeaderName]: csrfToken } });
65
+ }
66
+ }
67
+ }
68
+ return next(authReq).pipe(catchError((error) => {
69
+ const shouldHandle = error instanceof HttpErrorResponse &&
70
+ error.status === 401 &&
71
+ isAuthApiRequest &&
72
+ !isRefreshEndpoint &&
73
+ !isPublicEndpoint &&
74
+ !retriedRequests.has(req);
75
+ if (!shouldHandle) {
76
+ return throwError(() => error);
77
+ }
78
+ if (config.debug) {
79
+ console.warn('[nauth-interceptor] 401 detected:', req.url);
80
+ }
81
+ if (!isRefreshing) {
82
+ isRefreshing = true;
83
+ refreshTokenSubject.next(null);
84
+ if (config.debug) {
85
+ console.warn('[nauth-interceptor] Starting refresh...');
86
+ }
87
+ // Refresh based on mode
88
+ const refresh$ = tokenDelivery === 'cookies'
89
+ ? http.post(refreshUrl, {}, { withCredentials: true })
90
+ : from(authService.refresh());
91
+ return refresh$.pipe(switchMap((response) => {
92
+ if (config.debug) {
93
+ console.warn('[nauth-interceptor] Refresh successful');
94
+ }
95
+ isRefreshing = false;
96
+ // Get new token (JSON mode) or signal success (cookies mode)
97
+ const newToken = 'accessToken' in response ? response.accessToken : 'success';
98
+ refreshTokenSubject.next(newToken ?? 'success');
99
+ // Build retry request
100
+ const retryReq = buildRetryRequest(authReq, tokenDelivery, newToken);
101
+ retriedRequests.add(retryReq);
102
+ if (config.debug) {
103
+ console.warn('[nauth-interceptor] Retrying:', req.url);
104
+ }
105
+ return next(retryReq);
106
+ }), catchError((err) => {
107
+ if (config.debug) {
108
+ console.error('[nauth-interceptor] Refresh failed:', err);
109
+ }
110
+ isRefreshing = false;
111
+ refreshTokenSubject.next(null);
112
+ // Handle session expiration - redirect to configured URL
113
+ if (config.redirects?.sessionExpired) {
114
+ router.navigateByUrl(config.redirects.sessionExpired).catch((navError) => {
115
+ if (config.debug) {
116
+ console.error('[nauth-interceptor] Navigation failed:', navError);
117
+ }
118
+ });
119
+ }
120
+ return throwError(() => err);
121
+ }));
122
+ }
123
+ else {
124
+ // Wait for ongoing refresh
125
+ if (config.debug) {
126
+ console.warn('[nauth-interceptor] Waiting for refresh...');
127
+ }
128
+ return refreshTokenSubject.pipe(filter((token) => token !== null), take(1), switchMap((token) => {
129
+ if (config.debug) {
130
+ console.warn('[nauth-interceptor] Refresh done, retrying:', req.url);
131
+ }
132
+ const retryReq = buildRetryRequest(authReq, tokenDelivery, token);
133
+ retriedRequests.add(retryReq);
134
+ return next(retryReq);
135
+ }));
136
+ }
137
+ }));
138
+ };
139
+ /**
140
+ * Build retry request with appropriate auth.
141
+ */
142
+ function buildRetryRequest(originalReq, tokenDelivery, newToken) {
143
+ if (tokenDelivery === 'json' && newToken && newToken !== 'success') {
144
+ return originalReq.clone({
145
+ setHeaders: { Authorization: `Bearer ${newToken}` },
146
+ });
147
+ }
148
+ return originalReq.clone();
149
+ }
150
+ /**
151
+ * Class-based interceptor for NgModule compatibility.
152
+ */
153
+ export class AuthInterceptor {
154
+ intercept(req, next) {
155
+ return authInterceptor(req, next);
156
+ }
157
+ }
158
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5pbnRlcmNlcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvYXV0aC5pbnRlcmNlcHRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNwRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQWlELFVBQVUsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3BILE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzlGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUV2RDs7O0dBR0c7QUFDSCxJQUFJLFlBQVksR0FBRyxLQUFLLENBQUM7QUFDekIsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLGVBQWUsQ0FBZ0IsSUFBSSxDQUFDLENBQUM7QUFFckU7O0dBRUc7QUFDSCxNQUFNLGVBQWUsR0FBRyxJQUFJLE9BQU8sRUFBd0IsQ0FBQztBQUU1RDs7R0FFRztBQUNILFNBQVMsWUFBWSxDQUFDLFVBQWtCO0lBQ3RDLElBQUksT0FBTyxRQUFRLEtBQUssV0FBVztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ2pELE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLFFBQVEsVUFBVSxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQzlFLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENB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LFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNuRSxPQUFPLFdBQVcsQ0FBQyxLQUFLLENBQUM7WUFDdkIsVUFBVSxFQUFFLEVBQUUsYUFBYSxFQUFFLFVBQVUsUUFBUSxFQUFFLEVBQUU7U0FDcEQsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUNELE9BQU8sV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQzdCLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sT0FBTyxlQUFlO0lBQzFCLFNBQVMsQ0FBQyxHQUF5QixFQUFFLElBQW1CO1FBQ3RELE9BQU8sZUFBZSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNwQyxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbmplY3QsIFBMQVRGT1JNX0lEIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBIdHRwSGFuZGxlckZuLCBIdHRwSW50ZXJjZXB0b3JGbiwgSHR0cFJlcXVlc3QsIEh0dHBDbGllbnQsIEh0dHBFcnJvclJlc3BvbnNlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIHN3aXRjaE1hcCwgdGhyb3dFcnJvciwgZmlsdGVyLCB0YWtlLCBCZWhhdmlvclN1YmplY3QsIGZyb20gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE5BVVRIX0NMSUVOVF9DT05GSUcgfSBmcm9tICcuLi9uZ21vZHVsZS90b2tlbnMnO1xuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tICcuLi9uZ21vZHVsZS9hdXRoLnNlcnZpY2UnO1xuXG4vKipcbiAqIFJlZnJlc2ggc3RhdGUgbWFuYWdlbWVudC5cbiAqIEJlaGF2aW9yU3ViamVjdCBwYXR0ZXJuIGlzIHRoZSBpbmR1c3RyeS1zdGFuZGFyZCBmb3IgdG9rZW4gcmVmcmVzaC5cbiAqL1xubGV0IGlzUmVmcmVzaGluZyA9IGZhbHNlO1xuY29uc3QgcmVmcmVzaFRva2VuU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8c3RyaW5nIHwgbnVsbD4obnVsbCk7XG5cbi8qKlxuICogVHJhY2sgcmV0cmllZCByZXF1ZXN0cyB0byBwcmV2ZW50IGluZmluaXRlIGxvb3BzLlxuICovXG5jb25zdCByZXRyaWVkUmVxdWVzdHMgPSBuZXcgV2Vha1NldDxIdHRwUmVxdWVzdDx1bmtub3duPj4oKTtcblxuLyoqXG4gKiBHZXQgQ1NSRiB0b2tlbiBmcm9tIGNvb2tpZS5cbiAqL1xuZnVuY3Rpb24gZ2V0Q3NyZlRva2VuKGNvb2tpZU5hbWU6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICBpZiAodHlwZW9mIGRvY3VtZW50ID09PSAndW5kZWZpbmVkJykgcmV0dXJuIG51bGw7XG4gIGNvbnN0IG1hdGNoID0gZG9jdW1lbnQuY29va2llLm1hdGNoKG5ldyBSZWdFeHAoYChefCApJHtjb29raWVOYW1lfT0oW147XSspYCkpO1xuICByZXR1cm4gbWF0Y2ggPyBkZWNvZGVVUklDb21wb25lbnQobWF0Y2hbMl0pIDogbnVsbDtcbn1cblxuLyoqXG4gKiBBbmd1bGFyIEhUVFAgaW50ZXJjZXB0b3IgZm9yIG5hdXRoLXRvb2xraXQuXG4gKlxuICogSGFuZGxlczpcbiAqIC0gQ29va2llcyBtb2RlOiB3aXRoQ3JlZGVudGlhbHMgKyBDU1JGIHRva2VucyArIHJlZnJlc2ggdmlhIFBPU1RcbiAqIC0gSlNPTiBtb2RlOiByZWZyZXNoIHZpYSBTREssIHJldHJ5IHdpdGggbmV3IHRva2VuXG4gKi9cbmV4cG9ydCBjb25zdCBhdXRoSW50ZXJjZXB0b3I6IEh0dHBJbnRlcmNlcHRvckZuID0gKHJlcTogSHR0cFJlcXVlc3Q8dW5rbm93bj4sIG5leHQ6IEh0dHBIYW5kbGVyRm4pID0+IHtcbiAgY29uc3QgY29uZmlnID0gaW5qZWN0KE5BVVRIX0NMSUVOVF9DT05GSUcpO1xuICBjb25zdCBodHRwID0gaW5qZWN0KEh0dHBDbGllbnQpO1xuICBjb25zdCBhdXRoU2VydmljZSA9IGluamVjdChBdXRoU2VydmljZSk7XG4gIGNvbnN0IHBsYXRmb3JtSWQgPSBpbmplY3QoUExBVEZPUk1fSUQpO1xuICBjb25zdCByb3V0ZXIgPSBpbmplY3QoUm91dGVyKTtcbiAgY29uc3QgaXNCcm93c2VyID0gaXNQbGF0Zm9ybUJyb3dzZXIocGxhdGZvcm1JZCk7XG5cbiAgaWYgKCFpc0Jyb3dzZXIpIHtcbiAgICByZXR1cm4gbmV4dChyZXEpO1xuICB9XG5cbiAgY29uc3QgdG9rZW5EZWxpdmVyeSA9IGNvbmZpZy50b2tlbkRlbGl2ZXJ5O1xuICBjb25zdCBiYXNlVXJsID0gY29uZmlnLmJhc2VVcmw7XG4gIGNvbnN0IGVuZHBvaW50cyA9IGNvbmZpZy5lbmRwb2ludHMgPz8ge307XG4gIGNvbnN0IHJlZnJlc2hQYXRoID0gZW5kcG9pbnRzLnJlZnJlc2ggPz8gJy9yZWZyZXNoJztcbiAgY29uc3QgbG9naW5QYXRoID0gZW5kcG9pbnRzLmxvZ2luID8/ICcvbG9naW4nO1xuICBjb25zdCBzaWdudXBQYXRoID0gZW5kcG9pbnRzLnNpZ251cCA/PyAnL3NpZ251cCc7XG4gIGNvbnN0IHNvY2lhbEV4Y2hhbmdlUGF0aCA9IGVuZHBvaW50cy5zb2NpYWxFeGNoYW5nZSA/PyAnL3NvY2lhbC9leGNoYW5nZSc7XG4gIGNvbnN0IHJlZnJlc2hVcmwgPSBgJHtiYXNlVXJsfSR7cmVmcmVzaFBhdGh9YDtcblxuICBjb25zdCBpc0F1dGhBcGlSZXF1ZXN0ID0gcmVxLnVybC5pbmNsdWRlcyhiYXNlVXJsKTtcbiAgY29uc3QgaXNSZWZyZXNoRW5kcG9pbnQgPSByZXEudXJsLmluY2x1ZGVzKHJlZnJlc2hQYXRoKTtcbiAgY29uc3QgaXNQdWJsaWNFbmRwb2ludCA9XG4gICAgcmVxLnVybC5pbmNsdWRlcyhsb2dpblBhdGgpIHx8IHJlcS51cmwuaW5jbHVkZXMoc2lnbnVwUGF0aCkgfHwgcmVxLnVybC5pbmNsdWRlcyhzb2NpYWxFeGNoYW5nZVBhdGgpO1xuXG4gIC8vIEJ1aWxkIHJlcXVlc3Qgd2l0aCBjcmVkZW50aWFscyAoY29va2llcyBtb2RlIG9ubHkpXG4gIGxldCBhdXRoUmVxID0gcmVxO1xuICBpZiAodG9rZW5EZWxpdmVyeSA9PT0gJ2Nvb2tpZXMnKSB7XG4gICAgYXV0aFJlcSA9IGF1dGhSZXEuY2xvbmUoeyB3aXRoQ3JlZGVudGlhbHM6IHRydWUgfSk7XG5cbiAgICBpZiAoWydQT1NUJywgJ1BVVCcsICdQQVRDSCcsICdERUxFVEUnXS5pbmNsdWRlcyhyZXEubWV0aG9kKSkge1xuICAgICAgY29uc3QgY3NyZkNvb2tpZU5hbWUgPSBjb25maWcuY3NyZj8uY29va2llTmFtZSA/PyAnbmF1dGhfY3NyZl90b2tlbic7XG4gICAgICBjb25zdCBjc3JmSGVhZGVyTmFtZSA9IGNvbmZpZy5jc3JmPy5oZWFkZXJOYW1lID8/ICd4LWNzcmYtdG9rZW4nO1xuICAgICAgY29uc3QgY3NyZlRva2VuID0gZ2V0Q3NyZlRva2VuKGNzcmZDb29raWVOYW1lKTtcbiAgICAgIGlmIChjc3JmVG9rZW4pIHtcbiAgICAgICAgYXV0aFJlcSA9IGF1dGhSZXEuY2xvbmUoeyBzZXRIZWFkZXJzOiB7IFtjc3JmSGVhZGVyTmFtZV06IGNzcmZUb2tlbiB9IH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXh0KGF1dGhSZXEpLnBpcGUoXG4gICAgY2F0Y2hFcnJvcigoZXJyb3I6IHVua25vd24pID0+IHtcbiAgICAgIGNvbnN0IHNob3VsZEhhbmRsZSA9XG4gICAgICAgIGVycm9yIGluc3RhbmNlb2YgSHR0cEVycm9yUmVzcG9uc2UgJiZcbiAgICAgICAgZXJyb3Iuc3RhdHVzID09PSA0MDEgJiZcbiAgICAgICAgaXNBdXRoQXBpUmVxdWVzdCAmJlxuICAgICAgICAhaXNSZWZyZXNoRW5kcG9pbnQgJiZcbiAgICAgICAgIWlzUHVibGljRW5kcG9pbnQgJiZcbiAgICAgICAgIXJldHJpZWRSZXF1ZXN0cy5oYXMocmVxKTtcblxuICAgICAgaWYgKCFzaG91bGRIYW5kbGUpIHtcbiAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gZXJyb3IpO1xuICAgICAgfVxuXG4gICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSA0MDEgZGV0ZWN0ZWQ6JywgcmVxLnVybCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghaXNSZWZyZXNoaW5nKSB7XG4gICAgICAgIGlzUmVmcmVzaGluZyA9IHRydWU7XG4gICAgICAgIHJlZnJlc2hUb2tlblN1YmplY3QubmV4dChudWxsKTtcblxuICAgICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKCdbbmF1dGgtaW50ZXJjZXB0b3JdIFN0YXJ0aW5nIHJlZnJlc2guLi4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlZnJlc2ggYmFzZWQgb24gbW9kZVxuICAgICAgICBjb25zdCByZWZyZXNoJCA9XG4gICAgICAgICAgdG9rZW5EZWxpdmVyeSA9PT0gJ2Nvb2tpZXMnXG4gICAgICAgICAgICA/IGh0dHAucG9zdDx7IGFjY2Vzc1Rva2VuPzogc3RyaW5nIH0+KHJlZnJlc2hVcmwsIHt9LCB7IHdpdGhDcmVkZW50aWFsczogdHJ1ZSB9KVxuICAgICAgICAgICAgOiBmcm9tKGF1dGhTZXJ2aWNlLnJlZnJlc2goKSk7XG5cbiAgICAgICAgcmV0dXJuIHJlZnJlc2gkLnBpcGUoXG4gICAgICAgICAgc3dpdGNoTWFwKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tuYXV0aC1pbnRlcmNlcHRvcl0gUmVmcmVzaCBzdWNjZXNzZnVsJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpc1JlZnJlc2hpbmcgPSBmYWxzZTtcblxuICAgICAgICAgICAgLy8gR2V0IG5ldyB0b2tlbiAoSlNPTiBtb2RlKSBvciBzaWduYWwgc3VjY2VzcyAoY29va2llcyBtb2RlKVxuICAgICAgICAgICAgY29uc3QgbmV3VG9rZW4gPSAnYWNjZXNzVG9rZW4nIGluIHJlc3BvbnNlID8gcmVzcG9uc2UuYWNjZXNzVG9rZW4gOiAnc3VjY2Vzcyc7XG4gICAgICAgICAgICByZWZyZXNoVG9rZW5TdWJqZWN0Lm5leHQobmV3VG9rZW4gPz8gJ3N1Y2Nlc3MnKTtcblxuICAgICAgICAgICAgLy8gQnVpbGQgcmV0cnkgcmVxdWVzdFxuICAgICAgICAgICAgY29uc3QgcmV0cnlSZXEgPSBidWlsZFJldHJ5UmVxdWVzdChhdXRoUmVxLCB0b2tlbkRlbGl2ZXJ5LCBuZXdUb2tlbik7XG4gICAgICAgICAgICByZXRyaWVkUmVxdWVzdHMuYWRkKHJldHJ5UmVxKTtcblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tuYXV0aC1pbnRlcmNlcHRvcl0gUmV0cnlpbmc6JywgcmVxLnVybCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV4dChyZXRyeVJlcSk7XG4gICAgICAgICAgfSksXG4gICAgICAgICAgY2F0Y2hFcnJvcigoZXJyKSA9PiB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1tuYXV0aC1pbnRlcmNlcHRvcl0gUmVmcmVzaCBmYWlsZWQ6JywgZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlzUmVmcmVzaGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmVmcmVzaFRva2VuU3ViamVjdC5uZXh0KG51bGwpO1xuXG4gICAgICAgICAgICAvLyBIYW5kbGUgc2Vzc2lvbiBleHBpcmF0aW9uIC0gcmVkaXJlY3QgdG8gY29uZmlndXJlZCBVUkxcbiAgICAgICAgICAgIGlmIChjb25maWcucmVkaXJlY3RzPy5zZXNzaW9uRXhwaXJlZCkge1xuICAgICAgICAgICAgICByb3V0ZXIubmF2aWdhdGVCeVVybChjb25maWcucmVkaXJlY3RzLnNlc3Npb25FeHBpcmVkKS5jYXRjaCgobmF2RXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdbbmF1dGgtaW50ZXJjZXB0b3JdIE5hdmlnYXRpb24gZmFpbGVkOicsIG5hdkVycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnIpO1xuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gV2FpdCBmb3Igb25nb2luZyByZWZyZXNoXG4gICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJ1tuYXV0aC1pbnRlcmNlcHRvcl0gV2FpdGluZyBmb3IgcmVmcmVzaC4uLicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZWZyZXNoVG9rZW5TdWJqZWN0LnBpcGUoXG4gICAgICAgICAgZmlsdGVyKCh0b2tlbik6IHRva2VuIGlzIHN0cmluZyA9PiB0b2tlbiAhPT0gbnVsbCksXG4gICAgICAgICAgdGFrZSgxKSxcbiAgICAgICAgICBzd2l0Y2hNYXAoKHRva2VuKSA9PiB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSBSZWZyZXNoIGRvbmUsIHJldHJ5aW5nOicsIHJlcS51cmwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmV0cnlSZXEgPSBidWlsZFJldHJ5UmVxdWVzdChhdXRoUmVxLCB0b2tlbkRlbGl2ZXJ5LCB0b2tlbik7XG4gICAgICAgICAgICByZXRyaWVkUmVxdWVzdHMuYWRkKHJldHJ5UmVxKTtcbiAgICAgICAgICAgIHJldHVybiBuZXh0KHJldHJ5UmVxKTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KSxcbiAgKTtcbn07XG5cbi8qKlxuICogQnVpbGQgcmV0cnkgcmVxdWVzdCB3aXRoIGFwcHJvcHJpYXRlIGF1dGguXG4gKi9cbmZ1bmN0aW9uIGJ1aWxkUmV0cnlSZXF1ZXN0KFxuICBvcmlnaW5hbFJlcTogSHR0cFJlcXVlc3Q8dW5rbm93bj4sXG4gIHRva2VuRGVsaXZlcnk6IHN0cmluZyxcbiAgbmV3VG9rZW4/OiBzdHJpbmcsXG4pOiBIdHRwUmVxdWVzdDx1bmtub3duPiB7XG4gIGlmICh0b2tlbkRlbGl2ZXJ5ID09PSAnanNvbicgJiYgbmV3VG9rZW4gJiYgbmV3VG9rZW4gIT09ICdzdWNjZXNzJykge1xuICAgIHJldHVybiBvcmlnaW5hbFJlcS5jbG9uZSh7XG4gICAgICBzZXRIZWFkZXJzOiB7IEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHtuZXdUb2tlbn1gIH0sXG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIG9yaWdpbmFsUmVxLmNsb25lKCk7XG59XG5cbi8qKlxuICogQ2xhc3MtYmFzZWQgaW50ZXJjZXB0b3IgZm9yIE5nTW9kdWxlIGNvbXBhdGliaWxpdHkuXG4gKi9cbmV4cG9ydCBjbGFzcyBBdXRoSW50ZXJjZXB0b3Ige1xuICBpbnRlcmNlcHQocmVxOiBIdHRwUmVxdWVzdDx1bmtub3duPiwgbmV4dDogSHR0cEhhbmRsZXJGbikge1xuICAgIHJldHVybiBhdXRoSW50ZXJjZXB0b3IocmVxLCBuZXh0KTtcbiAgfVxufVxuIl19
@@ -0,0 +1,81 @@
1
+ import { inject, PLATFORM_ID } from '@angular/core';
2
+ import { isPlatformBrowser } from '@angular/common';
3
+ import { AuthService } from '../ngmodule/auth.service';
4
+ import { NAUTH_CLIENT_CONFIG } from '../ngmodule/tokens';
5
+ /**
6
+ * Social redirect callback route guard.
7
+ *
8
+ * This guard supports the redirect-first social flow where the backend redirects
9
+ * back to the frontend with:
10
+ * - `appState` (always optional)
11
+ * - `exchangeToken` (present for json/hybrid flows, and for cookie flows that return a challenge)
12
+ * - `error` / `error_description` (provider errors)
13
+ *
14
+ * Behavior:
15
+ * - If `exchangeToken` exists: exchanges it via backend and redirects to success or challenge routes.
16
+ * - If no `exchangeToken`: treat as cookie-success path and redirect to success route.
17
+ * - If `error` exists: redirects to oauthError route.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { socialRedirectCallbackGuard } from '@nauth-toolkit/client/angular';
22
+ *
23
+ * export const routes: Routes = [
24
+ * { path: 'auth/callback', canActivate: [socialRedirectCallbackGuard], component: CallbackComponent },
25
+ * ];
26
+ * ```
27
+ */
28
+ export const socialRedirectCallbackGuard = async () => {
29
+ const auth = inject(AuthService);
30
+ const config = inject(NAUTH_CLIENT_CONFIG);
31
+ const platformId = inject(PLATFORM_ID);
32
+ const isBrowser = isPlatformBrowser(platformId);
33
+ if (!isBrowser) {
34
+ return false;
35
+ }
36
+ const params = new URLSearchParams(window.location.search);
37
+ const error = params.get('error');
38
+ const exchangeToken = params.get('exchangeToken');
39
+ // Provider error: redirect to oauthError
40
+ if (error) {
41
+ const errorUrl = config.redirects?.oauthError || '/login';
42
+ window.location.replace(errorUrl);
43
+ return false;
44
+ }
45
+ // No exchangeToken: cookie success path; redirect to success.
46
+ //
47
+ // Note: we do not "activate" the callback route to avoid consumers needing to render a page.
48
+ if (!exchangeToken) {
49
+ // ============================================================================
50
+ // Cookies mode: hydrate user state before redirecting
51
+ // ============================================================================
52
+ // WHY: In cookie delivery, the OAuth callback completes via browser redirects, so the frontend
53
+ // does not receive a JSON AuthResponse to populate the SDK's cached `currentUser`.
54
+ //
55
+ // Without this, sync guards (`authGuard`) can immediately redirect to /login because
56
+ // `currentUser` is still null even though cookies were set successfully.
57
+ try {
58
+ await auth.getProfile();
59
+ }
60
+ catch {
61
+ const errorUrl = config.redirects?.oauthError || '/login';
62
+ window.location.replace(errorUrl);
63
+ return false;
64
+ }
65
+ const successUrl = config.redirects?.success || '/';
66
+ window.location.replace(successUrl);
67
+ return false;
68
+ }
69
+ // Exchange token and route accordingly
70
+ const response = await auth.exchangeSocialRedirect(exchangeToken);
71
+ if (response.challengeName) {
72
+ const challengeBase = config.redirects?.challengeBase || '/auth/challenge';
73
+ const challengeRoute = response.challengeName.toLowerCase().replace(/_/g, '-');
74
+ window.location.replace(`${challengeBase}/${challengeRoute}`);
75
+ return false;
76
+ }
77
+ const successUrl = config.redirects?.success || '/';
78
+ window.location.replace(successUrl);
79
+ return false;
80
+ };
81
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29jaWFsLXJlZGlyZWN0LWNhbGxiYWNrLmd1YXJkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi9zb2NpYWwtcmVkaXJlY3QtY2FsbGJhY2suZ3VhcmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDcEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFcEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRXpEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sMkJBQTJCLEdBQWtCLEtBQUssSUFBc0IsRUFBRTtJQUNyRixNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDakMsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDM0MsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sU0FBUyxHQUFHLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBRWhELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNmLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELE1BQU0sTUFBTSxHQUFHLElBQUksZUFBZSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDM0QsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNsQyxNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBRWxELHlDQUF5QztJQUN6QyxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQ1YsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLFNBQVMsRUFBRSxVQUFVLElBQUksUUFBUSxDQUFDO1FBQzFELE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2xDLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELDhEQUE4RDtJQUM5RCxFQUFFO0lBQ0YsNkZBQTZGO0lBQzdGLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUNuQiwrRUFBK0U7UUFDL0Usc0RBQXNEO1FBQ3RELCtFQUErRTtRQUMvRSwrRkFBK0Y7UUFDL0YsbUZBQW1GO1FBQ25GLEVBQUU7UUFDRixxRkFBcUY7UUFDckYseUVBQXlFO1FBQ3pFLElBQUksQ0FBQztZQUNILE1BQU0sSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQzFCLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsU0FBUyxFQUFFLFVBQVUsSUFBSSxRQUFRLENBQUM7WUFDMUQsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDbEMsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBQ0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLFNBQVMsRUFBRSxPQUFPLElBQUksR0FBRyxDQUFDO1FBQ3BELE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3BDLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELHVDQUF1QztJQUN2QyxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUNsRSxJQUFJLFFBQVEsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUMzQixNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsU0FBUyxFQUFFLGFBQWEsSUFBSSxpQkFBaUIsQ0FBQztRQUMzRSxNQUFNLGNBQWMsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLFdBQVcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDL0UsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxhQUFhLElBQUksY0FBYyxFQUFFLENBQUMsQ0FBQztRQUM5RCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRCxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsU0FBUyxFQUFFLE9BQU8sSUFBSSxHQUFHLENBQUM7SUFDcEQsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDcEMsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbmplY3QsIFBMQVRGT1JNX0lEIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyB0eXBlIENhbkFjdGl2YXRlRm4gfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tICcuLi9uZ21vZHVsZS9hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgTkFVVEhfQ0xJRU5UX0NPTkZJRyB9IGZyb20gJy4uL25nbW9kdWxlL3Rva2Vucyc7XG5cbi8qKlxuICogU29jaWFsIHJlZGlyZWN0IGNhbGxiYWNrIHJvdXRlIGd1YXJkLlxuICpcbiAqIFRoaXMgZ3VhcmQgc3VwcG9ydHMgdGhlIHJlZGlyZWN0LWZpcnN0IHNvY2lhbCBmbG93IHdoZXJlIHRoZSBiYWNrZW5kIHJlZGlyZWN0c1xuICogYmFjayB0byB0aGUgZnJvbnRlbmQgd2l0aDpcbiAqIC0gYGFwcFN0YXRlYCAoYWx3YXlzIG9wdGlvbmFsKVxuICogLSBgZXhjaGFuZ2VUb2tlbmAgKHByZXNlbnQgZm9yIGpzb24vaHlicmlkIGZsb3dzLCBhbmQgZm9yIGNvb2tpZSBmbG93cyB0aGF0IHJldHVybiBhIGNoYWxsZW5nZSlcbiAqIC0gYGVycm9yYCAvIGBlcnJvcl9kZXNjcmlwdGlvbmAgKHByb3ZpZGVyIGVycm9ycylcbiAqXG4gKiBCZWhhdmlvcjpcbiAqIC0gSWYgYGV4Y2hhbmdlVG9rZW5gIGV4aXN0czogZXhjaGFuZ2VzIGl0IHZpYSBiYWNrZW5kIGFuZCByZWRpcmVjdHMgdG8gc3VjY2VzcyBvciBjaGFsbGVuZ2Ugcm91dGVzLlxuICogLSBJZiBubyBgZXhjaGFuZ2VUb2tlbmA6IHRyZWF0IGFzIGNvb2tpZS1zdWNjZXNzIHBhdGggYW5kIHJlZGlyZWN0IHRvIHN1Y2Nlc3Mgcm91dGUuXG4gKiAtIElmIGBlcnJvcmAgZXhpc3RzOiByZWRpcmVjdHMgdG8gb2F1dGhFcnJvciByb3V0ZS5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgc29jaWFsUmVkaXJlY3RDYWxsYmFja0d1YXJkIH0gZnJvbSAnQG5hdXRoLXRvb2xraXQvY2xpZW50L2FuZ3VsYXInO1xuICpcbiAqIGV4cG9ydCBjb25zdCByb3V0ZXM6IFJvdXRlcyA9IFtcbiAqICAgeyBwYXRoOiAnYXV0aC9jYWxsYmFjaycsIGNhbkFjdGl2YXRlOiBbc29jaWFsUmVkaXJlY3RDYWxsYmFja0d1YXJkXSwgY29tcG9uZW50OiBDYWxsYmFja0NvbXBvbmVudCB9LFxuICogXTtcbiAqIGBgYFxuICovXG5leHBvcnQgY29uc3Qgc29jaWFsUmVkaXJlY3RDYWxsYmFja0d1YXJkOiBDYW5BY3RpdmF0ZUZuID0gYXN5bmMgKCk6IFByb21pc2U8Ym9vbGVhbj4gPT4ge1xuICBjb25zdCBhdXRoID0gaW5qZWN0KEF1dGhTZXJ2aWNlKTtcbiAgY29uc3QgY29uZmlnID0gaW5qZWN0KE5BVVRIX0NMSUVOVF9DT05GSUcpO1xuICBjb25zdCBwbGF0Zm9ybUlkID0gaW5qZWN0KFBMQVRGT1JNX0lEKTtcbiAgY29uc3QgaXNCcm93c2VyID0gaXNQbGF0Zm9ybUJyb3dzZXIocGxhdGZvcm1JZCk7XG5cbiAgaWYgKCFpc0Jyb3dzZXIpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdCBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpO1xuICBjb25zdCBlcnJvciA9IHBhcmFtcy5nZXQoJ2Vycm9yJyk7XG4gIGNvbnN0IGV4Y2hhbmdlVG9rZW4gPSBwYXJhbXMuZ2V0KCdleGNoYW5nZVRva2VuJyk7XG5cbiAgLy8gUHJvdmlkZXIgZXJyb3I6IHJlZGlyZWN0IHRvIG9hdXRoRXJyb3JcbiAgaWYgKGVycm9yKSB7XG4gICAgY29uc3QgZXJyb3JVcmwgPSBjb25maWcucmVkaXJlY3RzPy5vYXV0aEVycm9yIHx8ICcvbG9naW4nO1xuICAgIHdpbmRvdy5sb2NhdGlvbi5yZXBsYWNlKGVycm9yVXJsKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyBObyBleGNoYW5nZVRva2VuOiBjb29raWUgc3VjY2VzcyBwYXRoOyByZWRpcmVjdCB0byBzdWNjZXNzLlxuICAvL1xuICAvLyBOb3RlOiB3ZSBkbyBub3QgXCJhY3RpdmF0ZVwiIHRoZSBjYWxsYmFjayByb3V0ZSB0byBhdm9pZCBjb25zdW1lcnMgbmVlZGluZyB0byByZW5kZXIgYSBwYWdlLlxuICBpZiAoIWV4Y2hhbmdlVG9rZW4pIHtcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gQ29va2llcyBtb2RlOiBoeWRyYXRlIHVzZXIgc3RhdGUgYmVmb3JlIHJlZGlyZWN0aW5nXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIFdIWTogSW4gY29va2llIGRlbGl2ZXJ5LCB0aGUgT0F1dGggY2FsbGJhY2sgY29tcGxldGVzIHZpYSBicm93c2VyIHJlZGlyZWN0cywgc28gdGhlIGZyb250ZW5kXG4gICAgLy8gZG9lcyBub3QgcmVjZWl2ZSBhIEpTT04gQXV0aFJlc3BvbnNlIHRvIHBvcHVsYXRlIHRoZSBTREsncyBjYWNoZWQgYGN1cnJlbnRVc2VyYC5cbiAgICAvL1xuICAgIC8vIFdpdGhvdXQgdGhpcywgc3luYyBndWFyZHMgKGBhdXRoR3VhcmRgKSBjYW4gaW1tZWRpYXRlbHkgcmVkaXJlY3QgdG8gL2xvZ2luIGJlY2F1c2VcbiAgICAvLyBgY3VycmVudFVzZXJgIGlzIHN0aWxsIG51bGwgZXZlbiB0aG91Z2ggY29va2llcyB3ZXJlIHNldCBzdWNjZXNzZnVsbHkuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGF1dGguZ2V0UHJvZmlsZSgpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgY29uc3QgZXJyb3JVcmwgPSBjb25maWcucmVkaXJlY3RzPy5vYXV0aEVycm9yIHx8ICcvbG9naW4nO1xuICAgICAgd2luZG93LmxvY2F0aW9uLnJlcGxhY2UoZXJyb3JVcmwpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCBzdWNjZXNzVXJsID0gY29uZmlnLnJlZGlyZWN0cz8uc3VjY2VzcyB8fCAnLyc7XG4gICAgd2luZG93LmxvY2F0aW9uLnJlcGxhY2Uoc3VjY2Vzc1VybCk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLy8gRXhjaGFuZ2UgdG9rZW4gYW5kIHJvdXRlIGFjY29yZGluZ2x5XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXV0aC5leGNoYW5nZVNvY2lhbFJlZGlyZWN0KGV4Y2hhbmdlVG9rZW4pO1xuICBpZiAocmVzcG9uc2UuY2hhbGxlbmdlTmFtZSkge1xuICAgIGNvbnN0IGNoYWxsZW5nZUJhc2UgPSBjb25maWcucmVkaXJlY3RzPy5jaGFsbGVuZ2VCYXNlIHx8ICcvYXV0aC9jaGFsbGVuZ2UnO1xuICAgIGNvbnN0IGNoYWxsZW5nZVJvdXRlID0gcmVzcG9uc2UuY2hhbGxlbmdlTmFtZS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL18vZywgJy0nKTtcbiAgICB3aW5kb3cubG9jYXRpb24ucmVwbGFjZShgJHtjaGFsbGVuZ2VCYXNlfS8ke2NoYWxsZW5nZVJvdXRlfWApO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGNvbnN0IHN1Y2Nlc3NVcmwgPSBjb25maWcucmVkaXJlY3RzPy5zdWNjZXNzIHx8ICcvJztcbiAgd2luZG93LmxvY2F0aW9uLnJlcGxhY2Uoc3VjY2Vzc1VybCk7XG4gIHJldHVybiBmYWxzZTtcbn07XG4iXX0=
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ export * from './public-api';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF1dGgtdG9vbGtpdC1jbGllbnQtYW5ndWxhci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9uYXV0aC10b29sa2l0LWNsaWVudC1hbmd1bGFyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyxjQUFjLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdlbmVyYXRlZCBidW5kbGUgaW5kZXguIERvIG5vdCBlZGl0LlxuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vcHVibGljLWFwaSc7XG4iXX0=
@@ -0,0 +1,109 @@
1
+ import { Injectable, Inject } from '@angular/core';
2
+ import { catchError, switchMap, throwError, filter, take, BehaviorSubject, from } from 'rxjs';
3
+ import { NAUTH_CLIENT_CONFIG } from './tokens';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@angular/common/http";
6
+ import * as i2 from "./auth.service";
7
+ import * as i3 from "@angular/router";
8
+ /**
9
+ * Refresh state management.
10
+ */
11
+ let isRefreshing = false;
12
+ const refreshTokenSubject = new BehaviorSubject(null);
13
+ const retriedRequests = new WeakSet();
14
+ /**
15
+ * Get CSRF token from cookie.
16
+ */
17
+ function getCsrfToken(cookieName) {
18
+ if (typeof document === 'undefined')
19
+ return null;
20
+ const match = document.cookie.match(new RegExp(`(^| )${cookieName}=([^;]+)`));
21
+ return match ? decodeURIComponent(match[2]) : null;
22
+ }
23
+ /**
24
+ * Class-based HTTP interceptor for NgModule apps (Angular < 17).
25
+ *
26
+ * For standalone components (Angular 17+), use the functional `authInterceptor` instead.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * // app.module.ts
31
+ * import { HTTP_INTERCEPTORS } from '@angular/common/http';
32
+ * import { AuthInterceptorClass } from '@nauth-toolkit/client-angular';
33
+ *
34
+ * @NgModule({
35
+ * providers: [
36
+ * { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptorClass, multi: true }
37
+ * ]
38
+ * })
39
+ * ```
40
+ */
41
+ export class AuthInterceptorClass {
42
+ config;
43
+ http;
44
+ authService;
45
+ router;
46
+ constructor(config, http, authService, router) {
47
+ this.config = config;
48
+ this.http = http;
49
+ this.authService = authService;
50
+ this.router = router;
51
+ }
52
+ intercept(req, next) {
53
+ const tokenDelivery = this.config.tokenDelivery;
54
+ const baseUrl = this.config.baseUrl;
55
+ // ============================================================================
56
+ // COOKIES MODE: withCredentials + CSRF token
57
+ // ============================================================================
58
+ if (tokenDelivery === 'cookies') {
59
+ let clonedReq = req.clone({ withCredentials: true });
60
+ // Add CSRF token header if it's a mutating request
61
+ if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)) {
62
+ const csrfToken = getCsrfToken(this.config.csrf?.cookieName || 'XSRF-TOKEN');
63
+ if (csrfToken) {
64
+ clonedReq = clonedReq.clone({
65
+ setHeaders: { [this.config.csrf?.headerName || 'X-XSRF-TOKEN']: csrfToken },
66
+ });
67
+ }
68
+ }
69
+ return next.handle(clonedReq).pipe(catchError((error) => {
70
+ if (error.status === 401 && !retriedRequests.has(req)) {
71
+ retriedRequests.add(req);
72
+ if (!isRefreshing) {
73
+ isRefreshing = true;
74
+ refreshTokenSubject.next(null);
75
+ return from(this.http
76
+ .post(`${baseUrl}/refresh`, {}, { withCredentials: true })
77
+ .toPromise()).pipe(switchMap(() => {
78
+ isRefreshing = false;
79
+ refreshTokenSubject.next('refreshed');
80
+ return next.handle(clonedReq);
81
+ }), catchError((refreshError) => {
82
+ isRefreshing = false;
83
+ this.authService.logout();
84
+ this.router.navigate([this.config.redirects?.sessionExpired || '/login']);
85
+ return throwError(() => refreshError);
86
+ }));
87
+ }
88
+ else {
89
+ return refreshTokenSubject.pipe(filter((token) => token !== null), take(1), switchMap(() => next.handle(clonedReq)));
90
+ }
91
+ }
92
+ return throwError(() => error);
93
+ }));
94
+ }
95
+ // ============================================================================
96
+ // JSON MODE: Delegate to SDK for token handling
97
+ // ============================================================================
98
+ return next.handle(req);
99
+ }
100
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AuthInterceptorClass, deps: [{ token: NAUTH_CLIENT_CONFIG }, { token: i1.HttpClient }, { token: i2.AuthService }, { token: i3.Router }], target: i0.ɵɵFactoryTarget.Injectable });
101
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AuthInterceptorClass });
102
+ }
103
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AuthInterceptorClass, decorators: [{
104
+ type: Injectable
105
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
106
+ type: Inject,
107
+ args: [NAUTH_CLIENT_CONFIG]
108
+ }] }, { type: i1.HttpClient }, { type: i2.AuthService }, { type: i3.Router }] });
109
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5pbnRlcmNlcHRvci5jbGFzcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9uZ21vZHVsZS9hdXRoLmludGVyY2VwdG9yLmNsYXNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBVW5ELE9BQU8sRUFBYyxVQUFVLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDMUcsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sVUFBVSxDQUFDOzs7OztBQUkvQzs7R0FFRztBQUNILElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQztBQUN6QixNQUFNLG1CQUFtQixHQUFHLElBQUksZUFBZSxDQUFnQixJQUFJLENBQUMsQ0FBQztBQUNyRSxNQUFNLGVBQWUsR0FBRyxJQUFJLE9BQU8sRUFBd0IsQ0FBQztBQUU1RDs7R0FFRztBQUNILFNBQVMsWUFBWSxDQUFDLFVBQWtCO0lBQ3RDLElBQUksT0FBTyxRQUFRLEtBQUssV0FBVztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ2pELE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLFFBQVEsVUFBVSxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQzlFLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0FBQ3JELENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFFSCxNQUFNLE9BQU8sb0JBQW9CO0lBRWlCO0lBQzdCO0lBQ0E7SUFDQTtJQUpuQixZQUNnRCxNQUF5QixFQUN0RCxJQUFnQixFQUNoQixXQUF3QixFQUN4QixNQUFjO1FB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QUssSUFBSSxDQUFDLEVBQ2pDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFDUCxTQUFTLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUN4QyxDQUFDO29CQUNKLENBQUM7Z0JBQ0gsQ0FBQztnQkFFRCxPQUFPLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNqQyxDQUFDLENBQUMsQ0FDSCxDQUFDO1FBQ0osQ0FBQztRQUVELCtFQUErRTtRQUMvRSxnREFBZ0Q7UUFDaEQsK0VBQStFO1FBQy9FLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMxQixDQUFDO3dHQXhFVSxvQkFBb0Isa0JBRXJCLG1CQUFtQjs0R0FGbEIsb0JBQW9COzs0RkFBcEIsb0JBQW9CO2tCQURoQyxVQUFVOzswQkFHTixNQUFNOzJCQUFDLG1CQUFtQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIEluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgSHR0cEludGVyY2VwdG9yLFxuICBIdHRwUmVxdWVzdCxcbiAgSHR0cEhhbmRsZXIsXG4gIEh0dHBFdmVudCxcbiAgSHR0cENsaWVudCxcbiAgSHR0cEVycm9yUmVzcG9uc2UsXG59IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBjYXRjaEVycm9yLCBzd2l0Y2hNYXAsIHRocm93RXJyb3IsIGZpbHRlciwgdGFrZSwgQmVoYXZpb3JTdWJqZWN0LCBmcm9tIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBOQVVUSF9DTElFTlRfQ09ORklHIH0gZnJvbSAnLi90b2tlbnMnO1xuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tICcuL2F1dGguc2VydmljZSc7XG5pbXBvcnQgeyBOQXV0aENsaWVudENvbmZpZyB9IGZyb20gJ0BuYXV0aC10b29sa2l0L2NsaWVudCc7XG5cbi8qKlxuICogUmVmcmVzaCBzdGF0ZSBtYW5hZ2VtZW50LlxuICovXG5sZXQgaXNSZWZyZXNoaW5nID0gZmFsc2U7XG5jb25zdCByZWZyZXNoVG9rZW5TdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmcgfCBudWxsPihudWxsKTtcbmNvbnN0IHJldHJpZWRSZXF1ZXN0cyA9IG5ldyBXZWFrU2V0PEh0dHBSZXF1ZXN0PHVua25vd24+PigpO1xuXG4vKipcbiAqIEdldCBDU1JGIHRva2VuIGZyb20gY29va2llLlxuICovXG5mdW5jdGlvbiBnZXRDc3JmVG9rZW4oY29va2llTmFtZTogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgbWF0Y2ggPSBkb2N1bWVudC5jb29raWUubWF0Y2gobmV3IFJlZ0V4cChgKF58ICkke2Nvb2tpZU5hbWV9PShbXjtdKylgKSk7XG4gIHJldHVybiBtYXRjaCA/IGRlY29kZVVSSUNvbXBvbmVudChtYXRjaFsyXSkgOiBudWxsO1xufVxuXG4vKipcbiAqIENsYXNzLWJhc2VkIEhUVFAgaW50ZXJjZXB0b3IgZm9yIE5nTW9kdWxlIGFwcHMgKEFuZ3VsYXIgPCAxNykuXG4gKlxuICogRm9yIHN0YW5kYWxvbmUgY29tcG9uZW50cyAoQW5ndWxhciAxNyspLCB1c2UgdGhlIGZ1bmN0aW9uYWwgYGF1dGhJbnRlcmNlcHRvcmAgaW5zdGVhZC5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gYXBwLm1vZHVsZS50c1xuICogaW1wb3J0IHsgSFRUUF9JTlRFUkNFUFRPUlMgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG4gKiBpbXBvcnQgeyBBdXRoSW50ZXJjZXB0b3JDbGFzcyB9IGZyb20gJ0BuYXV0aC10b29sa2l0L2NsaWVudC1hbmd1bGFyJztcbiAqXG4gKiBATmdNb2R1bGUoe1xuICogICBwcm92aWRlcnM6IFtcbiAqICAgICB7IHByb3ZpZGU6IEhUVFBfSU5URVJDRVBUT1JTLCB1c2VDbGFzczogQXV0aEludGVyY2VwdG9yQ2xhc3MsIG11bHRpOiB0cnVlIH1cbiAqICAgXVxuICogfSlcbiAqIGBgYFxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQXV0aEludGVyY2VwdG9yQ2xhc3MgaW1wbGVtZW50cyBIdHRwSW50ZXJjZXB0b3Ige1xuICBjb25zdHJ1Y3RvcihcbiAgICBASW5qZWN0KE5BVVRIX0NMSUVOVF9DT05GSUcpIHByaXZhdGUgcmVhZG9ubHkgY29uZmlnOiBOQXV0aENsaWVudENvbmZpZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGh0dHA6IEh0dHBDbGllbnQsXG4gICAgcHJpdmF0ZSByZWFkb25seSBhdXRoU2VydmljZTogQXV0aFNlcnZpY2UsXG4gICAgcHJpdmF0ZSByZWFkb25seSByb3V0ZXI6IFJvdXRlcixcbiAgKSB7fVxuXG4gIGludGVyY2VwdChyZXE6IEh0dHBSZXF1ZXN0PHVua25vd24+LCBuZXh0OiBIdHRwSGFuZGxlcik6IE9ic2VydmFibGU8SHR0cEV2ZW50PHVua25vd24+PiB7XG4gICAgY29uc3QgdG9rZW5EZWxpdmVyeSA9IHRoaXMuY29uZmlnLnRva2VuRGVsaXZlcnk7XG4gICAgY29uc3QgYmFzZVVybCA9IHRoaXMuY29uZmlnLmJhc2VVcmw7XG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gQ09PS0lFUyBNT0RFOiB3aXRoQ3JlZGVudGlhbHMgKyBDU1JGIHRva2VuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIGlmICh0b2tlbkRlbGl2ZXJ5ID09PSAnY29va2llcycpIHtcbiAgICAgIGxldCBjbG9uZWRSZXEgPSByZXEuY2xvbmUoeyB3aXRoQ3JlZGVudGlhbHM6IHRydWUgfSk7XG5cbiAgICAgIC8vIEFkZCBDU1JGIHRva2VuIGhlYWRlciBpZiBpdCdzIGEgbXV0YXRpbmcgcmVxdWVzdFxuICAgICAgaWYgKFsnUE9TVCcsICdQVVQnLCAnUEFUQ0gnLCAnREVMRVRFJ10uaW5jbHVkZXMocmVxLm1ldGhvZCkpIHtcbiAgICAgICAgY29uc3QgY3NyZlRva2VuID0gZ2V0Q3NyZlRva2VuKHRoaXMuY29uZmlnLmNzcmY/LmNvb2tpZU5hbWUgfHwgJ1hTUkYtVE9LRU4nKTtcbiAgICAgICAgaWYgKGNzcmZUb2tlbikge1xuICAgICAgICAgIGNsb25lZFJlcSA9IGNsb25lZFJlcS5jbG9uZSh7XG4gICAgICAgICAgICBzZXRIZWFkZXJzOiB7IFt0aGlzLmNvbmZpZy5jc3JmPy5oZWFkZXJOYW1lIHx8ICdYLVhTUkYtVE9LRU4nXTogY3NyZlRva2VuIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5leHQuaGFuZGxlKGNsb25lZFJlcSkucGlwZShcbiAgICAgICAgY2F0Y2hFcnJvcigoZXJyb3I6IEh0dHBFcnJvclJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yLnN0YXR1cyA9PT0gNDAxICYmICFyZXRyaWVkUmVxdWVzdHMuaGFzKHJlcSkpIHtcbiAgICAgICAgICAgIHJldHJpZWRSZXF1ZXN0cy5hZGQocmVxKTtcblxuICAgICAgICAgICAgaWYgKCFpc1JlZnJlc2hpbmcpIHtcbiAgICAgICAgICAgICAgaXNSZWZyZXNoaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgcmVmcmVzaFRva2VuU3ViamVjdC5uZXh0KG51bGwpO1xuXG4gICAgICAgICAgICAgIHJldHVybiBmcm9tKFxuICAgICAgICAgICAgICAgIHRoaXMuaHR0cFxuICAgICAgICAgICAgICAgICAgLnBvc3Q8eyBhY2Nlc3NUb2tlbj86IHN0cmluZyB9PihgJHtiYXNlVXJsfS9yZWZyZXNoYCwge30sIHsgd2l0aENyZWRlbnRpYWxzOiB0cnVlIH0pXG4gICAgICAgICAgICAgICAgICAudG9Qcm9taXNlKCksXG4gICAgICAgICAgICAgICkucGlwZShcbiAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgaXNSZWZyZXNoaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICByZWZyZXNoVG9rZW5TdWJqZWN0Lm5leHQoJ3JlZnJlc2hlZCcpO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIG5leHQuaGFuZGxlKGNsb25lZFJlcSk7XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgY2F0Y2hFcnJvcigocmVmcmVzaEVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpc1JlZnJlc2hpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgIHRoaXMuYXV0aFNlcnZpY2UubG9nb3V0KCk7XG4gICAgICAgICAgICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbdGhpcy5jb25maWcucmVkaXJlY3RzPy5zZXNzaW9uRXhwaXJlZCB8fCAnL2xvZ2luJ10pO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gcmVmcmVzaEVycm9yKTtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiByZWZyZXNoVG9rZW5TdWJqZWN0LnBpcGUoXG4gICAgICAgICAgICAgICAgZmlsdGVyKCh0b2tlbikgPT4gdG9rZW4gIT09IG51bGwpLFxuICAgICAgICAgICAgICAgIHRha2UoMSksXG4gICAgICAgICAgICAgICAgc3dpdGNoTWFwKCgpID0+IG5leHQuaGFuZGxlKGNsb25lZFJlcSkpLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycm9yKTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBKU09OIE1PREU6IERlbGVnYXRlIHRvIFNESyBmb3IgdG9rZW4gaGFuZGxpbmdcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgcmV0dXJuIG5leHQuaGFuZGxlKHJlcSk7XG4gIH1cbn1cbiJdfQ==