primus-angular-auth 1.0.0

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.
@@ -0,0 +1,23 @@
1
+ import { Router } from '@angular/router';
2
+ import { inject } from '@angular/core';
3
+ import { PrimusAuthService } from './primus-auth.service';
4
+ import { map, filter, switchMap, take } from 'rxjs/operators';
5
+ import { PRIMUS_AUTH_CONFIG } from './primus-auth.tokens';
6
+ export const primusAuthGuard = (route, state) => {
7
+ const auth = inject(PrimusAuthService);
8
+ const router = inject(Router);
9
+ const config = inject(PRIMUS_AUTH_CONFIG);
10
+ // Wait for initialization to complete, then check authentication status
11
+ return auth.initialized$.pipe(filter((isInit) => isInit), // Wait until true
12
+ take(1), switchMap(() => auth.isAuthenticated$), take(1), map((isAuthenticated) => {
13
+ if (isAuthenticated) {
14
+ return true;
15
+ }
16
+ // Redirect to login
17
+ const loginPath = config.loginPath || '/login';
18
+ return router.createUrlTree([loginPath], {
19
+ queryParams: { returnUrl: state.url }
20
+ });
21
+ }));
22
+ };
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpbXVzLWF1dGguZ3VhcmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9hbmd1bGFyL3ByaW11cy1hdXRoL3NyYy9saWIvcHJpbXVzLWF1dGguZ3VhcmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFpQixNQUFNLEVBQXdELE1BQU0saUJBQWlCLENBQUM7QUFDOUcsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN2QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDOUQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFMUQsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFrQixDQUFDLEtBQTZCLEVBQUUsS0FBMEIsRUFBRSxFQUFFO0lBQ3hHLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM5QixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUUxQyx3RUFBd0U7SUFDeEUsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FDekIsTUFBTSxDQUFDLENBQUMsTUFBZSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxrQkFBa0I7SUFDdkQsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUNQLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFDdEMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUNQLEdBQUcsQ0FBQyxDQUFDLGVBQXdCLEVBQUUsRUFBRTtRQUM3QixJQUFJLGVBQWUsRUFBRTtZQUNqQixPQUFPLElBQUksQ0FBQztTQUNmO1FBRUQsb0JBQW9CO1FBQ3BCLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLElBQUksUUFBUSxDQUFDO1FBQy9DLE9BQU8sTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxFQUFFO1lBQ3JDLFdBQVcsRUFBRSxFQUFFLFNBQVMsRUFBRSxLQUFLLENBQUMsR0FBRyxFQUFFO1NBQ3hDLENBQUMsQ0FBQztJQUNQLENBQUMsQ0FBQyxDQUNMLENBQUM7QUFDTixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDYW5BY3RpdmF0ZUZuLCBSb3V0ZXIsIFVybFRyZWUsIEFjdGl2YXRlZFJvdXRlU25hcHNob3QsIFJvdXRlclN0YXRlU25hcHNob3QgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xyXG5pbXBvcnQgeyBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgUHJpbXVzQXV0aFNlcnZpY2UgfSBmcm9tICcuL3ByaW11cy1hdXRoLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBtYXAsIGZpbHRlciwgc3dpdGNoTWFwLCB0YWtlIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBQUklNVVNfQVVUSF9DT05GSUcgfSBmcm9tICcuL3ByaW11cy1hdXRoLnRva2Vucyc7XHJcblxyXG5leHBvcnQgY29uc3QgcHJpbXVzQXV0aEd1YXJkOiBDYW5BY3RpdmF0ZUZuID0gKHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90LCBzdGF0ZTogUm91dGVyU3RhdGVTbmFwc2hvdCkgPT4ge1xyXG4gICAgY29uc3QgYXV0aCA9IGluamVjdChQcmltdXNBdXRoU2VydmljZSk7XHJcbiAgICBjb25zdCByb3V0ZXIgPSBpbmplY3QoUm91dGVyKTtcclxuICAgIGNvbnN0IGNvbmZpZyA9IGluamVjdChQUklNVVNfQVVUSF9DT05GSUcpO1xyXG5cclxuICAgIC8vIFdhaXQgZm9yIGluaXRpYWxpemF0aW9uIHRvIGNvbXBsZXRlLCB0aGVuIGNoZWNrIGF1dGhlbnRpY2F0aW9uIHN0YXR1c1xyXG4gICAgcmV0dXJuIGF1dGguaW5pdGlhbGl6ZWQkLnBpcGUoXHJcbiAgICAgICAgZmlsdGVyKChpc0luaXQ6IGJvb2xlYW4pID0+IGlzSW5pdCksIC8vIFdhaXQgdW50aWwgdHJ1ZVxyXG4gICAgICAgIHRha2UoMSksXHJcbiAgICAgICAgc3dpdGNoTWFwKCgpID0+IGF1dGguaXNBdXRoZW50aWNhdGVkJCksXHJcbiAgICAgICAgdGFrZSgxKSxcclxuICAgICAgICBtYXAoKGlzQXV0aGVudGljYXRlZDogYm9vbGVhbikgPT4ge1xyXG4gICAgICAgICAgICBpZiAoaXNBdXRoZW50aWNhdGVkKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gUmVkaXJlY3QgdG8gbG9naW5cclxuICAgICAgICAgICAgY29uc3QgbG9naW5QYXRoID0gY29uZmlnLmxvZ2luUGF0aCB8fCAnL2xvZ2luJztcclxuICAgICAgICAgICAgcmV0dXJuIHJvdXRlci5jcmVhdGVVcmxUcmVlKFtsb2dpblBhdGhdLCB7XHJcbiAgICAgICAgICAgICAgICBxdWVyeVBhcmFtczogeyByZXR1cm5Vcmw6IHN0YXRlLnVybCB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pXHJcbiAgICApO1xyXG59O1xyXG4iXX0=
@@ -0,0 +1,45 @@
1
+ import { inject } from '@angular/core';
2
+ import { catchError, throwError } from 'rxjs';
3
+ import { PrimusAuthService } from './primus-auth.service';
4
+ export const primusAuthInterceptor = (req, next) => {
5
+ const authService = inject(PrimusAuthService);
6
+ // 1. Add CSRF Header to non-GET requests
7
+ // Double-Submit Cookie Pattern: Read XSRF-TOKEN cookie and mirror in header.
8
+ let request = req;
9
+ if (req.method !== 'GET' && req.method !== 'HEAD' && req.method !== 'OPTIONS') {
10
+ const token = getCookie('XSRF-TOKEN') || '';
11
+ request = req.clone({
12
+ setHeaders: {
13
+ 'X-Primus-CSRF': token
14
+ },
15
+ withCredentials: true // Ensure cookies are sent
16
+ });
17
+ }
18
+ else {
19
+ // Determine if we need credentials for GETs?
20
+ // Usually yes for API calls to our backend.
21
+ // We assume calls to same origin or API URL need creds.
22
+ request = req.clone({
23
+ withCredentials: true
24
+ });
25
+ }
26
+ return next(request).pipe(catchError((error) => {
27
+ // 2. Handle 401 Unauthorized
28
+ if (error.status === 401) {
29
+ authService.handleUnauthorized();
30
+ }
31
+ return throwError(() => error);
32
+ }));
33
+ };
34
+ function getCookie(name) {
35
+ try {
36
+ if (typeof document === 'undefined')
37
+ return null;
38
+ const matches = document.cookie.match(new RegExp('(?:^|; )' + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + '=([^;]*)'));
39
+ return matches ? decodeURIComponent(matches[1]) : null;
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpbXVzLWF1dGguaW50ZXJjZXB0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9hbmd1bGFyL3ByaW11cy1hdXRoL3NyYy9saWIvcHJpbXVzLWF1dGguaW50ZXJjZXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN2QyxPQUFPLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM5QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUUxRCxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBc0IsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUU7SUFDbEUsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFFMUMseUNBQXlDO0lBQ3pDLDZFQUE2RTtJQUM3RSxJQUFJLE9BQU8sR0FBRyxHQUFHLENBQUM7SUFDbEIsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLEtBQUssSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLE1BQU0sSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRTtRQUMzRSxNQUFNLEtBQUssR0FBRyxTQUFTLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzVDLE9BQU8sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDO1lBQ2hCLFVBQVUsRUFBRTtnQkFDUixlQUFlLEVBQUUsS0FBSzthQUN6QjtZQUNELGVBQWUsRUFBRSxJQUFJLENBQUMsMEJBQTBCO1NBQ25ELENBQUMsQ0FBQztLQUNOO1NBQU07UUFDSCw2Q0FBNkM7UUFDN0MsNENBQTRDO1FBQzVDLHdEQUF3RDtRQUN4RCxPQUFPLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQztZQUNoQixlQUFlLEVBQUUsSUFBSTtTQUN4QixDQUFDLENBQUM7S0FDTjtJQUVELE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FDckIsVUFBVSxDQUFDLENBQUMsS0FBd0IsRUFBRSxFQUFFO1FBQ3BDLDZCQUE2QjtRQUM3QixJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssR0FBRyxFQUFFO1lBQ3RCLFdBQVcsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1NBQ3BDO1FBQ0QsT0FBTyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDbkMsQ0FBQyxDQUFDLENBQ0wsQ0FBQztBQUNOLENBQUMsQ0FBQztBQUVGLFNBQVMsU0FBUyxDQUFDLElBQVk7SUFDM0IsSUFBSTtRQUNBLElBQUksT0FBTyxRQUFRLEtBQUssV0FBVztZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQ2pELE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLDhCQUE4QixFQUFFLE1BQU0sQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUM7UUFDbEksT0FBTyxPQUFPLENBQUMsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7S0FDMUQ7SUFBQyxNQUFNO1FBQ0osT0FBTyxJQUFJLENBQUM7S0FDZjtBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBIdHRwSW50ZXJjZXB0b3JGbiwgSHR0cEVycm9yUmVzcG9uc2UgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XHJcbmltcG9ydCB7IGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBjYXRjaEVycm9yLCB0aHJvd0Vycm9yIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IFByaW11c0F1dGhTZXJ2aWNlIH0gZnJvbSAnLi9wcmltdXMtYXV0aC5zZXJ2aWNlJztcclxuXHJcbmV4cG9ydCBjb25zdCBwcmltdXNBdXRoSW50ZXJjZXB0b3I6IEh0dHBJbnRlcmNlcHRvckZuID0gKHJlcSwgbmV4dCkgPT4ge1xyXG4gICAgY29uc3QgYXV0aFNlcnZpY2UgPSBpbmplY3QoUHJpbXVzQXV0aFNlcnZpY2UpO1xyXG5cclxuICAgICAgICAvLyAxLiBBZGQgQ1NSRiBIZWFkZXIgdG8gbm9uLUdFVCByZXF1ZXN0c1xyXG4gICAgICAgIC8vIERvdWJsZS1TdWJtaXQgQ29va2llIFBhdHRlcm46IFJlYWQgWFNSRi1UT0tFTiBjb29raWUgYW5kIG1pcnJvciBpbiBoZWFkZXIuXHJcbiAgICAgICAgbGV0IHJlcXVlc3QgPSByZXE7XHJcbiAgICAgICAgaWYgKHJlcS5tZXRob2QgIT09ICdHRVQnICYmIHJlcS5tZXRob2QgIT09ICdIRUFEJyAmJiByZXEubWV0aG9kICE9PSAnT1BUSU9OUycpIHtcclxuICAgICAgICAgICAgY29uc3QgdG9rZW4gPSBnZXRDb29raWUoJ1hTUkYtVE9LRU4nKSB8fCAnJztcclxuICAgICAgICAgICAgcmVxdWVzdCA9IHJlcS5jbG9uZSh7XHJcbiAgICAgICAgICAgICAgICBzZXRIZWFkZXJzOiB7XHJcbiAgICAgICAgICAgICAgICAgICAgJ1gtUHJpbXVzLUNTUkYnOiB0b2tlblxyXG4gICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgIHdpdGhDcmVkZW50aWFsczogdHJ1ZSAvLyBFbnN1cmUgY29va2llcyBhcmUgc2VudFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAvLyBEZXRlcm1pbmUgaWYgd2UgbmVlZCBjcmVkZW50aWFscyBmb3IgR0VUcz9cclxuICAgICAgICAgICAgLy8gVXN1YWxseSB5ZXMgZm9yIEFQSSBjYWxscyB0byBvdXIgYmFja2VuZC5cclxuICAgICAgICAgICAgLy8gV2UgYXNzdW1lIGNhbGxzIHRvIHNhbWUgb3JpZ2luIG9yIEFQSSBVUkwgbmVlZCBjcmVkcy5cclxuICAgICAgICAgICAgcmVxdWVzdCA9IHJlcS5jbG9uZSh7XHJcbiAgICAgICAgICAgICAgICB3aXRoQ3JlZGVudGlhbHM6IHRydWVcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgXHJcbiAgICAgICAgcmV0dXJuIG5leHQocmVxdWVzdCkucGlwZShcclxuICAgICAgICAgICAgY2F0Y2hFcnJvcigoZXJyb3I6IEh0dHBFcnJvclJlc3BvbnNlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAvLyAyLiBIYW5kbGUgNDAxIFVuYXV0aG9yaXplZFxyXG4gICAgICAgICAgICAgICAgaWYgKGVycm9yLnN0YXR1cyA9PT0gNDAxKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYXV0aFNlcnZpY2UuaGFuZGxlVW5hdXRob3JpemVkKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuICAgIH07XHJcbiAgICBcclxuICAgIGZ1bmN0aW9uIGdldENvb2tpZShuYW1lOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ID09PSAndW5kZWZpbmVkJykgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgICAgIGNvbnN0IG1hdGNoZXMgPSBkb2N1bWVudC5jb29raWUubWF0Y2gobmV3IFJlZ0V4cCgnKD86Xnw7ICknICsgbmFtZS5yZXBsYWNlKC8oW1xcLiQ/Knx7fVxcKFxcKVxcW1xcXVxcXFxcXC9cXCteXSkvZywgJ1xcXFwkMScpICsgJz0oW147XSopJykpO1xyXG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hlcyA/IGRlY29kZVVSSUNvbXBvbmVudChtYXRjaGVzWzFdKSA6IG51bGw7XHJcbiAgICAgICAgfSBjYXRjaCB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuIl19
@@ -0,0 +1,29 @@
1
+ import { makeEnvironmentProviders, APP_INITIALIZER, PLATFORM_ID } from '@angular/core';
2
+ import { provideHttpClient, withInterceptors } from '@angular/common/http';
3
+ import { PRIMUS_AUTH_CONFIG } from './primus-auth.tokens';
4
+ import { PrimusAuthService } from './primus-auth.service';
5
+ import { primusAuthInterceptor } from './primus-auth.interceptor';
6
+ export function providePrimusAuth(config) {
7
+ return makeEnvironmentProviders([
8
+ {
9
+ provide: PRIMUS_AUTH_CONFIG,
10
+ useValue: config
11
+ },
12
+ PrimusAuthService,
13
+ provideHttpClient(withInterceptors([primusAuthInterceptor])),
14
+ {
15
+ provide: APP_INITIALIZER,
16
+ useFactory: (auth, platform) => () => {
17
+ // We trigger checkSession in constructor, but we can also do it here if we want to await it.
18
+ // However, awaiting APP_INITIALIZER blocks the whole app render.
19
+ // Better to let it run in background and use the Guard to block specific routes.
20
+ // So we just ensure service is instantiated.
21
+ // Actually, checkSession is already called in constructor.
22
+ // This APP_INITIALIZER forces the service to be created immediately on app start.
23
+ },
24
+ deps: [PrimusAuthService, PLATFORM_ID],
25
+ multi: true
26
+ }
27
+ ]);
28
+ }
29
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpbXVzLWF1dGgucHJvdmlkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9hbmd1bGFyL3ByaW11cy1hdXRoL3NyYy9saWIvcHJpbXVzLWF1dGgucHJvdmlkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUF3Qix3QkFBd0IsRUFBWSxlQUFlLEVBQUUsV0FBVyxFQUFVLE1BQU0sZUFBZSxDQUFDO0FBQy9ILE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRTNFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzFELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzFELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBR2xFLE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxNQUF3QjtJQUN0RCxPQUFPLHdCQUF3QixDQUFDO1FBQzVCO1lBQ0ksT0FBTyxFQUFFLGtCQUFrQjtZQUMzQixRQUFRLEVBQUUsTUFBTTtTQUNuQjtRQUNELGlCQUFpQjtRQUNqQixpQkFBaUIsQ0FDYixnQkFBZ0IsQ0FBQyxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FDNUM7UUFDRDtZQUNJLE9BQU8sRUFBRSxlQUFlO1lBQ3hCLFVBQVUsRUFBRSxDQUFDLElBQXVCLEVBQUUsUUFBZ0IsRUFBRSxFQUFFLENBQUMsR0FBRyxFQUFFO2dCQUM1RCw2RkFBNkY7Z0JBQzdGLGlFQUFpRTtnQkFDakUsaUZBQWlGO2dCQUNqRiw2Q0FBNkM7Z0JBRTdDLDJEQUEyRDtnQkFDM0Qsa0ZBQWtGO1lBQ3RGLENBQUM7WUFDRCxJQUFJLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSxXQUFXLENBQUM7WUFDdEMsS0FBSyxFQUFFLElBQUk7U0FDZDtLQUNKLENBQUMsQ0FBQztBQUNQLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBFbnZpcm9ubWVudFByb3ZpZGVycywgbWFrZUVudmlyb25tZW50UHJvdmlkZXJzLCBQcm92aWRlciwgQVBQX0lOSVRJQUxJWkVSLCBQTEFURk9STV9JRCwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IHByb3ZpZGVIdHRwQ2xpZW50LCB3aXRoSW50ZXJjZXB0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xyXG5pbXBvcnQgeyBQcmltdXNBdXRoQ29uZmlnIH0gZnJvbSAnLi9wcmltdXMtYXV0aC50eXBlcyc7XHJcbmltcG9ydCB7IFBSSU1VU19BVVRIX0NPTkZJRyB9IGZyb20gJy4vcHJpbXVzLWF1dGgudG9rZW5zJztcclxuaW1wb3J0IHsgUHJpbXVzQXV0aFNlcnZpY2UgfSBmcm9tICcuL3ByaW11cy1hdXRoLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBwcmltdXNBdXRoSW50ZXJjZXB0b3IgfSBmcm9tICcuL3ByaW11cy1hdXRoLmludGVyY2VwdG9yJztcclxuaW1wb3J0IHsgaXNQbGF0Zm9ybUJyb3dzZXIgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIHByb3ZpZGVQcmltdXNBdXRoKGNvbmZpZzogUHJpbXVzQXV0aENvbmZpZyk6IEVudmlyb25tZW50UHJvdmlkZXJzIHtcclxuICAgIHJldHVybiBtYWtlRW52aXJvbm1lbnRQcm92aWRlcnMoW1xyXG4gICAgICAgIHtcclxuICAgICAgICAgICAgcHJvdmlkZTogUFJJTVVTX0FVVEhfQ09ORklHLFxyXG4gICAgICAgICAgICB1c2VWYWx1ZTogY29uZmlnXHJcbiAgICAgICAgfSxcclxuICAgICAgICBQcmltdXNBdXRoU2VydmljZSxcclxuICAgICAgICBwcm92aWRlSHR0cENsaWVudChcclxuICAgICAgICAgICAgd2l0aEludGVyY2VwdG9ycyhbcHJpbXVzQXV0aEludGVyY2VwdG9yXSlcclxuICAgICAgICApLFxyXG4gICAgICAgIHtcclxuICAgICAgICAgICAgcHJvdmlkZTogQVBQX0lOSVRJQUxJWkVSLFxyXG4gICAgICAgICAgICB1c2VGYWN0b3J5OiAoYXV0aDogUHJpbXVzQXV0aFNlcnZpY2UsIHBsYXRmb3JtOiBPYmplY3QpID0+ICgpID0+IHtcclxuICAgICAgICAgICAgICAgIC8vIFdlIHRyaWdnZXIgY2hlY2tTZXNzaW9uIGluIGNvbnN0cnVjdG9yLCBidXQgd2UgY2FuIGFsc28gZG8gaXQgaGVyZSBpZiB3ZSB3YW50IHRvIGF3YWl0IGl0LlxyXG4gICAgICAgICAgICAgICAgLy8gSG93ZXZlciwgYXdhaXRpbmcgQVBQX0lOSVRJQUxJWkVSIGJsb2NrcyB0aGUgd2hvbGUgYXBwIHJlbmRlci5cclxuICAgICAgICAgICAgICAgIC8vIEJldHRlciB0byBsZXQgaXQgcnVuIGluIGJhY2tncm91bmQgYW5kIHVzZSB0aGUgR3VhcmQgdG8gYmxvY2sgc3BlY2lmaWMgcm91dGVzLlxyXG4gICAgICAgICAgICAgICAgLy8gU28gd2UganVzdCBlbnN1cmUgc2VydmljZSBpcyBpbnN0YW50aWF0ZWQuXHJcblxyXG4gICAgICAgICAgICAgICAgLy8gQWN0dWFsbHksIGNoZWNrU2Vzc2lvbiBpcyBhbHJlYWR5IGNhbGxlZCBpbiBjb25zdHJ1Y3Rvci5cclxuICAgICAgICAgICAgICAgIC8vIFRoaXMgQVBQX0lOSVRJQUxJWkVSIGZvcmNlcyB0aGUgc2VydmljZSB0byBiZSBjcmVhdGVkIGltbWVkaWF0ZWx5IG9uIGFwcCBzdGFydC5cclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgZGVwczogW1ByaW11c0F1dGhTZXJ2aWNlLCBQTEFURk9STV9JRF0sXHJcbiAgICAgICAgICAgIG11bHRpOiB0cnVlXHJcbiAgICAgICAgfVxyXG4gICAgXSk7XHJcbn1cclxuIl19
@@ -0,0 +1,161 @@
1
+ import { Injectable, Inject, signal, computed, PLATFORM_ID } from '@angular/core';
2
+ import { isPlatformBrowser } from '@angular/common';
3
+ import { catchError, map, tap } from 'rxjs/operators';
4
+ import { of, BehaviorSubject, interval } from 'rxjs';
5
+ import { PRIMUS_AUTH_CONFIG } from './primus-auth.tokens';
6
+ import * as i0 from "@angular/core";
7
+ import * as i1 from "@angular/common/http";
8
+ import * as i2 from "@angular/router";
9
+ import * as i3 from "@angular/common";
10
+ export class PrimusAuthService {
11
+ http;
12
+ router;
13
+ location;
14
+ config;
15
+ platformId;
16
+ // Reactive State (Signals)
17
+ _user = signal(null);
18
+ _isLoading = signal(true);
19
+ user = this._user.asReadonly();
20
+ isLoading = this._isLoading.asReadonly();
21
+ isAuthenticated = computed(() => !!this._user());
22
+ // Legacy Observable support
23
+ user$ = new BehaviorSubject(null);
24
+ isAuthenticated$ = this.user$.pipe(map(u => !!u));
25
+ initialized$ = new BehaviorSubject(false);
26
+ heartbeatSub = null;
27
+ HEARTBEAT_INTERVAL = 5 * 60 * 1000; // 5 minutes
28
+ constructor(http, router, location, config, platformId) {
29
+ this.http = http;
30
+ this.router = router;
31
+ this.location = location;
32
+ this.config = config;
33
+ this.platformId = platformId;
34
+ this.checkSession();
35
+ }
36
+ ngOnDestroy() {
37
+ this.stopHeartbeat();
38
+ }
39
+ /**
40
+ * Checks /api/auth/me to see if user is logged in.
41
+ * Should be called on app startup.
42
+ */
43
+ checkSession() {
44
+ if (!isPlatformBrowser(this.platformId)) {
45
+ this._isLoading.set(false);
46
+ this.initialized$.next(true);
47
+ return;
48
+ }
49
+ this._isLoading.set(true);
50
+ this.fetchUser().subscribe(() => {
51
+ this._isLoading.set(false);
52
+ this.initialized$.next(true);
53
+ });
54
+ }
55
+ fetchUser() {
56
+ const endpoint = `${this.config.apiUrl}/api/auth/me`;
57
+ return this.http.get(endpoint, { withCredentials: true }).pipe(tap(user => this.updateState(user)), catchError(() => {
58
+ this.updateState(null);
59
+ return of(null);
60
+ }));
61
+ }
62
+ /**
63
+ * Performs a local login (username/password) via the Backend Broker.
64
+ * The backend must accept a POST to /api/auth/login and set a cookie.
65
+ */
66
+ login(credentials) {
67
+ const endpoint = `${this.config.apiUrl}/api/auth/login`;
68
+ // We expect the backend to return the User object on success (or we fetch it)
69
+ // If the backend returns just 200 OK, we might need to chain a fetchUser()
70
+ return this.http.post(endpoint, credentials, { withCredentials: true }).pipe(tap(user => {
71
+ // If the backend returns the user directly, great.
72
+ // If it returns a generic success, we might get 'null' here if typing doesn't match.
73
+ // For safety, if we get a success response, we can also force-fetch the user to be sure.
74
+ if (user && user.email) {
75
+ this.updateState(user);
76
+ }
77
+ else {
78
+ // Fallback: Fetch user info if response was just { success: true }
79
+ this.fetchUser().subscribe();
80
+ }
81
+ }));
82
+ }
83
+ /**
84
+ * Redirects the browser to the backend login endpoint for the provider.
85
+ * e.g. /api/auth/azure, /api/auth/auth0
86
+ */
87
+ loginWithProvider(provider, redirectUrl) {
88
+ const returnUrl = redirectUrl || this.router.url;
89
+ // We can pass returnUrl if backend supports it, usually configured globally
90
+ // or via a query param handled by the Resolution logic.
91
+ // For now we assume standard flow or basic redirect.
92
+ const target = `${this.config.apiUrl}/api/auth/${provider}`;
93
+ window.location.href = target;
94
+ }
95
+ logout() {
96
+ const endpoint = `${this.config.apiUrl}/api/auth/logout`;
97
+ this.http.post(endpoint, {}, {
98
+ withCredentials: true
99
+ // Interceptor will add CSRF header automatically
100
+ }).subscribe({
101
+ next: () => {
102
+ this.updateState(null);
103
+ const redirect = this.config.logoutRedirect || '/login';
104
+ this.router.navigateByUrl(redirect);
105
+ },
106
+ error: () => {
107
+ // Force logout state even if API failed
108
+ this.updateState(null);
109
+ const redirect = this.config.logoutRedirect || '/login';
110
+ this.router.navigateByUrl(redirect);
111
+ }
112
+ });
113
+ }
114
+ updateState(user) {
115
+ this._user.set(user);
116
+ this.user$.next(user);
117
+ // Auto-sync signal to loading state
118
+ if (user) {
119
+ this._isLoading.set(false);
120
+ this.startHeartbeat();
121
+ }
122
+ else {
123
+ this.stopHeartbeat();
124
+ }
125
+ }
126
+ // Called by Interceptor on 401
127
+ handleUnauthorized() {
128
+ this.updateState(null);
129
+ }
130
+ startHeartbeat() {
131
+ if (!isPlatformBrowser(this.platformId))
132
+ return;
133
+ if (this.heartbeatSub)
134
+ return; // Already running
135
+ this.heartbeatSub = interval(this.HEARTBEAT_INTERVAL).subscribe(() => {
136
+ // Quietly check session
137
+ this.fetchUser().subscribe();
138
+ });
139
+ }
140
+ stopHeartbeat() {
141
+ if (this.heartbeatSub) {
142
+ this.heartbeatSub.unsubscribe();
143
+ this.heartbeatSub = null;
144
+ }
145
+ }
146
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PrimusAuthService, deps: [{ token: i1.HttpClient }, { token: i2.Router }, { token: i3.Location }, { token: PRIMUS_AUTH_CONFIG }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable });
147
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PrimusAuthService, providedIn: 'root' });
148
+ }
149
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PrimusAuthService, decorators: [{
150
+ type: Injectable,
151
+ args: [{
152
+ providedIn: 'root'
153
+ }]
154
+ }], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.Router }, { type: i3.Location }, { type: undefined, decorators: [{
155
+ type: Inject,
156
+ args: [PRIMUS_AUTH_CONFIG]
157
+ }] }, { type: Object, decorators: [{
158
+ type: Inject,
159
+ args: [PLATFORM_ID]
160
+ }] }] });
161
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpbXVzLWF1dGguc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2FuZ3VsYXIvcHJpbXVzLWF1dGgvc3JjL2xpYi9wcmltdXMtYXV0aC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFhLE1BQU0sZUFBZSxDQUFDO0FBRzdGLE9BQU8sRUFBRSxpQkFBaUIsRUFBWSxNQUFNLGlCQUFpQixDQUFDO0FBQzlELE9BQU8sRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3RELE9BQU8sRUFBYyxFQUFFLEVBQUUsZUFBZSxFQUFnQixRQUFRLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFL0UsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7Ozs7O0FBSzFELE1BQU0sT0FBTyxpQkFBaUI7SUFrQmQ7SUFDQTtJQUNBO0lBQzRCO0lBQ1A7SUFyQmpDLDJCQUEyQjtJQUNuQixLQUFLLEdBQUcsTUFBTSxDQUFvQixJQUFJLENBQUMsQ0FBQztJQUN4QyxVQUFVLEdBQUcsTUFBTSxDQUFVLElBQUksQ0FBQyxDQUFDO0lBRTNCLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQy9CLFNBQVMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ3pDLGVBQWUsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBRWpFLDRCQUE0QjtJQUNaLEtBQUssR0FBRyxJQUFJLGVBQWUsQ0FBb0IsSUFBSSxDQUFDLENBQUM7SUFDckQsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FB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QyxXQUFXIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgSW5qZWN0LCBzaWduYWwsIGNvbXB1dGVkLCBQTEFURk9STV9JRCwgT25EZXN0cm95IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XHJcbmltcG9ydCB7IFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XHJcbmltcG9ydCB7IGlzUGxhdGZvcm1Ccm93c2VyLCBMb2NhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7IGNhdGNoRXJyb3IsIG1hcCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBvZiwgQmVoYXZpb3JTdWJqZWN0LCBTdWJzY3JpcHRpb24sIGludGVydmFsIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IFByaW11c0F1dGhDb25maWcsIFByaW11c1VzZXIgfSBmcm9tICcuL3ByaW11cy1hdXRoLnR5cGVzJztcclxuaW1wb3J0IHsgUFJJTVVTX0FVVEhfQ09ORklHIH0gZnJvbSAnLi9wcmltdXMtYXV0aC50b2tlbnMnO1xyXG5cclxuQEluamVjdGFibGUoe1xyXG4gICAgcHJvdmlkZWRJbjogJ3Jvb3QnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBQcmltdXNBdXRoU2VydmljZSBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XHJcbiAgICAvLyBSZWFjdGl2ZSBTdGF0ZSAoU2lnbmFscylcclxuICAgIHByaXZhdGUgX3VzZXIgPSBzaWduYWw8UHJpbXVzVXNlciB8IG51bGw+KG51bGwpO1xyXG4gICAgcHJpdmF0ZSBfaXNMb2FkaW5nID0gc2lnbmFsPGJvb2xlYW4+KHRydWUpO1xyXG5cclxuICAgIHB1YmxpYyByZWFkb25seSB1c2VyID0gdGhpcy5fdXNlci5hc1JlYWRvbmx5KCk7XHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgaXNMb2FkaW5nID0gdGhpcy5faXNMb2FkaW5nLmFzUmVhZG9ubHkoKTtcclxuICAgIHB1YmxpYyByZWFkb25seSBpc0F1dGhlbnRpY2F0ZWQgPSBjb21wdXRlZCgoKSA9PiAhIXRoaXMuX3VzZXIoKSk7XHJcblxyXG4gICAgLy8gTGVnYWN5IE9ic2VydmFibGUgc3VwcG9ydFxyXG4gICAgcHVibGljIHJlYWRvbmx5IHVzZXIkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxQcmltdXNVc2VyIHwgbnVsbD4obnVsbCk7XHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgaXNBdXRoZW50aWNhdGVkJCA9IHRoaXMudXNlciQucGlwZShtYXAodSA9PiAhIXUpKTtcclxuICAgIHB1YmxpYyByZWFkb25seSBpbml0aWFsaXplZCQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcclxuXHJcbiAgICBwcml2YXRlIGhlYXJ0YmVhdFN1YjogU3Vic2NyaXB0aW9uIHwgbnVsbCA9IG51bGw7XHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IEhFQVJUQkVBVF9JTlRFUlZBTCA9IDUgKiA2MCAqIDEwMDA7IC8vIDUgbWludXRlc1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICAgIHByaXZhdGUgaHR0cDogSHR0cENsaWVudCxcclxuICAgICAgICBwcml2YXRlIHJvdXRlcjogUm91dGVyLFxyXG4gICAgICAgIHByaXZhdGUgbG9jYXRpb246IExvY2F0aW9uLFxyXG4gICAgICAgIEBJbmplY3QoUFJJTVVTX0FVVEhfQ09ORklHKSBwcml2YXRlIGNvbmZpZzogUHJpbXVzQXV0aENvbmZpZyxcclxuICAgICAgICBASW5qZWN0KFBMQVRGT1JNX0lEKSBwcml2YXRlIHBsYXRmb3JtSWQ6IE9iamVjdFxyXG4gICAgKSB7XHJcbiAgICAgICAgdGhpcy5jaGVja1Nlc3Npb24oKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5zdG9wSGVhcnRiZWF0KCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDaGVja3MgL2FwaS9hdXRoL21lIHRvIHNlZSBpZiB1c2VyIGlzIGxvZ2dlZCBpbi5cclxuICAgICAqIFNob3VsZCBiZSBjYWxsZWQgb24gYXBwIHN0YXJ0dXAuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjaGVja1Nlc3Npb24oKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKCFpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2lzTG9hZGluZy5zZXQoZmFsc2UpO1xyXG4gICAgICAgICAgICB0aGlzLmluaXRpYWxpemVkJC5uZXh0KHRydWUpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLl9pc0xvYWRpbmcuc2V0KHRydWUpO1xyXG4gICAgICAgIHRoaXMuZmV0Y2hVc2VyKCkuc3Vic2NyaWJlKCgpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5faXNMb2FkaW5nLnNldChmYWxzZSk7XHJcbiAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZWQkLm5leHQodHJ1ZSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBmZXRjaFVzZXIoKTogT2JzZXJ2YWJsZTxQcmltdXNVc2VyIHwgbnVsbD4ge1xyXG4gICAgICAgIGNvbnN0IGVuZHBvaW50ID0gYCR7dGhpcy5jb25maWcuYXBpVXJsfS9hcGkvYXV0aC9tZWA7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQ8UHJpbXVzVXNlcj4oZW5kcG9pbnQsIHsgd2l0aENyZWRlbnRpYWxzOiB0cnVlIH0pLnBpcGUoXHJcbiAgICAgICAgICAgIHRhcCh1c2VyID0+IHRoaXMudXBkYXRlU3RhdGUodXNlcikpLFxyXG4gICAgICAgICAgICBjYXRjaEVycm9yKCgpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlU3RhdGUobnVsbCk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gb2YobnVsbCk7XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFBlcmZvcm1zIGEgbG9jYWwgbG9naW4gKHVzZXJuYW1lL3Bhc3N3b3JkKSB2aWEgdGhlIEJhY2tlbmQgQnJva2VyLlxyXG4gICAgICogVGhlIGJhY2tlbmQgbXVzdCBhY2NlcHQgYSBQT1NUIHRvIC9hcGkvYXV0aC9sb2dpbiBhbmQgc2V0IGEgY29va2llLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9naW4oY3JlZGVudGlhbHM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBPYnNlcnZhYmxlPFByaW11c1VzZXIgfCBudWxsPiB7XHJcbiAgICAgICAgY29uc3QgZW5kcG9pbnQgPSBgJHt0aGlzLmNvbmZpZy5hcGlVcmx9L2FwaS9hdXRoL2xvZ2luYDtcclxuICAgICAgICAvLyBXZSBleHBlY3QgdGhlIGJhY2tlbmQgdG8gcmV0dXJuIHRoZSBVc2VyIG9iamVjdCBvbiBzdWNjZXNzIChvciB3ZSBmZXRjaCBpdClcclxuICAgICAgICAvLyBJZiB0aGUgYmFja2VuZCByZXR1cm5zIGp1c3QgMjAwIE9LLCB3ZSBtaWdodCBuZWVkIHRvIGNoYWluIGEgZmV0Y2hVc2VyKClcclxuICAgICAgICByZXR1cm4gdGhpcy5odHRwLnBvc3Q8UHJpbXVzVXNlcj4oZW5kcG9pbnQsIGNyZWRlbnRpYWxzLCB7IHdpdGhDcmVkZW50aWFsczogdHJ1ZSB9KS5waXBlKFxyXG4gICAgICAgICAgICB0YXAodXNlciA9PiB7XHJcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgYmFja2VuZCByZXR1cm5zIHRoZSB1c2VyIGRpcmVjdGx5LCBncmVhdC5cclxuICAgICAgICAgICAgICAgIC8vIElmIGl0IHJldHVybnMgYSBnZW5lcmljIHN1Y2Nlc3MsIHdlIG1pZ2h0IGdldCAnbnVsbCcgaGVyZSBpZiB0eXBpbmcgZG9lc24ndCBtYXRjaC5cclxuICAgICAgICAgICAgICAgIC8vIEZvciBzYWZldHksIGlmIHdlIGdldCBhIHN1Y2Nlc3MgcmVzcG9uc2UsIHdlIGNhbiBhbHNvIGZvcmNlLWZldGNoIHRoZSB1c2VyIHRvIGJlIHN1cmUuXHJcbiAgICAgICAgICAgICAgICBpZiAodXNlciAmJiB1c2VyLmVtYWlsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy51cGRhdGVTdGF0ZSh1c2VyKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gRmFsbGJhY2s6IEZldGNoIHVzZXIgaW5mbyBpZiByZXNwb25zZSB3YXMganVzdCB7IHN1Y2Nlc3M6IHRydWUgfVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmV0Y2hVc2VyKCkuc3Vic2NyaWJlKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJlZGlyZWN0cyB0aGUgYnJvd3NlciB0byB0aGUgYmFja2VuZCBsb2dpbiBlbmRwb2ludCBmb3IgdGhlIHByb3ZpZGVyLlxyXG4gICAgICogZS5nLiAvYXBpL2F1dGgvYXp1cmUsIC9hcGkvYXV0aC9hdXRoMFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9naW5XaXRoUHJvdmlkZXIocHJvdmlkZXI6IHN0cmluZywgcmVkaXJlY3RVcmw/OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCByZXR1cm5VcmwgPSByZWRpcmVjdFVybCB8fCB0aGlzLnJvdXRlci51cmw7XHJcbiAgICAgICAgLy8gV2UgY2FuIHBhc3MgcmV0dXJuVXJsIGlmIGJhY2tlbmQgc3VwcG9ydHMgaXQsIHVzdWFsbHkgY29uZmlndXJlZCBnbG9iYWxseVxyXG4gICAgICAgIC8vIG9yIHZpYSBhIHF1ZXJ5IHBhcmFtIGhhbmRsZWQgYnkgdGhlIFJlc29sdXRpb24gbG9naWMuXHJcbiAgICAgICAgLy8gRm9yIG5vdyB3ZSBhc3N1bWUgc3RhbmRhcmQgZmxvdyBvciBiYXNpYyByZWRpcmVjdC5cclxuXHJcbiAgICAgICAgY29uc3QgdGFyZ2V0ID0gYCR7dGhpcy5jb25maWcuYXBpVXJsfS9hcGkvYXV0aC8ke3Byb3ZpZGVyfWA7XHJcbiAgICAgICAgd2luZG93LmxvY2F0aW9uLmhyZWYgPSB0YXJnZXQ7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGxvZ291dCgpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBlbmRwb2ludCA9IGAke3RoaXMuY29uZmlnLmFwaVVybH0vYXBpL2F1dGgvbG9nb3V0YDtcclxuICAgICAgICB0aGlzLmh0dHAucG9zdChlbmRwb2ludCwge30sIHtcclxuICAgICAgICAgICAgd2l0aENyZWRlbnRpYWxzOiB0cnVlXHJcbiAgICAgICAgICAgIC8vIEludGVyY2VwdG9yIHdpbGwgYWRkIENTUkYgaGVhZGVyIGF1dG9tYXRpY2FsbHlcclxuICAgICAgICB9KS5zdWJzY3JpYmUoe1xyXG4gICAgICAgICAgICBuZXh0OiAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVN0YXRlKG51bGwpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgcmVkaXJlY3QgPSB0aGlzLmNvbmZpZy5sb2dvdXRSZWRpcmVjdCB8fCAnL2xvZ2luJztcclxuICAgICAgICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlQnlVcmwocmVkaXJlY3QpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBlcnJvcjogKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgLy8gRm9yY2UgbG9nb3V0IHN0YXRlIGV2ZW4gaWYgQVBJIGZhaWxlZFxyXG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVTdGF0ZShudWxsKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHJlZGlyZWN0ID0gdGhpcy5jb25maWcubG9nb3V0UmVkaXJlY3QgfHwgJy9sb2dpbic7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZUJ5VXJsKHJlZGlyZWN0KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgdXBkYXRlU3RhdGUodXNlcjogUHJpbXVzVXNlciB8IG51bGwpIHtcclxuICAgICAgICB0aGlzLl91c2VyLnNldCh1c2VyKTtcclxuICAgICAgICB0aGlzLnVzZXIkLm5leHQodXNlcik7XHJcblxyXG4gICAgICAgIC8vIEF1dG8tc3luYyBzaWduYWwgdG8gbG9hZGluZyBzdGF0ZVxyXG4gICAgICAgIGlmICh1c2VyKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2lzTG9hZGluZy5zZXQoZmFsc2UpO1xyXG4gICAgICAgICAgICB0aGlzLnN0YXJ0SGVhcnRiZWF0KCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy5zdG9wSGVhcnRiZWF0KCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIENhbGxlZCBieSBJbnRlcmNlcHRvciBvbiA0MDFcclxuICAgIHB1YmxpYyBoYW5kbGVVbmF1dGhvcml6ZWQoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy51cGRhdGVTdGF0ZShudWxsKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHN0YXJ0SGVhcnRiZWF0KCk6IHZvaWQge1xyXG4gICAgICAgIGlmICghaXNQbGF0Zm9ybUJyb3dzZXIodGhpcy5wbGF0Zm9ybUlkKSkgcmV0dXJuO1xyXG4gICAgICAgIGlmICh0aGlzLmhlYXJ0YmVhdFN1YikgcmV0dXJuOyAvLyBBbHJlYWR5IHJ1bm5pbmdcclxuXHJcbiAgICAgICAgdGhpcy5oZWFydGJlYXRTdWIgPSBpbnRlcnZhbCh0aGlzLkhFQVJUQkVBVF9JTlRFUlZBTCkuc3Vic2NyaWJlKCgpID0+IHtcclxuICAgICAgICAgICAgLy8gUXVpZXRseSBjaGVjayBzZXNzaW9uXHJcbiAgICAgICAgICAgIHRoaXMuZmV0Y2hVc2VyKCkuc3Vic2NyaWJlKCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdG9wSGVhcnRiZWF0KCk6IHZvaWQge1xyXG4gICAgICAgIGlmICh0aGlzLmhlYXJ0YmVhdFN1Yikge1xyXG4gICAgICAgICAgICB0aGlzLmhlYXJ0YmVhdFN1Yi51bnN1YnNjcmliZSgpO1xyXG4gICAgICAgICAgICB0aGlzLmhlYXJ0YmVhdFN1YiA9IG51bGw7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcbiJdfQ==
@@ -0,0 +1,3 @@
1
+ import { InjectionToken } from '@angular/core';
2
+ export const PRIMUS_AUTH_CONFIG = new InjectionToken('PRIMUS_AUTH_CONFIG');
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpbXVzLWF1dGgudG9rZW5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vYW5ndWxhci9wcmltdXMtYXV0aC9zcmMvbGliL3ByaW11cy1hdXRoLnRva2Vucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRy9DLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLElBQUksY0FBYyxDQUFtQixvQkFBb0IsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0aW9uVG9rZW4gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgUHJpbXVzQXV0aENvbmZpZyB9IGZyb20gJy4vcHJpbXVzLWF1dGgudHlwZXMnO1xyXG5cclxuZXhwb3J0IGNvbnN0IFBSSU1VU19BVVRIX0NPTkZJRyA9IG5ldyBJbmplY3Rpb25Ub2tlbjxQcmltdXNBdXRoQ29uZmlnPignUFJJTVVTX0FVVEhfQ09ORklHJyk7XHJcbiJdfQ==
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpbXVzLWF1dGgudHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9hbmd1bGFyL3ByaW11cy1hdXRoL3NyYy9saWIvcHJpbXVzLWF1dGgudHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBpbnRlcmZhY2UgUHJpbXVzQXV0aENvbmZpZyB7XHJcbiAgICBhcGlVcmw6IHN0cmluZztcclxuICAgIGxvZ2luUGF0aD86IHN0cmluZzsgLy8gRGVmYXVsdDogL2xvZ2luXHJcbiAgICBsb2dvdXRSZWRpcmVjdD86IHN0cmluZzsgLy8gRGVmYXVsdDogL2xvZ2luXHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgUHJpbXVzVXNlciB7XHJcbiAgICBpZDogc3RyaW5nO1xyXG4gICAgZW1haWw6IHN0cmluZztcclxuICAgIG5hbWU/OiBzdHJpbmc7XHJcbiAgICByb2xlPzogc3RyaW5nO1xyXG4gICAgcHJvdmlkZXI/OiBzdHJpbmc7XHJcbiAgICBwaWN0dXJlPzogc3RyaW5nO1xyXG4gICAgW2tleTogc3RyaW5nXTogYW55O1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIEF1dGhTdGF0ZSB7XHJcbiAgICBpc0F1dGhlbnRpY2F0ZWQ6IGJvb2xlYW47XHJcbiAgICB1c2VyOiBQcmltdXNVc2VyIHwgbnVsbDtcclxuICAgIGlzTG9hZGluZzogYm9vbGVhbjtcclxufVxyXG4iXX0=
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ export * from './public-api';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpbXVzLWFuZ3VsYXItYXV0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2FuZ3VsYXIvcHJpbXVzLWF1dGgvc3JjL3ByaW11cy1hbmd1bGFyLWF1dGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9wdWJsaWMtYXBpJztcbiJdfQ==
@@ -0,0 +1,9 @@
1
+ /*
2
+ * Public API Surface of primus-angular-auth
3
+ */
4
+ export * from './lib/primus-auth.service';
5
+ export * from './lib/primus-auth.interceptor';
6
+ export * from './lib/primus-auth.guard';
7
+ export * from './lib/primus-auth.provider';
8
+ export * from './lib/primus-auth.types';
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2FuZ3VsYXIvcHJpbXVzLWF1dGgvc3JjL3B1YmxpYy1hcGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLDJCQUEyQixDQUFDO0FBQzFDLGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLDRCQUE0QixDQUFDO0FBQzNDLGNBQWMseUJBQXlCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxyXG4gKiBQdWJsaWMgQVBJIFN1cmZhY2Ugb2YgcHJpbXVzLWFuZ3VsYXItYXV0aFxyXG4gKi9cclxuXHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL3ByaW11cy1hdXRoLnNlcnZpY2UnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9wcmltdXMtYXV0aC5pbnRlcmNlcHRvcic7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL3ByaW11cy1hdXRoLmd1YXJkJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvcHJpbXVzLWF1dGgucHJvdmlkZXInO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9wcmltdXMtYXV0aC50eXBlcyc7XHJcbiJdfQ==
@@ -0,0 +1,259 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, signal, computed, PLATFORM_ID, Inject, Injectable, inject, makeEnvironmentProviders, APP_INITIALIZER } from '@angular/core';
3
+ import * as i3 from '@angular/common';
4
+ import { isPlatformBrowser } from '@angular/common';
5
+ import { map, tap, catchError, filter, take, switchMap } from 'rxjs/operators';
6
+ import { BehaviorSubject, of, interval, catchError as catchError$1, throwError } from 'rxjs';
7
+ import * as i1 from '@angular/common/http';
8
+ import { provideHttpClient, withInterceptors } from '@angular/common/http';
9
+ import * as i2 from '@angular/router';
10
+ import { Router } from '@angular/router';
11
+
12
+ const PRIMUS_AUTH_CONFIG = new InjectionToken('PRIMUS_AUTH_CONFIG');
13
+
14
+ class PrimusAuthService {
15
+ http;
16
+ router;
17
+ location;
18
+ config;
19
+ platformId;
20
+ // Reactive State (Signals)
21
+ _user = signal(null);
22
+ _isLoading = signal(true);
23
+ user = this._user.asReadonly();
24
+ isLoading = this._isLoading.asReadonly();
25
+ isAuthenticated = computed(() => !!this._user());
26
+ // Legacy Observable support
27
+ user$ = new BehaviorSubject(null);
28
+ isAuthenticated$ = this.user$.pipe(map(u => !!u));
29
+ initialized$ = new BehaviorSubject(false);
30
+ heartbeatSub = null;
31
+ HEARTBEAT_INTERVAL = 5 * 60 * 1000; // 5 minutes
32
+ constructor(http, router, location, config, platformId) {
33
+ this.http = http;
34
+ this.router = router;
35
+ this.location = location;
36
+ this.config = config;
37
+ this.platformId = platformId;
38
+ this.checkSession();
39
+ }
40
+ ngOnDestroy() {
41
+ this.stopHeartbeat();
42
+ }
43
+ /**
44
+ * Checks /api/auth/me to see if user is logged in.
45
+ * Should be called on app startup.
46
+ */
47
+ checkSession() {
48
+ if (!isPlatformBrowser(this.platformId)) {
49
+ this._isLoading.set(false);
50
+ this.initialized$.next(true);
51
+ return;
52
+ }
53
+ this._isLoading.set(true);
54
+ this.fetchUser().subscribe(() => {
55
+ this._isLoading.set(false);
56
+ this.initialized$.next(true);
57
+ });
58
+ }
59
+ fetchUser() {
60
+ const endpoint = `${this.config.apiUrl}/api/auth/me`;
61
+ return this.http.get(endpoint, { withCredentials: true }).pipe(tap(user => this.updateState(user)), catchError(() => {
62
+ this.updateState(null);
63
+ return of(null);
64
+ }));
65
+ }
66
+ /**
67
+ * Performs a local login (username/password) via the Backend Broker.
68
+ * The backend must accept a POST to /api/auth/login and set a cookie.
69
+ */
70
+ login(credentials) {
71
+ const endpoint = `${this.config.apiUrl}/api/auth/login`;
72
+ // We expect the backend to return the User object on success (or we fetch it)
73
+ // If the backend returns just 200 OK, we might need to chain a fetchUser()
74
+ return this.http.post(endpoint, credentials, { withCredentials: true }).pipe(tap(user => {
75
+ // If the backend returns the user directly, great.
76
+ // If it returns a generic success, we might get 'null' here if typing doesn't match.
77
+ // For safety, if we get a success response, we can also force-fetch the user to be sure.
78
+ if (user && user.email) {
79
+ this.updateState(user);
80
+ }
81
+ else {
82
+ // Fallback: Fetch user info if response was just { success: true }
83
+ this.fetchUser().subscribe();
84
+ }
85
+ }));
86
+ }
87
+ /**
88
+ * Redirects the browser to the backend login endpoint for the provider.
89
+ * e.g. /api/auth/azure, /api/auth/auth0
90
+ */
91
+ loginWithProvider(provider, redirectUrl) {
92
+ const returnUrl = redirectUrl || this.router.url;
93
+ // We can pass returnUrl if backend supports it, usually configured globally
94
+ // or via a query param handled by the Resolution logic.
95
+ // For now we assume standard flow or basic redirect.
96
+ const target = `${this.config.apiUrl}/api/auth/${provider}`;
97
+ window.location.href = target;
98
+ }
99
+ logout() {
100
+ const endpoint = `${this.config.apiUrl}/api/auth/logout`;
101
+ this.http.post(endpoint, {}, {
102
+ withCredentials: true
103
+ // Interceptor will add CSRF header automatically
104
+ }).subscribe({
105
+ next: () => {
106
+ this.updateState(null);
107
+ const redirect = this.config.logoutRedirect || '/login';
108
+ this.router.navigateByUrl(redirect);
109
+ },
110
+ error: () => {
111
+ // Force logout state even if API failed
112
+ this.updateState(null);
113
+ const redirect = this.config.logoutRedirect || '/login';
114
+ this.router.navigateByUrl(redirect);
115
+ }
116
+ });
117
+ }
118
+ updateState(user) {
119
+ this._user.set(user);
120
+ this.user$.next(user);
121
+ // Auto-sync signal to loading state
122
+ if (user) {
123
+ this._isLoading.set(false);
124
+ this.startHeartbeat();
125
+ }
126
+ else {
127
+ this.stopHeartbeat();
128
+ }
129
+ }
130
+ // Called by Interceptor on 401
131
+ handleUnauthorized() {
132
+ this.updateState(null);
133
+ }
134
+ startHeartbeat() {
135
+ if (!isPlatformBrowser(this.platformId))
136
+ return;
137
+ if (this.heartbeatSub)
138
+ return; // Already running
139
+ this.heartbeatSub = interval(this.HEARTBEAT_INTERVAL).subscribe(() => {
140
+ // Quietly check session
141
+ this.fetchUser().subscribe();
142
+ });
143
+ }
144
+ stopHeartbeat() {
145
+ if (this.heartbeatSub) {
146
+ this.heartbeatSub.unsubscribe();
147
+ this.heartbeatSub = null;
148
+ }
149
+ }
150
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PrimusAuthService, deps: [{ token: i1.HttpClient }, { token: i2.Router }, { token: i3.Location }, { token: PRIMUS_AUTH_CONFIG }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable });
151
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PrimusAuthService, providedIn: 'root' });
152
+ }
153
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PrimusAuthService, decorators: [{
154
+ type: Injectable,
155
+ args: [{
156
+ providedIn: 'root'
157
+ }]
158
+ }], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.Router }, { type: i3.Location }, { type: undefined, decorators: [{
159
+ type: Inject,
160
+ args: [PRIMUS_AUTH_CONFIG]
161
+ }] }, { type: Object, decorators: [{
162
+ type: Inject,
163
+ args: [PLATFORM_ID]
164
+ }] }] });
165
+
166
+ const primusAuthInterceptor = (req, next) => {
167
+ const authService = inject(PrimusAuthService);
168
+ // 1. Add CSRF Header to non-GET requests
169
+ // Double-Submit Cookie Pattern: Read XSRF-TOKEN cookie and mirror in header.
170
+ let request = req;
171
+ if (req.method !== 'GET' && req.method !== 'HEAD' && req.method !== 'OPTIONS') {
172
+ const token = getCookie('XSRF-TOKEN') || '';
173
+ request = req.clone({
174
+ setHeaders: {
175
+ 'X-Primus-CSRF': token
176
+ },
177
+ withCredentials: true // Ensure cookies are sent
178
+ });
179
+ }
180
+ else {
181
+ // Determine if we need credentials for GETs?
182
+ // Usually yes for API calls to our backend.
183
+ // We assume calls to same origin or API URL need creds.
184
+ request = req.clone({
185
+ withCredentials: true
186
+ });
187
+ }
188
+ return next(request).pipe(catchError$1((error) => {
189
+ // 2. Handle 401 Unauthorized
190
+ if (error.status === 401) {
191
+ authService.handleUnauthorized();
192
+ }
193
+ return throwError(() => error);
194
+ }));
195
+ };
196
+ function getCookie(name) {
197
+ try {
198
+ if (typeof document === 'undefined')
199
+ return null;
200
+ const matches = document.cookie.match(new RegExp('(?:^|; )' + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + '=([^;]*)'));
201
+ return matches ? decodeURIComponent(matches[1]) : null;
202
+ }
203
+ catch {
204
+ return null;
205
+ }
206
+ }
207
+
208
+ const primusAuthGuard = (route, state) => {
209
+ const auth = inject(PrimusAuthService);
210
+ const router = inject(Router);
211
+ const config = inject(PRIMUS_AUTH_CONFIG);
212
+ // Wait for initialization to complete, then check authentication status
213
+ return auth.initialized$.pipe(filter((isInit) => isInit), // Wait until true
214
+ take(1), switchMap(() => auth.isAuthenticated$), take(1), map((isAuthenticated) => {
215
+ if (isAuthenticated) {
216
+ return true;
217
+ }
218
+ // Redirect to login
219
+ const loginPath = config.loginPath || '/login';
220
+ return router.createUrlTree([loginPath], {
221
+ queryParams: { returnUrl: state.url }
222
+ });
223
+ }));
224
+ };
225
+
226
+ function providePrimusAuth(config) {
227
+ return makeEnvironmentProviders([
228
+ {
229
+ provide: PRIMUS_AUTH_CONFIG,
230
+ useValue: config
231
+ },
232
+ PrimusAuthService,
233
+ provideHttpClient(withInterceptors([primusAuthInterceptor])),
234
+ {
235
+ provide: APP_INITIALIZER,
236
+ useFactory: (auth, platform) => () => {
237
+ // We trigger checkSession in constructor, but we can also do it here if we want to await it.
238
+ // However, awaiting APP_INITIALIZER blocks the whole app render.
239
+ // Better to let it run in background and use the Guard to block specific routes.
240
+ // So we just ensure service is instantiated.
241
+ // Actually, checkSession is already called in constructor.
242
+ // This APP_INITIALIZER forces the service to be created immediately on app start.
243
+ },
244
+ deps: [PrimusAuthService, PLATFORM_ID],
245
+ multi: true
246
+ }
247
+ ]);
248
+ }
249
+
250
+ /*
251
+ * Public API Surface of primus-angular-auth
252
+ */
253
+
254
+ /**
255
+ * Generated bundle index. Do not edit.
256
+ */
257
+
258
+ export { PrimusAuthService, primusAuthGuard, primusAuthInterceptor, providePrimusAuth };
259
+ //# sourceMappingURL=primus-angular-auth.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primus-angular-auth.mjs","sources":["../../../angular/primus-auth/src/lib/primus-auth.tokens.ts","../../../angular/primus-auth/src/lib/primus-auth.service.ts","../../../angular/primus-auth/src/lib/primus-auth.interceptor.ts","../../../angular/primus-auth/src/lib/primus-auth.guard.ts","../../../angular/primus-auth/src/lib/primus-auth.provider.ts","../../../angular/primus-auth/src/public-api.ts","../../../angular/primus-auth/src/primus-angular-auth.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\r\nimport { PrimusAuthConfig } from './primus-auth.types';\r\n\r\nexport const PRIMUS_AUTH_CONFIG = new InjectionToken<PrimusAuthConfig>('PRIMUS_AUTH_CONFIG');\r\n","import { Injectable, Inject, signal, computed, PLATFORM_ID, OnDestroy } from '@angular/core';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { Router } from '@angular/router';\r\nimport { isPlatformBrowser, Location } from '@angular/common';\r\nimport { catchError, map, tap } from 'rxjs/operators';\r\nimport { Observable, of, BehaviorSubject, Subscription, interval } from 'rxjs';\r\nimport { PrimusAuthConfig, PrimusUser } from './primus-auth.types';\r\nimport { PRIMUS_AUTH_CONFIG } from './primus-auth.tokens';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class PrimusAuthService implements OnDestroy {\r\n // Reactive State (Signals)\r\n private _user = signal<PrimusUser | null>(null);\r\n private _isLoading = signal<boolean>(true);\r\n\r\n public readonly user = this._user.asReadonly();\r\n public readonly isLoading = this._isLoading.asReadonly();\r\n public readonly isAuthenticated = computed(() => !!this._user());\r\n\r\n // Legacy Observable support\r\n public readonly user$ = new BehaviorSubject<PrimusUser | null>(null);\r\n public readonly isAuthenticated$ = this.user$.pipe(map(u => !!u));\r\n public readonly initialized$ = new BehaviorSubject<boolean>(false);\r\n\r\n private heartbeatSub: Subscription | null = null;\r\n private readonly HEARTBEAT_INTERVAL = 5 * 60 * 1000; // 5 minutes\r\n\r\n constructor(\r\n private http: HttpClient,\r\n private router: Router,\r\n private location: Location,\r\n @Inject(PRIMUS_AUTH_CONFIG) private config: PrimusAuthConfig,\r\n @Inject(PLATFORM_ID) private platformId: Object\r\n ) {\r\n this.checkSession();\r\n }\r\n\r\n public ngOnDestroy(): void {\r\n this.stopHeartbeat();\r\n }\r\n\r\n /**\r\n * Checks /api/auth/me to see if user is logged in.\r\n * Should be called on app startup.\r\n */\r\n public checkSession(): void {\r\n if (!isPlatformBrowser(this.platformId)) {\r\n this._isLoading.set(false);\r\n this.initialized$.next(true);\r\n return;\r\n }\r\n\r\n this._isLoading.set(true);\r\n this.fetchUser().subscribe(() => {\r\n this._isLoading.set(false);\r\n this.initialized$.next(true);\r\n });\r\n }\r\n\r\n private fetchUser(): Observable<PrimusUser | null> {\r\n const endpoint = `${this.config.apiUrl}/api/auth/me`;\r\n return this.http.get<PrimusUser>(endpoint, { withCredentials: true }).pipe(\r\n tap(user => this.updateState(user)),\r\n catchError(() => {\r\n this.updateState(null);\r\n return of(null);\r\n })\r\n );\r\n }\r\n\r\n /**\r\n * Performs a local login (username/password) via the Backend Broker.\r\n * The backend must accept a POST to /api/auth/login and set a cookie.\r\n */\r\n public login(credentials: Record<string, any>): Observable<PrimusUser | null> {\r\n const endpoint = `${this.config.apiUrl}/api/auth/login`;\r\n // We expect the backend to return the User object on success (or we fetch it)\r\n // If the backend returns just 200 OK, we might need to chain a fetchUser()\r\n return this.http.post<PrimusUser>(endpoint, credentials, { withCredentials: true }).pipe(\r\n tap(user => {\r\n // If the backend returns the user directly, great.\r\n // If it returns a generic success, we might get 'null' here if typing doesn't match.\r\n // For safety, if we get a success response, we can also force-fetch the user to be sure.\r\n if (user && user.email) {\r\n this.updateState(user);\r\n } else {\r\n // Fallback: Fetch user info if response was just { success: true }\r\n this.fetchUser().subscribe();\r\n }\r\n })\r\n );\r\n }\r\n\r\n /**\r\n * Redirects the browser to the backend login endpoint for the provider.\r\n * e.g. /api/auth/azure, /api/auth/auth0\r\n */\r\n public loginWithProvider(provider: string, redirectUrl?: string): void {\r\n const returnUrl = redirectUrl || this.router.url;\r\n // We can pass returnUrl if backend supports it, usually configured globally\r\n // or via a query param handled by the Resolution logic.\r\n // For now we assume standard flow or basic redirect.\r\n\r\n const target = `${this.config.apiUrl}/api/auth/${provider}`;\r\n window.location.href = target;\r\n }\r\n\r\n public logout(): void {\r\n const endpoint = `${this.config.apiUrl}/api/auth/logout`;\r\n this.http.post(endpoint, {}, {\r\n withCredentials: true\r\n // Interceptor will add CSRF header automatically\r\n }).subscribe({\r\n next: () => {\r\n this.updateState(null);\r\n const redirect = this.config.logoutRedirect || '/login';\r\n this.router.navigateByUrl(redirect);\r\n },\r\n error: () => {\r\n // Force logout state even if API failed\r\n this.updateState(null);\r\n const redirect = this.config.logoutRedirect || '/login';\r\n this.router.navigateByUrl(redirect);\r\n }\r\n });\r\n }\r\n\r\n private updateState(user: PrimusUser | null) {\r\n this._user.set(user);\r\n this.user$.next(user);\r\n\r\n // Auto-sync signal to loading state\r\n if (user) {\r\n this._isLoading.set(false);\r\n this.startHeartbeat();\r\n } else {\r\n this.stopHeartbeat();\r\n }\r\n }\r\n\r\n // Called by Interceptor on 401\r\n public handleUnauthorized(): void {\r\n this.updateState(null);\r\n }\r\n\r\n private startHeartbeat(): void {\r\n if (!isPlatformBrowser(this.platformId)) return;\r\n if (this.heartbeatSub) return; // Already running\r\n\r\n this.heartbeatSub = interval(this.HEARTBEAT_INTERVAL).subscribe(() => {\r\n // Quietly check session\r\n this.fetchUser().subscribe();\r\n });\r\n }\r\n\r\n private stopHeartbeat(): void {\r\n if (this.heartbeatSub) {\r\n this.heartbeatSub.unsubscribe();\r\n this.heartbeatSub = null;\r\n }\r\n }\r\n}\r\n","import { HttpInterceptorFn, HttpErrorResponse } from '@angular/common/http';\r\nimport { inject } from '@angular/core';\r\nimport { catchError, throwError } from 'rxjs';\r\nimport { PrimusAuthService } from './primus-auth.service';\r\n\r\nexport const primusAuthInterceptor: HttpInterceptorFn = (req, next) => {\r\n const authService = inject(PrimusAuthService);\r\n\r\n // 1. Add CSRF Header to non-GET requests\r\n // Double-Submit Cookie Pattern: Read XSRF-TOKEN cookie and mirror in header.\r\n let request = req;\r\n if (req.method !== 'GET' && req.method !== 'HEAD' && req.method !== 'OPTIONS') {\r\n const token = getCookie('XSRF-TOKEN') || '';\r\n request = req.clone({\r\n setHeaders: {\r\n 'X-Primus-CSRF': token\r\n },\r\n withCredentials: true // Ensure cookies are sent\r\n });\r\n } else {\r\n // Determine if we need credentials for GETs?\r\n // Usually yes for API calls to our backend.\r\n // We assume calls to same origin or API URL need creds.\r\n request = req.clone({\r\n withCredentials: true\r\n });\r\n }\r\n \r\n return next(request).pipe(\r\n catchError((error: HttpErrorResponse) => {\r\n // 2. Handle 401 Unauthorized\r\n if (error.status === 401) {\r\n authService.handleUnauthorized();\r\n }\r\n return throwError(() => error);\r\n })\r\n );\r\n };\r\n \r\n function getCookie(name: string): string | null {\r\n try {\r\n if (typeof document === 'undefined') return null;\r\n const matches = document.cookie.match(new RegExp('(?:^|; )' + name.replace(/([\\.$?*|{}\\(\\)\\[\\]\\\\\\/\\+^])/g, '\\\\$1') + '=([^;]*)'));\r\n return matches ? decodeURIComponent(matches[1]) : null;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n","import { CanActivateFn, Router, UrlTree, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';\r\nimport { inject } from '@angular/core';\r\nimport { PrimusAuthService } from './primus-auth.service';\r\nimport { map, filter, switchMap, take } from 'rxjs/operators';\r\nimport { PRIMUS_AUTH_CONFIG } from './primus-auth.tokens';\r\n\r\nexport const primusAuthGuard: CanActivateFn = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {\r\n const auth = inject(PrimusAuthService);\r\n const router = inject(Router);\r\n const config = inject(PRIMUS_AUTH_CONFIG);\r\n\r\n // Wait for initialization to complete, then check authentication status\r\n return auth.initialized$.pipe(\r\n filter((isInit: boolean) => isInit), // Wait until true\r\n take(1),\r\n switchMap(() => auth.isAuthenticated$),\r\n take(1),\r\n map((isAuthenticated: boolean) => {\r\n if (isAuthenticated) {\r\n return true;\r\n }\r\n\r\n // Redirect to login\r\n const loginPath = config.loginPath || '/login';\r\n return router.createUrlTree([loginPath], {\r\n queryParams: { returnUrl: state.url }\r\n });\r\n })\r\n );\r\n};\r\n","import { EnvironmentProviders, makeEnvironmentProviders, Provider, APP_INITIALIZER, PLATFORM_ID, inject } from '@angular/core';\r\nimport { provideHttpClient, withInterceptors } from '@angular/common/http';\r\nimport { PrimusAuthConfig } from './primus-auth.types';\r\nimport { PRIMUS_AUTH_CONFIG } from './primus-auth.tokens';\r\nimport { PrimusAuthService } from './primus-auth.service';\r\nimport { primusAuthInterceptor } from './primus-auth.interceptor';\r\nimport { isPlatformBrowser } from '@angular/common';\r\n\r\nexport function providePrimusAuth(config: PrimusAuthConfig): EnvironmentProviders {\r\n return makeEnvironmentProviders([\r\n {\r\n provide: PRIMUS_AUTH_CONFIG,\r\n useValue: config\r\n },\r\n PrimusAuthService,\r\n provideHttpClient(\r\n withInterceptors([primusAuthInterceptor])\r\n ),\r\n {\r\n provide: APP_INITIALIZER,\r\n useFactory: (auth: PrimusAuthService, platform: Object) => () => {\r\n // We trigger checkSession in constructor, but we can also do it here if we want to await it.\r\n // However, awaiting APP_INITIALIZER blocks the whole app render.\r\n // Better to let it run in background and use the Guard to block specific routes.\r\n // So we just ensure service is instantiated.\r\n\r\n // Actually, checkSession is already called in constructor.\r\n // This APP_INITIALIZER forces the service to be created immediately on app start.\r\n },\r\n deps: [PrimusAuthService, PLATFORM_ID],\r\n multi: true\r\n }\r\n ]);\r\n}\r\n","/*\r\n * Public API Surface of primus-angular-auth\r\n */\r\n\r\nexport * from './lib/primus-auth.service';\r\nexport * from './lib/primus-auth.interceptor';\r\nexport * from './lib/primus-auth.guard';\r\nexport * from './lib/primus-auth.provider';\r\nexport * from './lib/primus-auth.types';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["catchError"],"mappings":";;;;;;;;;;;AAGO,MAAM,kBAAkB,GAAG,IAAI,cAAc,CAAmB,oBAAoB,CAAC;;MCS/E,iBAAiB,CAAA;AAkBd,IAAA,IAAA;AACA,IAAA,MAAA;AACA,IAAA,QAAA;AAC4B,IAAA,MAAA;AACP,IAAA,UAAA;;AApBzB,IAAA,KAAK,GAAG,MAAM,CAAoB,IAAI,CAAC;AACvC,IAAA,UAAU,GAAG,MAAM,CAAU,IAAI,CAAC;AAE1B,IAAA,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;AAC9B,IAAA,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE;AACxC,IAAA,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;;AAGhD,IAAA,KAAK,GAAG,IAAI,eAAe,CAAoB,IAAI,CAAC;AACpD,IAAA,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,IAAA,YAAY,GAAG,IAAI,eAAe,CAAU,KAAK,CAAC;IAE1D,YAAY,GAAwB,IAAI;IAC/B,kBAAkB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IAEpD,WAAA,CACY,IAAgB,EAChB,MAAc,EACd,QAAkB,EACU,MAAwB,EAC/B,UAAkB,EAAA;QAJvC,IAAA,CAAA,IAAI,GAAJ,IAAI;QACJ,IAAA,CAAA,MAAM,GAAN,MAAM;QACN,IAAA,CAAA,QAAQ,GAAR,QAAQ;QACoB,IAAA,CAAA,MAAM,GAAN,MAAM;QACb,IAAA,CAAA,UAAU,GAAV,UAAU;QAEvC,IAAI,CAAC,YAAY,EAAE;IACvB;IAEO,WAAW,GAAA;QACd,IAAI,CAAC,aAAa,EAAE;IACxB;AAEA;;;AAGG;IACI,YAAY,GAAA;AACf,QAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;AACrC,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;AAC1B,YAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YAC5B;AACH,QAAA;AAED,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;AACzB,QAAA,IAAI,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC,MAAK;AAC5B,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;AAC1B,YAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;AAChC,QAAA,CAAC,CAAC;IACN;IAEQ,SAAS,GAAA;QACb,MAAM,QAAQ,GAAG,CAAA,EAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAA,YAAA,CAAc;AACpD,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAa,QAAQ,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CACtE,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EACnC,UAAU,CAAC,MAAK;AACZ,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;AACtB,YAAA,OAAO,EAAE,CAAC,IAAI,CAAC;QACnB,CAAC,CAAC,CACL;IACL;AAEA;;;AAGG;AACI,IAAA,KAAK,CAAC,WAAgC,EAAA;QACzC,MAAM,QAAQ,GAAG,CAAA,EAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAA,eAAA,CAAiB;;;QAGvD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAa,QAAQ,EAAE,WAAW,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CACpF,GAAG,CAAC,IAAI,IAAG;;;;AAIP,YAAA,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE;AACpB,gBAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;AACzB,YAAA;AAAM,iBAAA;;AAEH,gBAAA,IAAI,CAAC,SAAS,EAAE,CAAC,SAAS,EAAE;AAC/B,YAAA;QACL,CAAC,CAAC,CACL;IACL;AAEA;;;AAGG;IACI,iBAAiB,CAAC,QAAgB,EAAE,WAAoB,EAAA;QAC3D,MAAM,SAAS,GAAG,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG;;;;QAKhD,MAAM,MAAM,GAAG,CAAA,EAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAA,UAAA,EAAa,QAAQ,CAAA,CAAE;AAC3D,QAAA,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,MAAM;IACjC;IAEO,MAAM,GAAA;QACT,MAAM,QAAQ,GAAG,CAAA,EAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAA,gBAAA,CAAkB;QACxD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE;AACzB,YAAA,eAAe,EAAE;;SAEpB,CAAC,CAAC,SAAS,CAAC;YACT,IAAI,EAAE,MAAK;AACP,gBAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;gBACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,QAAQ;AACvD,gBAAA,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC;YACvC,CAAC;YACD,KAAK,EAAE,MAAK;;AAER,gBAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;gBACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,QAAQ;AACvD,gBAAA,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC;YACvC;AACH,SAAA,CAAC;IACN;AAEQ,IAAA,WAAW,CAAC,IAAuB,EAAA;AACvC,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;AACpB,QAAA,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;;AAGrB,QAAA,IAAI,IAAI,EAAE;AACN,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;YAC1B,IAAI,CAAC,cAAc,EAAE;AACxB,QAAA;AAAM,aAAA;YACH,IAAI,CAAC,aAAa,EAAE;AACvB,QAAA;IACL;;IAGO,kBAAkB,GAAA;AACrB,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IAC1B;IAEQ,cAAc,GAAA;AAClB,QAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC;YAAE;QACzC,IAAI,IAAI,CAAC,YAAY;AAAE,YAAA,OAAO;AAE9B,QAAA,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,SAAS,CAAC,MAAK;;AAEjE,YAAA,IAAI,CAAC,SAAS,EAAE,CAAC,SAAS,EAAE;AAChC,QAAA,CAAC,CAAC;IACN;IAEQ,aAAa,GAAA;QACjB,IAAI,IAAI,CAAC,YAAY,EAAE;AACnB,YAAA,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE;AAC/B,YAAA,IAAI,CAAC,YAAY,GAAG,IAAI;AAC3B,QAAA;IACL;wGAtJS,iBAAiB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,UAAA,EAAA,EAAA,EAAA,KAAA,EAAA,EAAA,CAAA,MAAA,EAAA,EAAA,EAAA,KAAA,EAAA,EAAA,CAAA,QAAA,EAAA,EAAA,EAAA,KAAA,EAqBd,kBAAkB,EAAA,EAAA,EAAA,KAAA,EAClB,WAAW,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAtBd,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,iBAAiB,cAFd,MAAM,EAAA,CAAA;;4FAET,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAH7B,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACR,oBAAA,UAAU,EAAE;AACf,iBAAA;;0BAsBQ,MAAM;2BAAC,kBAAkB;;0BACzB,MAAM;2BAAC,WAAW;;;MC7Bd,qBAAqB,GAAsB,CAAC,GAAG,EAAE,IAAI,KAAI;AAClE,IAAA,MAAM,WAAW,GAAG,MAAM,CAAC,iBAAiB,CAAC;;;IAIzC,IAAI,OAAO,GAAG,GAAG;AACjB,IAAA,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE;QAC3E,MAAM,KAAK,GAAG,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE;AAC3C,QAAA,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC;AAChB,YAAA,UAAU,EAAE;AACR,gBAAA,eAAe,EAAE;AACpB,aAAA;YACD,eAAe,EAAE,IAAI;AACxB,SAAA,CAAC;AACL,IAAA;AAAM,SAAA;;;;AAIH,QAAA,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC;AAChB,YAAA,eAAe,EAAE;AACpB,SAAA,CAAC;AACL,IAAA;AAED,IAAA,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CACrBA,YAAU,CAAC,CAAC,KAAwB,KAAI;;AAEpC,QAAA,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE;YACtB,WAAW,CAAC,kBAAkB,EAAE;AACnC,QAAA;AACD,QAAA,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC;IAClC,CAAC,CAAC,CACL;AACL;AAEA,SAAS,SAAS,CAAC,IAAY,EAAA;IAC3B,IAAI;QACA,IAAI,OAAO,QAAQ,KAAK,WAAW;AAAE,YAAA,OAAO,IAAI;QAChD,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,8BAA8B,EAAE,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC;AACjI,QAAA,OAAO,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;AACzD,IAAA;IAAC,MAAM;AACJ,QAAA,OAAO,IAAI;AACd,IAAA;AACL;;MCzCS,eAAe,GAAkB,CAAC,KAA6B,EAAE,KAA0B,KAAI;AACxG,IAAA,MAAM,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;AACtC,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AAC7B,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,kBAAkB,CAAC;;AAGzC,IAAA,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CACzB,MAAM,CAAC,CAAC,MAAe,KAAK,MAAM,CAAC;IACnC,IAAI,CAAC,CAAC,CAAC,EACP,SAAS,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,EACtC,IAAI,CAAC,CAAC,CAAC,EACP,GAAG,CAAC,CAAC,eAAwB,KAAI;AAC7B,QAAA,IAAI,eAAe,EAAE;AACjB,YAAA,OAAO,IAAI;AACd,QAAA;;AAGD,QAAA,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,QAAQ;AAC9C,QAAA,OAAO,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,EAAE;AACrC,YAAA,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,GAAG;AACtC,SAAA,CAAC;IACN,CAAC,CAAC,CACL;AACL;;ACrBM,SAAU,iBAAiB,CAAC,MAAwB,EAAA;AACtD,IAAA,OAAO,wBAAwB,CAAC;AAC5B,QAAA;AACI,YAAA,OAAO,EAAE,kBAAkB;AAC3B,YAAA,QAAQ,EAAE;AACb,SAAA;QACD,iBAAiB;AACjB,QAAA,iBAAiB,CACb,gBAAgB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAC5C;AACD,QAAA;AACI,YAAA,OAAO,EAAE,eAAe;YACxB,UAAU,EAAE,CAAC,IAAuB,EAAE,QAAgB,KAAK,MAAK;;;;;;;YAQhE,CAAC;AACD,YAAA,IAAI,EAAE,CAAC,iBAAiB,EAAE,WAAW,CAAC;AACtC,YAAA,KAAK,EAAE;AACV;AACJ,KAAA,CAAC;AACN;;ACjCA;;AAEG;;ACFH;;AAEG;;;;"}
package/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ /// <amd-module name="primus-angular-auth" />
5
+ export * from './public-api';
@@ -0,0 +1,2 @@
1
+ import { CanActivateFn } from '@angular/router';
2
+ export declare const primusAuthGuard: CanActivateFn;
@@ -0,0 +1,2 @@
1
+ import { HttpInterceptorFn } from '@angular/common/http';
2
+ export declare const primusAuthInterceptor: HttpInterceptorFn;
@@ -0,0 +1,3 @@
1
+ import { EnvironmentProviders } from '@angular/core';
2
+ import { PrimusAuthConfig } from './primus-auth.types';
3
+ export declare function providePrimusAuth(config: PrimusAuthConfig): EnvironmentProviders;
@@ -0,0 +1,49 @@
1
+ import { OnDestroy } from '@angular/core';
2
+ import { HttpClient } from '@angular/common/http';
3
+ import { Router } from '@angular/router';
4
+ import { Location } from '@angular/common';
5
+ import { Observable, BehaviorSubject } from 'rxjs';
6
+ import { PrimusAuthConfig, PrimusUser } from './primus-auth.types';
7
+ import * as i0 from "@angular/core";
8
+ export declare class PrimusAuthService implements OnDestroy {
9
+ private http;
10
+ private router;
11
+ private location;
12
+ private config;
13
+ private platformId;
14
+ private _user;
15
+ private _isLoading;
16
+ readonly user: import("@angular/core").Signal<PrimusUser>;
17
+ readonly isLoading: import("@angular/core").Signal<boolean>;
18
+ readonly isAuthenticated: import("@angular/core").Signal<boolean>;
19
+ readonly user$: BehaviorSubject<PrimusUser>;
20
+ readonly isAuthenticated$: Observable<boolean>;
21
+ readonly initialized$: BehaviorSubject<boolean>;
22
+ private heartbeatSub;
23
+ private readonly HEARTBEAT_INTERVAL;
24
+ constructor(http: HttpClient, router: Router, location: Location, config: PrimusAuthConfig, platformId: Object);
25
+ ngOnDestroy(): void;
26
+ /**
27
+ * Checks /api/auth/me to see if user is logged in.
28
+ * Should be called on app startup.
29
+ */
30
+ checkSession(): void;
31
+ private fetchUser;
32
+ /**
33
+ * Performs a local login (username/password) via the Backend Broker.
34
+ * The backend must accept a POST to /api/auth/login and set a cookie.
35
+ */
36
+ login(credentials: Record<string, any>): Observable<PrimusUser | null>;
37
+ /**
38
+ * Redirects the browser to the backend login endpoint for the provider.
39
+ * e.g. /api/auth/azure, /api/auth/auth0
40
+ */
41
+ loginWithProvider(provider: string, redirectUrl?: string): void;
42
+ logout(): void;
43
+ private updateState;
44
+ handleUnauthorized(): void;
45
+ private startHeartbeat;
46
+ private stopHeartbeat;
47
+ static ɵfac: i0.ɵɵFactoryDeclaration<PrimusAuthService, never>;
48
+ static ɵprov: i0.ɵɵInjectableDeclaration<PrimusAuthService>;
49
+ }
@@ -0,0 +1,3 @@
1
+ import { InjectionToken } from '@angular/core';
2
+ import { PrimusAuthConfig } from './primus-auth.types';
3
+ export declare const PRIMUS_AUTH_CONFIG: InjectionToken<PrimusAuthConfig>;
@@ -0,0 +1,19 @@
1
+ export interface PrimusAuthConfig {
2
+ apiUrl: string;
3
+ loginPath?: string;
4
+ logoutRedirect?: string;
5
+ }
6
+ export interface PrimusUser {
7
+ id: string;
8
+ email: string;
9
+ name?: string;
10
+ role?: string;
11
+ provider?: string;
12
+ picture?: string;
13
+ [key: string]: any;
14
+ }
15
+ export interface AuthState {
16
+ isAuthenticated: boolean;
17
+ user: PrimusUser | null;
18
+ isLoading: boolean;
19
+ }
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "primus-angular-auth",
3
+ "version": "1.0.0",
4
+ "description": "Enterprise-grade BFF authentication client for Primus SaaS Framework in Angular.",
5
+ "license": "MIT",
6
+ "peerDependencies": {
7
+ "@angular/common": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
8
+ "@angular/core": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
9
+ "@angular/router": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
10
+ "rxjs": "^7.8.0"
11
+ },
12
+ "dependencies": {
13
+ "tslib": "^2.3.0"
14
+ },
15
+ "sideEffects": false,
16
+ "module": "fesm2022/primus-angular-auth.mjs",
17
+ "typings": "index.d.ts",
18
+ "exports": {
19
+ "./package.json": {
20
+ "default": "./package.json"
21
+ },
22
+ ".": {
23
+ "types": "./index.d.ts",
24
+ "esm2022": "./esm2022/primus-angular-auth.mjs",
25
+ "esm": "./esm2022/primus-angular-auth.mjs",
26
+ "default": "./fesm2022/primus-angular-auth.mjs"
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,5 @@
1
+ export * from './lib/primus-auth.service';
2
+ export * from './lib/primus-auth.interceptor';
3
+ export * from './lib/primus-auth.guard';
4
+ export * from './lib/primus-auth.provider';
5
+ export * from './lib/primus-auth.types';