@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.
- package/esm2022/lib/auth.guard.mjs +83 -0
- package/esm2022/lib/auth.interceptor.mjs +158 -0
- package/esm2022/lib/social-redirect-callback.guard.mjs +81 -0
- package/esm2022/nauth-toolkit-client-angular.mjs +5 -0
- package/esm2022/ngmodule/auth.interceptor.class.mjs +109 -0
- package/esm2022/ngmodule/auth.service.mjs +777 -0
- package/esm2022/ngmodule/http-adapter.mjs +127 -0
- package/esm2022/ngmodule/nauth.module.mjs +65 -0
- package/esm2022/ngmodule/tokens.mjs +6 -0
- package/esm2022/public-api.mjs +19 -0
- package/esm2022/src/standalone/nauth-toolkit-client-angular-src-standalone.mjs +5 -0
- package/esm2022/src/standalone/public-api.mjs +12 -0
- package/esm2022/standalone/auth.guard.mjs +83 -0
- package/esm2022/standalone/auth.interceptor.mjs +158 -0
- package/esm2022/standalone/auth.service.mjs +777 -0
- package/esm2022/standalone/http-adapter.mjs +127 -0
- package/esm2022/standalone/nauth-toolkit-client-angular-standalone.mjs +5 -0
- package/esm2022/standalone/public-api.mjs +16 -0
- package/esm2022/standalone/social-redirect-callback.guard.mjs +81 -0
- package/esm2022/standalone/tokens.mjs +6 -0
- package/fesm2022/nauth-toolkit-client-angular-src-standalone.mjs +17 -0
- package/fesm2022/nauth-toolkit-client-angular-src-standalone.mjs.map +1 -0
- package/fesm2022/nauth-toolkit-client-angular-standalone.mjs +1229 -0
- package/fesm2022/nauth-toolkit-client-angular-standalone.mjs.map +1 -0
- package/fesm2022/nauth-toolkit-client-angular.mjs +1390 -0
- package/fesm2022/nauth-toolkit-client-angular.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/{src/lib/auth.guard.ts → lib/auth.guard.d.ts} +15 -37
- package/lib/auth.interceptor.d.ts +15 -0
- package/lib/social-redirect-callback.guard.d.ts +25 -0
- package/ngmodule/auth.interceptor.class.d.ts +34 -0
- package/ngmodule/auth.service.d.ts +580 -0
- package/ngmodule/http-adapter.d.ts +53 -0
- package/ngmodule/nauth.module.d.ts +31 -0
- package/{src/ngmodule/tokens.ts → ngmodule/tokens.d.ts} +1 -2
- package/package.json +30 -20
- package/{src/public-api.ts → public-api.d.ts} +0 -6
- package/src/standalone/index.d.ts +5 -0
- package/src/standalone/{public-api.ts → public-api.d.ts} +0 -2
- package/standalone/{auth.guard.ts → auth.guard.d.ts} +15 -37
- package/standalone/auth.interceptor.d.ts +15 -0
- package/standalone/auth.service.d.ts +580 -0
- package/standalone/http-adapter.d.ts +53 -0
- package/standalone/index.d.ts +5 -0
- package/standalone/{public-api.ts → public-api.d.ts} +1 -6
- package/standalone/social-redirect-callback.guard.d.ts +25 -0
- package/standalone/{tokens.ts → tokens.d.ts} +1 -2
- package/ng-package.json +0 -12
- package/src/lib/auth.interceptor.ts +0 -194
- package/src/lib/social-redirect-callback.guard.ts +0 -87
- package/src/ngmodule/auth.interceptor.class.ts +0 -124
- package/src/ngmodule/auth.service.ts +0 -865
- package/src/ngmodule/http-adapter.ts +0 -79
- package/src/ngmodule/nauth.module.ts +0 -59
- package/src/package.json +0 -11
- package/src/standalone/ng-package.json +0 -7
- package/src/standalone/package.json +0 -8
- package/standalone/auth.interceptor.ts +0 -194
- package/standalone/auth.service.ts +0 -865
- package/standalone/http-adapter.ts +0 -79
- package/standalone/ng-package.json +0 -7
- package/standalone/package.json +0 -8
- package/standalone/social-redirect-callback.guard.ts +0 -87
- package/tsconfig.json +0 -10
- package/tsconfig.lib.json +0 -28
- 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5pbnRlcmNlcHRvci5jbGFzcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9uZ21vZHVsZS9hdXRoLmludGVyY2VwdG9yLmNsYXNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBVW5ELE9BQU8sRUFBYyxVQUFVLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDMUcsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sVUFBVSxDQUFDOzs7OztBQUkvQzs7R0FFRztBQUNILElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQztBQUN6QixNQUFNLG1CQUFtQixHQUFHLElBQUksZUFBZSxDQUFnQixJQUFJLENBQUMsQ0FBQztBQUNyRSxNQUFNLGVBQWUsR0FBRyxJQUFJLE9BQU8sRUFBd0IsQ0FBQztBQUU1RDs7R0FFRztBQUNILFNBQVMsWUFBWSxDQUFDLFVBQWtCO0lBQ3RDLElBQUksT0FBTyxRQUFRLEtBQUssV0FBVztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ2pELE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLFFBQVEsVUFBVSxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQzlFLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0FBQ3JELENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFFSCxNQUFNLE9BQU8sb0JBQW9CO0lBRWlCO0lBQzdCO0lBQ0E7SUFDQTtJQUpuQixZQUNnRCxNQUF5QixFQUN0RCxJQUFnQixFQUNoQixXQUF3QixFQUN4QixNQUFjO1FBSGUsV0FBTSxHQUFOLE1BQU0sQ0FBbUI7UUFDdEQsU0FBSSxHQUFKLElBQUksQ0FBWTtRQUNoQixnQkFBVyxHQUFYLFdBQVcsQ0FBYTtRQUN4QixXQUFNLEdBQU4sTUFBTSxDQUFRO0lBQzlCLENBQUM7SUFFSixTQUFTLENBQUMsR0FBeUIsRUFBRSxJQUFpQjtRQUNwRCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQztRQUNoRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQztRQUVwQywrRUFBK0U7UUFDL0UsNkNBQTZDO1FBQzdDLCtFQUErRTtRQUMvRSxJQUFJLGFBQWEsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNoQyxJQUFJLFNBQVMsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsZUFBZSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7WUFFckQsbURBQW1EO1lBQ25ELElBQUksQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7Z0JBQzVELE1BQU0sU0FBUyxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxVQUFVLElBQUksWUFBWSxDQUFDLENBQUM7Z0JBQzdFLElBQUksU0FBUyxFQUFFLENBQUM7b0JBQ2QsU0FBUyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUM7d0JBQzFCLFVBQVUsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsVUFBVSxJQUFJLGNBQWMsQ0FBQyxFQUFFLFNBQVMsRUFBRTtxQkFDNUUsQ0FBQyxDQUFDO2dCQUNMLENBQUM7WUFDSCxDQUFDO1lBRUQsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksQ0FDaEMsVUFBVSxDQUFDLENBQUMsS0FBd0IsRUFBRSxFQUFFO2dCQUN0QyxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUN0RCxlQUFlLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUV6QixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7d0JBQ2xCLFlBQVksR0FBRyxJQUFJLENBQUM7d0JBQ3BCLG1CQUFtQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzt3QkFFL0IsT0FBTyxJQUFJLENBQ1QsSUFBSSxDQUFDLElBQUk7NkJBQ04sSUFBSSxDQUEyQixHQUFHLE9BQU8sVUFBVSxFQUFFLEVBQUUsRUFBRSxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUsQ0FBQzs2QkFDbkYsU0FBUyxFQUFFLENBQ2YsQ0FBQyxJQUFJLENBQ0osU0FBUyxDQUFDLEdBQUcsRUFBRTs0QkFDYixZQUFZLEdBQUcsS0FBSyxDQUFDOzRCQUNyQixtQkFBbUIsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7NEJBQ3RDLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQzt3QkFDaEMsQ0FBQyxDQUFDLEVBQ0YsVUFBVSxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7NEJBQzFCLFlBQVksR0FBRyxLQUFLLENBQUM7NEJBQ3JCLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLENBQUM7NEJBQzFCLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsY0FBYyxJQUFJLFFBQVEsQ0FBQyxDQUFDLENBQUM7NEJBQzFFLE9BQU8sVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLFlBQVksQ0FBQyxDQUFDO3dCQUN4QyxDQUFDLENBQUMsQ0FDSCxDQUFDO29CQUNKLENBQUM7eUJBQU0sQ0FBQzt3QkFDTixPQUFPLG1CQUFtQixDQUFDLElBQUksQ0FDN0IsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLEtBQUssSUFBSSxDQUFDLEVBQ2pDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFDUCxTQUFTLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUN4QyxDQUFDO29CQUNKLENBQUM7Z0JBQ0gsQ0FBQztnQkFFRCxPQUFPLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNqQyxDQUFDLENBQUMsQ0FDSCxDQUFDO1FBQ0osQ0FBQztRQUVELCtFQUErRTtRQUMvRSxnREFBZ0Q7UUFDaEQsK0VBQStFO1FBQy9FLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMxQixDQUFDO3dHQXhFVSxvQkFBb0Isa0JBRXJCLG1CQUFtQjs0R0FGbEIsb0JBQW9COzs0RkFBcEIsb0JBQW9CO2tCQURoQyxVQUFVOzswQkFHTixNQUFNOzJCQUFDLG1CQUFtQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIEluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgSHR0cEludGVyY2VwdG9yLFxuICBIdHRwUmVxdWVzdCxcbiAgSHR0cEhhbmRsZXIsXG4gIEh0dHBFdmVudCxcbiAgSHR0cENsaWVudCxcbiAgSHR0cEVycm9yUmVzcG9uc2UsXG59IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBjYXRjaEVycm9yLCBzd2l0Y2hNYXAsIHRocm93RXJyb3IsIGZpbHRlciwgdGFrZSwgQmVoYXZpb3JTdWJqZWN0LCBmcm9tIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBOQVVUSF9DTElFTlRfQ09ORklHIH0gZnJvbSAnLi90b2tlbnMnO1xuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tICcuL2F1dGguc2VydmljZSc7XG5pbXBvcnQgeyBOQXV0aENsaWVudENvbmZpZyB9IGZyb20gJ0BuYXV0aC10b29sa2l0L2NsaWVudCc7XG5cbi8qKlxuICogUmVmcmVzaCBzdGF0ZSBtYW5hZ2VtZW50LlxuICovXG5sZXQgaXNSZWZyZXNoaW5nID0gZmFsc2U7XG5jb25zdCByZWZyZXNoVG9rZW5TdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmcgfCBudWxsPihudWxsKTtcbmNvbnN0IHJldHJpZWRSZXF1ZXN0cyA9IG5ldyBXZWFrU2V0PEh0dHBSZXF1ZXN0PHVua25vd24+PigpO1xuXG4vKipcbiAqIEdldCBDU1JGIHRva2VuIGZyb20gY29va2llLlxuICovXG5mdW5jdGlvbiBnZXRDc3JmVG9rZW4oY29va2llTmFtZTogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgbWF0Y2ggPSBkb2N1bWVudC5jb29raWUubWF0Y2gobmV3IFJlZ0V4cChgKF58ICkke2Nvb2tpZU5hbWV9PShbXjtdKylgKSk7XG4gIHJldHVybiBtYXRjaCA/IGRlY29kZVVSSUNvbXBvbmVudChtYXRjaFsyXSkgOiBudWxsO1xufVxuXG4vKipcbiAqIENsYXNzLWJhc2VkIEhUVFAgaW50ZXJjZXB0b3IgZm9yIE5nTW9kdWxlIGFwcHMgKEFuZ3VsYXIgPCAxNykuXG4gKlxuICogRm9yIHN0YW5kYWxvbmUgY29tcG9uZW50cyAoQW5ndWxhciAxNyspLCB1c2UgdGhlIGZ1bmN0aW9uYWwgYGF1dGhJbnRlcmNlcHRvcmAgaW5zdGVhZC5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gYXBwLm1vZHVsZS50c1xuICogaW1wb3J0IHsgSFRUUF9JTlRFUkNFUFRPUlMgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG4gKiBpbXBvcnQgeyBBdXRoSW50ZXJjZXB0b3JDbGFzcyB9IGZyb20gJ0BuYXV0aC10b29sa2l0L2NsaWVudC1hbmd1bGFyJztcbiAqXG4gKiBATmdNb2R1bGUoe1xuICogICBwcm92aWRlcnM6IFtcbiAqICAgICB7IHByb3ZpZGU6IEhUVFBfSU5URVJDRVBUT1JTLCB1c2VDbGFzczogQXV0aEludGVyY2VwdG9yQ2xhc3MsIG11bHRpOiB0cnVlIH1cbiAqICAgXVxuICogfSlcbiAqIGBgYFxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQXV0aEludGVyY2VwdG9yQ2xhc3MgaW1wbGVtZW50cyBIdHRwSW50ZXJjZXB0b3Ige1xuICBjb25zdHJ1Y3RvcihcbiAgICBASW5qZWN0KE5BVVRIX0NMSUVOVF9DT05GSUcpIHByaXZhdGUgcmVhZG9ubHkgY29uZmlnOiBOQXV0aENsaWVudENvbmZpZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGh0dHA6IEh0dHBDbGllbnQsXG4gICAgcHJpdmF0ZSByZWFkb25seSBhdXRoU2VydmljZTogQXV0aFNlcnZpY2UsXG4gICAgcHJpdmF0ZSByZWFkb25seSByb3V0ZXI6IFJvdXRlcixcbiAgKSB7fVxuXG4gIGludGVyY2VwdChyZXE6IEh0dHBSZXF1ZXN0PHVua25vd24+LCBuZXh0OiBIdHRwSGFuZGxlcik6IE9ic2VydmFibGU8SHR0cEV2ZW50PHVua25vd24+PiB7XG4gICAgY29uc3QgdG9rZW5EZWxpdmVyeSA9IHRoaXMuY29uZmlnLnRva2VuRGVsaXZlcnk7XG4gICAgY29uc3QgYmFzZVVybCA9IHRoaXMuY29uZmlnLmJhc2VVcmw7XG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gQ09PS0lFUyBNT0RFOiB3aXRoQ3JlZGVudGlhbHMgKyBDU1JGIHRva2VuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIGlmICh0b2tlbkRlbGl2ZXJ5ID09PSAnY29va2llcycpIHtcbiAgICAgIGxldCBjbG9uZWRSZXEgPSByZXEuY2xvbmUoeyB3aXRoQ3JlZGVudGlhbHM6IHRydWUgfSk7XG5cbiAgICAgIC8vIEFkZCBDU1JGIHRva2VuIGhlYWRlciBpZiBpdCdzIGEgbXV0YXRpbmcgcmVxdWVzdFxuICAgICAgaWYgKFsnUE9TVCcsICdQVVQnLCAnUEFUQ0gnLCAnREVMRVRFJ10uaW5jbHVkZXMocmVxLm1ldGhvZCkpIHtcbiAgICAgICAgY29uc3QgY3NyZlRva2VuID0gZ2V0Q3NyZlRva2VuKHRoaXMuY29uZmlnLmNzcmY/LmNvb2tpZU5hbWUgfHwgJ1hTUkYtVE9LRU4nKTtcbiAgICAgICAgaWYgKGNzcmZUb2tlbikge1xuICAgICAgICAgIGNsb25lZFJlcSA9IGNsb25lZFJlcS5jbG9uZSh7XG4gICAgICAgICAgICBzZXRIZWFkZXJzOiB7IFt0aGlzLmNvbmZpZy5jc3JmPy5oZWFkZXJOYW1lIHx8ICdYLVhTUkYtVE9LRU4nXTogY3NyZlRva2VuIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5leHQuaGFuZGxlKGNsb25lZFJlcSkucGlwZShcbiAgICAgICAgY2F0Y2hFcnJvcigoZXJyb3I6IEh0dHBFcnJvclJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yLnN0YXR1cyA9PT0gNDAxICYmICFyZXRyaWVkUmVxdWVzdHMuaGFzKHJlcSkpIHtcbiAgICAgICAgICAgIHJldHJpZWRSZXF1ZXN0cy5hZGQocmVxKTtcblxuICAgICAgICAgICAgaWYgKCFpc1JlZnJlc2hpbmcpIHtcbiAgICAgICAgICAgICAgaXNSZWZyZXNoaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgcmVmcmVzaFRva2VuU3ViamVjdC5uZXh0KG51bGwpO1xuXG4gICAgICAgICAgICAgIHJldHVybiBmcm9tKFxuICAgICAgICAgICAgICAgIHRoaXMuaHR0cFxuICAgICAgICAgICAgICAgICAgLnBvc3Q8eyBhY2Nlc3NUb2tlbj86IHN0cmluZyB9PihgJHtiYXNlVXJsfS9yZWZyZXNoYCwge30sIHsgd2l0aENyZWRlbnRpYWxzOiB0cnVlIH0pXG4gICAgICAgICAgICAgICAgICAudG9Qcm9taXNlKCksXG4gICAgICAgICAgICAgICkucGlwZShcbiAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgaXNSZWZyZXNoaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICByZWZyZXNoVG9rZW5TdWJqZWN0Lm5leHQoJ3JlZnJlc2hlZCcpO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIG5leHQuaGFuZGxlKGNsb25lZFJlcSk7XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgY2F0Y2hFcnJvcigocmVmcmVzaEVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpc1JlZnJlc2hpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgIHRoaXMuYXV0aFNlcnZpY2UubG9nb3V0KCk7XG4gICAgICAgICAgICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbdGhpcy5jb25maWcucmVkaXJlY3RzPy5zZXNzaW9uRXhwaXJlZCB8fCAnL2xvZ2luJ10pO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gcmVmcmVzaEVycm9yKTtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiByZWZyZXNoVG9rZW5TdWJqZWN0LnBpcGUoXG4gICAgICAgICAgICAgICAgZmlsdGVyKCh0b2tlbikgPT4gdG9rZW4gIT09IG51bGwpLFxuICAgICAgICAgICAgICAgIHRha2UoMSksXG4gICAgICAgICAgICAgICAgc3dpdGNoTWFwKCgpID0+IG5leHQuaGFuZGxlKGNsb25lZFJlcSkpLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycm9yKTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBKU09OIE1PREU6IERlbGVnYXRlIHRvIFNESyBmb3IgdG9rZW4gaGFuZGxpbmdcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgcmV0dXJuIG5leHQuaGFuZGxlKHJlcSk7XG4gIH1cbn1cbiJdfQ==
|