@memberjunction/ng-auth-services 5.30.1 → 5.31.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.
@@ -291,16 +291,16 @@ describe('logout and cache clearing', () => {
291
291
  const { removeItem } = stubLocalStorage({
292
292
  'mj-session-id': 'abc',
293
293
  'auth0.token': 'xyz',
294
- 'mj-login-theme': 'dark',
294
+ 'mj-theme': 'dark',
295
295
  });
296
296
  stubIndexedDB();
297
297
  await makeProvider().logout();
298
298
  expect(removeItem).toHaveBeenCalledWith('mj-session-id');
299
299
  expect(removeItem).toHaveBeenCalledWith('auth0.token');
300
- expect(removeItem).not.toHaveBeenCalledWith('mj-login-theme');
300
+ expect(removeItem).not.toHaveBeenCalledWith('mj-theme');
301
301
  });
302
- it('should preserve mj-login-theme by default even when it is the only key', async () => {
303
- const { removeItem } = stubLocalStorage({ 'mj-login-theme': 'dark' });
302
+ it('should preserve mj-theme by default even when it is the only key', async () => {
303
+ const { removeItem } = stubLocalStorage({ 'mj-theme': 'dark' });
304
304
  stubIndexedDB();
305
305
  await makeProvider().logout();
306
306
  expect(removeItem).not.toHaveBeenCalled();
@@ -345,14 +345,14 @@ describe('logout and cache clearing', () => {
345
345
  });
346
346
  it('should respect overridden preservedLocalStorageKeys in a subclass', async () => {
347
347
  const { removeItem } = stubLocalStorage({
348
- 'mj-login-theme': 'dark',
348
+ 'mj-theme': 'dark',
349
349
  'my-app-setting': 'value',
350
350
  'session-data': 'to-remove',
351
351
  });
352
352
  stubIndexedDB();
353
- await makeProvider(new Set(['mj-login-theme', 'my-app-setting'])).logout();
353
+ await makeProvider(new Set(['mj-theme', 'my-app-setting'])).logout();
354
354
  expect(removeItem).toHaveBeenCalledWith('session-data');
355
- expect(removeItem).not.toHaveBeenCalledWith('mj-login-theme');
355
+ expect(removeItem).not.toHaveBeenCalledWith('mj-theme');
356
356
  expect(removeItem).not.toHaveBeenCalledWith('my-app-setting');
357
357
  });
358
358
  });
@@ -1 +1 @@
1
- {"version":3,"file":"auth-services.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/auth-services.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tests for auth-services package:\n * - AngularAuthProviderFactory\n * - Auth types\n * - MJAuthBase (via dynamic import)\n */\nimport { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';\nimport { AuthErrorType } from '../auth-types';\n\n// Mock Angular\nvi.mock('@angular/core', () => ({\n Injectable: () => (target: Function) => target,\n Injector: class {},\n}));\n\nvi.mock('@memberjunction/global', () => ({\n MJGlobal: {\n Instance: {\n ClassFactory: {\n CreateInstance: vi.fn(),\n GetRegistrationsByRootClass: vi.fn(() => []),\n GetRegistration: vi.fn(),\n },\n }\n },\n}));\n\nvi.mock('@memberjunction/core', () => ({\n AuthProviderConfig: class {},\n}));\n\nvi.mock('rxjs', async () => {\n const actual = await vi.importActual<typeof import('rxjs')>('rxjs');\n return actual;\n});\n\n// ======================= Auth types =======================\ndescribe('AuthErrorType enum', () => {\n it('should have expected error types', async () => {\n const { AuthErrorType } = await import('../auth-types');\n expect(AuthErrorType.TOKEN_EXPIRED).toBe('TOKEN_EXPIRED');\n expect(AuthErrorType.NO_ACTIVE_SESSION).toBe('NO_ACTIVE_SESSION');\n expect(AuthErrorType.INTERACTION_REQUIRED).toBe('INTERACTION_REQUIRED');\n expect(AuthErrorType.USER_CANCELLED).toBe('USER_CANCELLED');\n expect(AuthErrorType.NETWORK_ERROR).toBe('NETWORK_ERROR');\n expect(AuthErrorType.CONFIGURATION_ERROR).toBe('CONFIGURATION_ERROR');\n expect(AuthErrorType.UNKNOWN_ERROR).toBe('UNKNOWN_ERROR');\n });\n});\n\n// ======================= IAuthProvider interface =======================\ndescribe('IAuthProvider interface', () => {\n it('should export the interface module', async () => {\n const mod = await import('../IAuthProvider');\n expect(mod).toBeDefined();\n });\n});\n\n// ======================= MJAuthBase =======================\ndescribe('MJAuthBase', () => {\n let MJAuthBase: typeof import('../mjexplorer-auth-base.service').MJAuthBase;\n\n beforeEach(async () => {\n // Mock window before importing\n (global as Record<string, unknown>).window = { location: { pathname: '/test', search: '?q=1' } };\n\n const mod = await import('../mjexplorer-auth-base.service');\n MJAuthBase = mod.MJAuthBase;\n });\n\n it('should be importable', () => {\n expect(MJAuthBase).toBeDefined();\n });\n\n it('should capture initial window location in constructor', () => {\n // Create a concrete test subclass inline\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n expect(provider.initialPath).toBe('/test');\n expect(provider.initialSearch).toBe('?q=1');\n });\n\n it('should validate config with clientId', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n expect(provider.validateConfig({ clientId: 'my-client' })).toBe(true);\n expect(provider.validateConfig({})).toBe(false);\n expect(provider.validateConfig({ clientId: '' })).toBe(false);\n });\n\n it('should return clientId as required config', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n expect(provider.getRequiredConfig()).toEqual(['clientId']);\n });\n\n it('should emit false for isAuthenticated initially', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n let value: boolean | undefined;\n provider.isAuthenticated().subscribe(v => value = v);\n expect(value).toBe(false);\n });\n\n it('should emit null for getUserInfo initially', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n let value: unknown = 'not-null';\n provider.getUserInfo().subscribe(v => value = v);\n expect(value).toBeNull();\n });\n\n it('should delegate classifyError to classifyErrorInternal', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'Custom error msg' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n const result = provider.classifyError(new Error('test'));\n expect(result.type).toBe('UNKNOWN_ERROR');\n expect(result.message).toBe('Custom error msg');\n });\n\n it('should return token from getIdToken', async () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'my-test-token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n const token = await provider.getIdToken();\n expect(token).toBe('my-test-token');\n });\n\n it('should return an observable from login', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n const result = provider.login();\n expect(result).toBeDefined();\n expect(typeof result.subscribe).toBe('function');\n });\n});\n\n// ======================= logout and cache clearing =======================\ndescribe('logout and cache clearing', () => {\n let MJAuthBase: typeof import('../mjexplorer-auth-base.service').MJAuthBase;\n\n beforeEach(async () => {\n (global as Record<string, unknown>).window = { location: { pathname: '/test', search: '' } };\n const mod = await import('../mjexplorer-auth-base.service');\n MJAuthBase = mod.MJAuthBase;\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n });\n\n /**\n * Build a minimal TestProvider. The logoutSpy tracks logoutInternal calls.\n * Pass preservedKeys to override the default preservedLocalStorageKeys getter.\n */\n function makeProvider(preservedKeys?: Set<string>) {\n const logoutSpy = vi.fn<() => Promise<void>>().mockResolvedValue(undefined);\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n readonly logoutSpy = logoutSpy;\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> { return logoutSpy(); }\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true as const, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n override get preservedLocalStorageKeys(): Set<string> {\n return preservedKeys ?? super.preservedLocalStorageKeys;\n }\n }\n return new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n }\n\n /** Stub localStorage with a fixed set of key/value pairs, return a spy on removeItem. */\n function stubLocalStorage(items: Record<string, string>) {\n const keys = Object.keys(items);\n const removeItem = vi.fn();\n vi.stubGlobal('localStorage', {\n length: keys.length,\n key: (i: number) => keys[i] ?? null,\n removeItem,\n });\n return { removeItem };\n }\n\n /** Stub indexedDB.deleteDatabase to resolve immediately via onsuccess. */\n function stubIndexedDB() {\n const deleteDatabase = vi.fn(() => {\n const req = {} as Record<string, unknown>;\n Object.defineProperty(req, 'onsuccess', { configurable: true, set(fn: () => void) { fn(); } });\n Object.defineProperty(req, 'onerror', { configurable: true, set() {} });\n Object.defineProperty(req, 'onblocked', { configurable: true, set() {} });\n return req;\n });\n vi.stubGlobal('indexedDB', { deleteDatabase });\n return { deleteDatabase };\n }\n\n it('should call logoutInternal during logout', async () => {\n stubLocalStorage({});\n stubIndexedDB();\n const provider = makeProvider();\n await provider.logout();\n expect(provider.logoutSpy).toHaveBeenCalledOnce();\n });\n\n it('should remove non-preserved localStorage keys on logout', async () => {\n const { removeItem } = stubLocalStorage({\n 'mj-session-id': 'abc',\n 'auth0.token': 'xyz',\n 'mj-login-theme': 'dark',\n });\n stubIndexedDB();\n await makeProvider().logout();\n expect(removeItem).toHaveBeenCalledWith('mj-session-id');\n expect(removeItem).toHaveBeenCalledWith('auth0.token');\n expect(removeItem).not.toHaveBeenCalledWith('mj-login-theme');\n });\n\n it('should preserve mj-login-theme by default even when it is the only key', async () => {\n const { removeItem } = stubLocalStorage({ 'mj-login-theme': 'dark' });\n stubIndexedDB();\n await makeProvider().logout();\n expect(removeItem).not.toHaveBeenCalled();\n });\n\n it('should delete the MJ_Metadata IndexedDB on logout', async () => {\n stubLocalStorage({});\n const { deleteDatabase } = stubIndexedDB();\n await makeProvider().logout();\n expect(deleteDatabase).toHaveBeenCalledWith('MJ_Metadata');\n });\n\n it('should clear caches before calling logoutInternal', async () => {\n const callOrder: string[] = [];\n const deleteDatabase = vi.fn(() => {\n callOrder.push('clearCaches');\n const req = {} as Record<string, unknown>;\n Object.defineProperty(req, 'onsuccess', { configurable: true, set(fn: () => void) { fn(); } });\n Object.defineProperty(req, 'onerror', { configurable: true, set() {} });\n Object.defineProperty(req, 'onblocked', { configurable: true, set() {} });\n return req;\n });\n vi.stubGlobal('indexedDB', { deleteDatabase });\n stubLocalStorage({});\n\n const logoutSpy = vi.fn<() => Promise<void>>().mockImplementation(async () => {\n callOrder.push('logoutInternal');\n });\n class OrderTestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> { return logoutSpy(); }\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true as const, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n await new OrderTestProvider({ name: 'test', type: 'test', clientId: 'test-client' }).logout();\n expect(callOrder).toEqual(['clearCaches', 'logoutInternal']);\n });\n\n it('should respect overridden preservedLocalStorageKeys in a subclass', async () => {\n const { removeItem } = stubLocalStorage({\n 'mj-login-theme': 'dark',\n 'my-app-setting': 'value',\n 'session-data': 'to-remove',\n });\n stubIndexedDB();\n await makeProvider(new Set(['mj-login-theme', 'my-app-setting'])).logout();\n expect(removeItem).toHaveBeenCalledWith('session-data');\n expect(removeItem).not.toHaveBeenCalledWith('mj-login-theme');\n expect(removeItem).not.toHaveBeenCalledWith('my-app-setting');\n });\n});\n\n// ======================= AngularAuthProviderFactory =======================\ndescribe('AngularAuthProviderFactory', () => {\n let Factory: typeof import('../AngularAuthProviderFactory').AngularAuthProviderFactory;\n\n beforeEach(async () => {\n const mod = await import('../AngularAuthProviderFactory');\n Factory = mod.AngularAuthProviderFactory;\n });\n\n it('should create a new factory instance', () => {\n const factory = new Factory({ get: vi.fn() } as never);\n expect(factory).toBeDefined();\n });\n\n it('should return undefined for unregistered provider', () => {\n const factory = new Factory({ get: vi.fn() } as never);\n expect(factory.getProvider('nonexistent')).toBeUndefined();\n });\n\n it('should clear providers', () => {\n const factory = new Factory({ get: vi.fn() } as never);\n factory.clearProviders();\n expect(factory.getProvider('test')).toBeUndefined();\n });\n});\n"]}
1
+ {"version":3,"file":"auth-services.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/auth-services.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tests for auth-services package:\n * - AngularAuthProviderFactory\n * - Auth types\n * - MJAuthBase (via dynamic import)\n */\nimport { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';\nimport { AuthErrorType } from '../auth-types';\n\n// Mock Angular\nvi.mock('@angular/core', () => ({\n Injectable: () => (target: Function) => target,\n Injector: class {},\n}));\n\nvi.mock('@memberjunction/global', () => ({\n MJGlobal: {\n Instance: {\n ClassFactory: {\n CreateInstance: vi.fn(),\n GetRegistrationsByRootClass: vi.fn(() => []),\n GetRegistration: vi.fn(),\n },\n }\n },\n}));\n\nvi.mock('@memberjunction/core', () => ({\n AuthProviderConfig: class {},\n}));\n\nvi.mock('rxjs', async () => {\n const actual = await vi.importActual<typeof import('rxjs')>('rxjs');\n return actual;\n});\n\n// ======================= Auth types =======================\ndescribe('AuthErrorType enum', () => {\n it('should have expected error types', async () => {\n const { AuthErrorType } = await import('../auth-types');\n expect(AuthErrorType.TOKEN_EXPIRED).toBe('TOKEN_EXPIRED');\n expect(AuthErrorType.NO_ACTIVE_SESSION).toBe('NO_ACTIVE_SESSION');\n expect(AuthErrorType.INTERACTION_REQUIRED).toBe('INTERACTION_REQUIRED');\n expect(AuthErrorType.USER_CANCELLED).toBe('USER_CANCELLED');\n expect(AuthErrorType.NETWORK_ERROR).toBe('NETWORK_ERROR');\n expect(AuthErrorType.CONFIGURATION_ERROR).toBe('CONFIGURATION_ERROR');\n expect(AuthErrorType.UNKNOWN_ERROR).toBe('UNKNOWN_ERROR');\n });\n});\n\n// ======================= IAuthProvider interface =======================\ndescribe('IAuthProvider interface', () => {\n it('should export the interface module', async () => {\n const mod = await import('../IAuthProvider');\n expect(mod).toBeDefined();\n });\n});\n\n// ======================= MJAuthBase =======================\ndescribe('MJAuthBase', () => {\n let MJAuthBase: typeof import('../mjexplorer-auth-base.service').MJAuthBase;\n\n beforeEach(async () => {\n // Mock window before importing\n (global as Record<string, unknown>).window = { location: { pathname: '/test', search: '?q=1' } };\n\n const mod = await import('../mjexplorer-auth-base.service');\n MJAuthBase = mod.MJAuthBase;\n });\n\n it('should be importable', () => {\n expect(MJAuthBase).toBeDefined();\n });\n\n it('should capture initial window location in constructor', () => {\n // Create a concrete test subclass inline\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n expect(provider.initialPath).toBe('/test');\n expect(provider.initialSearch).toBe('?q=1');\n });\n\n it('should validate config with clientId', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n expect(provider.validateConfig({ clientId: 'my-client' })).toBe(true);\n expect(provider.validateConfig({})).toBe(false);\n expect(provider.validateConfig({ clientId: '' })).toBe(false);\n });\n\n it('should return clientId as required config', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n expect(provider.getRequiredConfig()).toEqual(['clientId']);\n });\n\n it('should emit false for isAuthenticated initially', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n let value: boolean | undefined;\n provider.isAuthenticated().subscribe(v => value = v);\n expect(value).toBe(false);\n });\n\n it('should emit null for getUserInfo initially', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n let value: unknown = 'not-null';\n provider.getUserInfo().subscribe(v => value = v);\n expect(value).toBeNull();\n });\n\n it('should delegate classifyError to classifyErrorInternal', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'Custom error msg' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n const result = provider.classifyError(new Error('test'));\n expect(result.type).toBe('UNKNOWN_ERROR');\n expect(result.message).toBe('Custom error msg');\n });\n\n it('should return token from getIdToken', async () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'my-test-token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n const token = await provider.getIdToken();\n expect(token).toBe('my-test-token');\n });\n\n it('should return an observable from login', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n const result = provider.login();\n expect(result).toBeDefined();\n expect(typeof result.subscribe).toBe('function');\n });\n});\n\n// ======================= logout and cache clearing =======================\ndescribe('logout and cache clearing', () => {\n let MJAuthBase: typeof import('../mjexplorer-auth-base.service').MJAuthBase;\n\n beforeEach(async () => {\n (global as Record<string, unknown>).window = { location: { pathname: '/test', search: '' } };\n const mod = await import('../mjexplorer-auth-base.service');\n MJAuthBase = mod.MJAuthBase;\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n });\n\n /**\n * Build a minimal TestProvider. The logoutSpy tracks logoutInternal calls.\n * Pass preservedKeys to override the default preservedLocalStorageKeys getter.\n */\n function makeProvider(preservedKeys?: Set<string>) {\n const logoutSpy = vi.fn<() => Promise<void>>().mockResolvedValue(undefined);\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n readonly logoutSpy = logoutSpy;\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> { return logoutSpy(); }\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true as const, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n override get preservedLocalStorageKeys(): Set<string> {\n return preservedKeys ?? super.preservedLocalStorageKeys;\n }\n }\n return new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n }\n\n /** Stub localStorage with a fixed set of key/value pairs, return a spy on removeItem. */\n function stubLocalStorage(items: Record<string, string>) {\n const keys = Object.keys(items);\n const removeItem = vi.fn();\n vi.stubGlobal('localStorage', {\n length: keys.length,\n key: (i: number) => keys[i] ?? null,\n removeItem,\n });\n return { removeItem };\n }\n\n /** Stub indexedDB.deleteDatabase to resolve immediately via onsuccess. */\n function stubIndexedDB() {\n const deleteDatabase = vi.fn(() => {\n const req = {} as Record<string, unknown>;\n Object.defineProperty(req, 'onsuccess', { configurable: true, set(fn: () => void) { fn(); } });\n Object.defineProperty(req, 'onerror', { configurable: true, set() {} });\n Object.defineProperty(req, 'onblocked', { configurable: true, set() {} });\n return req;\n });\n vi.stubGlobal('indexedDB', { deleteDatabase });\n return { deleteDatabase };\n }\n\n it('should call logoutInternal during logout', async () => {\n stubLocalStorage({});\n stubIndexedDB();\n const provider = makeProvider();\n await provider.logout();\n expect(provider.logoutSpy).toHaveBeenCalledOnce();\n });\n\n it('should remove non-preserved localStorage keys on logout', async () => {\n const { removeItem } = stubLocalStorage({\n 'mj-session-id': 'abc',\n 'auth0.token': 'xyz',\n 'mj-theme': 'dark',\n });\n stubIndexedDB();\n await makeProvider().logout();\n expect(removeItem).toHaveBeenCalledWith('mj-session-id');\n expect(removeItem).toHaveBeenCalledWith('auth0.token');\n expect(removeItem).not.toHaveBeenCalledWith('mj-theme');\n });\n\n it('should preserve mj-theme by default even when it is the only key', async () => {\n const { removeItem } = stubLocalStorage({ 'mj-theme': 'dark' });\n stubIndexedDB();\n await makeProvider().logout();\n expect(removeItem).not.toHaveBeenCalled();\n });\n\n it('should delete the MJ_Metadata IndexedDB on logout', async () => {\n stubLocalStorage({});\n const { deleteDatabase } = stubIndexedDB();\n await makeProvider().logout();\n expect(deleteDatabase).toHaveBeenCalledWith('MJ_Metadata');\n });\n\n it('should clear caches before calling logoutInternal', async () => {\n const callOrder: string[] = [];\n const deleteDatabase = vi.fn(() => {\n callOrder.push('clearCaches');\n const req = {} as Record<string, unknown>;\n Object.defineProperty(req, 'onsuccess', { configurable: true, set(fn: () => void) { fn(); } });\n Object.defineProperty(req, 'onerror', { configurable: true, set() {} });\n Object.defineProperty(req, 'onblocked', { configurable: true, set() {} });\n return req;\n });\n vi.stubGlobal('indexedDB', { deleteDatabase });\n stubLocalStorage({});\n\n const logoutSpy = vi.fn<() => Promise<void>>().mockImplementation(async () => {\n callOrder.push('logoutInternal');\n });\n class OrderTestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> { return logoutSpy(); }\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true as const, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n await new OrderTestProvider({ name: 'test', type: 'test', clientId: 'test-client' }).logout();\n expect(callOrder).toEqual(['clearCaches', 'logoutInternal']);\n });\n\n it('should respect overridden preservedLocalStorageKeys in a subclass', async () => {\n const { removeItem } = stubLocalStorage({\n 'mj-theme': 'dark',\n 'my-app-setting': 'value',\n 'session-data': 'to-remove',\n });\n stubIndexedDB();\n await makeProvider(new Set(['mj-theme', 'my-app-setting'])).logout();\n expect(removeItem).toHaveBeenCalledWith('session-data');\n expect(removeItem).not.toHaveBeenCalledWith('mj-theme');\n expect(removeItem).not.toHaveBeenCalledWith('my-app-setting');\n });\n});\n\n// ======================= AngularAuthProviderFactory =======================\ndescribe('AngularAuthProviderFactory', () => {\n let Factory: typeof import('../AngularAuthProviderFactory').AngularAuthProviderFactory;\n\n beforeEach(async () => {\n const mod = await import('../AngularAuthProviderFactory');\n Factory = mod.AngularAuthProviderFactory;\n });\n\n it('should create a new factory instance', () => {\n const factory = new Factory({ get: vi.fn() } as never);\n expect(factory).toBeDefined();\n });\n\n it('should return undefined for unregistered provider', () => {\n const factory = new Factory({ get: vi.fn() } as never);\n expect(factory.getProvider('nonexistent')).toBeUndefined();\n });\n\n it('should clear providers', () => {\n const factory = new Factory({ get: vi.fn() } as never);\n factory.clearProviders();\n expect(factory.getProvider('test')).toBeUndefined();\n });\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"mjexplorer-auth-base.service.d.ts","sourceRoot":"","sources":["../../src/lib/mjexplorer-auth-base.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mjexplorer-auth-base.service.d.ts","sourceRoot":"","sources":["../../src/lib/mjexplorer-auth-base.service.ts"],"names":[],"mappings":"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"}
@@ -80,7 +80,11 @@ export class MJAuthBase {
80
80
  * to your provider or application.
81
81
  */
82
82
  get preservedLocalStorageKeys() {
83
- return new Set(['mj-login-theme']);
83
+ // 'mj-theme' is the unified theme key used by the inline pre-paint
84
+ // script in index.html, MJExplorerAppComponent's login screen, and
85
+ // ThemeService post-login. Preserving across logout means the login
86
+ // screen continues to show the user's last theme without flashing.
87
+ return new Set(['mj-theme']);
84
88
  }
85
89
  /**
86
90
  * Clears MJ client-side caches before logout.
@@ -1 +1 @@
1
- {"version":3,"file":"mjexplorer-auth-base.service.js","sourceRoot":"","sources":["../../src/lib/mjexplorer-auth-base.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { Observable, BehaviorSubject, from } from 'rxjs';\nimport { IAngularAuthProvider, AngularAuthProviderConfig } from './IAuthProvider';\nimport {\n StandardUserInfo,\n StandardAuthToken,\n StandardAuthError,\n TokenRefreshResult\n} from './auth-types';\n\n/**\n * Base class for Angular authentication providers - v3.0.0\n *\n * Provides common functionality and enforces the provider interface.\n * All concrete providers (MSAL, Auth0, Okta) should extend this class.\n *\n * ## Key Improvements in v3.0:\n * - Proper abstraction - no more leaky provider-specific logic\n * - Standardized types - no more `any` types\n * - Clean token access - no more `__raw || idToken` patterns\n * - Semantic error handling - no more provider-specific error checks\n *\n * ## For Provider Implementers:\n * Extend this class and implement the abstract methods:\n * - `extractIdTokenInternal()` - Extract token from provider storage\n * - `extractTokenInfoInternal()` - Extract full token info\n * - `extractUserInfoInternal()` - Map claims to StandardUserInfo\n * - `refreshTokenInternal()` - Implement refresh mechanism\n * - `classifyErrorInternal()` - Map errors to AuthErrorType\n *\n * @version 3.0.0\n */\n@Injectable()\nexport abstract class MJAuthBase implements IAngularAuthProvider {\n protected config: AngularAuthProviderConfig;\n\n // State management with proper types (no more 'any'!)\n protected isAuthenticated$ = new BehaviorSubject<boolean>(false);\n protected userInfo$ = new BehaviorSubject<StandardUserInfo | null>(null);\n protected userEmail$ = new BehaviorSubject<string>('');\n\n private _initialPath: string | null = null;\n private _initialSearch: string | null = null;\n\n /**\n * Contains the initial path from window.location.pathname before any work was done by auth services\n */\n get initialPath(): string | null {\n return this._initialPath;\n }\n\n /**\n * Contains the initial search/query string from window.location.search before any work was done by auth services\n */\n get initialSearch(): string | null {\n return this._initialSearch;\n }\n\n /**\n * Provider type identifier\n * Must be implemented by concrete providers\n */\n abstract readonly type: string;\n\n constructor(config: AngularAuthProviderConfig) {\n this.config = config;\n this._initialPath = window.location.pathname;\n this._initialSearch = window.location.search;\n }\n\n // ============================================================================\n // ABSTRACT METHODS (Must be implemented by concrete providers)\n // ============================================================================\n\n /**\n * Initialize the provider\n *\n * Subclasses should override to set up provider-specific initialization,\n * handle redirect callbacks, restore sessions, etc.\n */\n abstract initialize(): Promise<void>;\n\n /**\n * Internal login implementation\n *\n * Subclasses implement provider-specific login flow.\n * This is called by the public login() method.\n */\n protected abstract loginInternal(options?: Record<string, unknown>): Promise<void>;\n\n /**\n * Provider-specific logout implementation\n *\n * Subclasses implement provider-specific logout flow (redirect, SDK logout, etc.).\n * The base class `logout()` calls `clearClientCaches()` before invoking this method,\n * so providers do NOT need to handle cache clearing themselves.\n */\n protected abstract logoutInternal(): Promise<void>;\n\n /**\n * Handle OAuth callback\n *\n * Subclasses implement provider-specific callback handling.\n */\n abstract handleCallback(): Promise<void>;\n\n /**\n * Extract ID token from provider-specific storage\n *\n * This is where providers hide their implementation details.\n * - Auth0: Extracts from claims.__raw\n * - MSAL: Extracts from response.idToken\n * - Okta: Extracts from authState.idToken\n *\n * @returns Promise resolving to token string or null if not authenticated\n */\n protected abstract extractIdTokenInternal(): Promise<string | null>;\n\n /**\n * Extract complete token info from provider-specific storage\n *\n * Maps provider-specific token structure to StandardAuthToken.\n *\n * @returns Promise resolving to StandardAuthToken or null if not authenticated\n */\n protected abstract extractTokenInfoInternal(): Promise<StandardAuthToken | null>;\n\n /**\n * Extract user info from provider-specific claims\n *\n * Maps provider-specific claim structure to StandardUserInfo.\n * This is where providers translate their claims (sub, email, name, etc.)\n * into the standard structure.\n *\n * @returns Promise resolving to StandardUserInfo or null if not authenticated\n */\n protected abstract extractUserInfoInternal(): Promise<StandardUserInfo | null>;\n\n /**\n * Refresh token using provider-specific mechanism\n *\n * Implements the provider's token refresh logic using whatever mechanism\n * is appropriate (silent refresh with refresh tokens, iframe-based token\n * acquisition, etc.).\n *\n * Should return success with token if refresh succeeds, or failure with\n * appropriate error type (TOKEN_EXPIRED, INTERACTION_REQUIRED, etc.) if\n * refresh fails.\n *\n * @returns Promise resolving to TokenRefreshResult indicating success/failure\n */\n protected abstract refreshTokenInternal(): Promise<TokenRefreshResult>;\n\n /**\n * Classify provider-specific error into standard error type\n *\n * Maps provider-specific errors to semantic AuthErrorType values.\n * Examines error objects, error codes, and messages to determine the\n * appropriate category (TOKEN_EXPIRED, INTERACTION_REQUIRED, NETWORK_ERROR, etc.).\n *\n * @param error The error to classify\n * @returns StandardAuthError with categorized type and user-friendly message\n */\n protected abstract classifyErrorInternal(error: unknown): StandardAuthError;\n\n /**\n * Get profile picture URL from auth provider\n *\n * Retrieves the user's profile picture using provider-specific mechanisms.\n * Some providers include the URL in user claims, others require API calls\n * to fetch the image.\n *\n * @returns Promise resolving to image URL or null if not available\n */\n protected abstract getProfilePictureUrlInternal(): Promise<string | null>;\n\n /**\n * Handle session expiry when silent refresh fails\n *\n * Called internally when silent token refresh fails with TOKEN_EXPIRED or\n * INTERACTION_REQUIRED errors. Providers that support refresh tokens can\n * implement this as a no-op. Providers that require interactive re-authentication\n * should initiate the appropriate flow (redirect, popup, etc.).\n *\n * Note: If this method redirects the page, it may never return. The app will\n * reload after authentication completes and re-initialize with a fresh token.\n *\n * @returns Promise that resolves if re-auth completed, or never returns if redirected\n */\n protected abstract handleSessionExpiryInternal(): Promise<void>;\n\n // ============================================================================\n // PUBLIC API (Concrete implementations using abstract internals)\n // ============================================================================\n\n /**\n * Public login method with Observable wrapper for backward compatibility\n *\n * Consumers can use either:\n * - `await this.authBase.login()` (Promise)\n * - `this.authBase.login().subscribe()` (Observable)\n */\n login(options?: Record<string, unknown>): Observable<void> {\n return from(this.loginInternal(options));\n }\n\n /**\n * Logout — clears all MJ client-side caches then delegates to the provider.\n *\n * Cache clearing happens universally regardless of auth provider so that a\n * subsequent login as a different user never sees the previous user's data.\n * Providers that need to clear additional caches should override\n * `logoutInternal()` and call `super.logoutInternal()` if applicable.\n */\n async logout(): Promise<void> {\n await this.clearClientCaches();\n await this.logoutInternal();\n }\n\n /**\n * localStorage keys that survive a logout (e.g. UI theme preference).\n *\n * Override this getter in a subclass to preserve additional keys specific\n * to your provider or application.\n */\n protected get preservedLocalStorageKeys(): Set<string> {\n return new Set(['mj-login-theme']);\n }\n\n /**\n * Clears MJ client-side caches before logout.\n *\n * Removes all localStorage entries except those returned by\n * `preservedLocalStorageKeys`, and deletes the `MJ_Metadata` IndexedDB\n * database so a subsequent user session starts with a clean slate.\n */\n protected async clearClientCaches(): Promise<void> {\n const preserved = this.preservedLocalStorageKeys;\n const keysToRemove: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && !preserved.has(key)) {\n keysToRemove.push(key);\n }\n }\n keysToRemove.forEach(key => localStorage.removeItem(key));\n\n await new Promise<void>((resolve) => {\n const req = indexedDB.deleteDatabase('MJ_Metadata');\n req.onsuccess = () => resolve();\n req.onerror = () => resolve();\n req.onblocked = () => resolve();\n });\n }\n\n /**\n * Check if user is authenticated (Observable stream)\n *\n * Returns a reactive stream that emits authentication state changes.\n * Consumers can subscribe to react to login/logout events.\n */\n isAuthenticated(): Observable<boolean> {\n return this.isAuthenticated$.asObservable();\n }\n\n /**\n * Get user info as Observable stream\n *\n * Returns standardized user info, hiding provider-specific claim structures.\n * No more need for consumers to merge claims or check provider-specific fields!\n */\n getUserInfo(): Observable<StandardUserInfo | null> {\n return this.userInfo$.asObservable();\n }\n\n /**\n * Get user email as Observable stream\n */\n getUserEmail(): Observable<string> {\n return this.userEmail$.asObservable();\n }\n\n /**\n * Get ID token string (primary token method)\n *\n * This is the clean abstraction - no provider-specific logic needed!\n * Replaces the old pattern of: `claims?.__raw || claims?.idToken`\n *\n * @example\n * ```typescript\n * const token = await this.authBase.getIdToken();\n * if (token) {\n * setupGraphQLClient(token, apiUrl);\n * }\n * ```\n */\n async getIdToken(): Promise<string | null> {\n return this.extractIdTokenInternal();\n }\n\n /**\n * Get complete token information\n *\n * Returns full token details including expiration and scopes.\n * Use this when you need more than just the token string.\n */\n async getTokenInfo(): Promise<StandardAuthToken | null> {\n return this.extractTokenInfoInternal();\n }\n\n /**\n * Refresh authentication token\n *\n * Attempts to obtain a fresh authentication token using the provider's\n * refresh mechanism. If silent refresh fails due to session expiry, the\n * provider will handle re-authentication automatically (which may involve\n * redirecting to the auth provider's login page).\n *\n * Returns StandardAuthToken on success, or throws on complete failure.\n *\n * IMPORTANT: If the provider requires interactive re-authentication (redirect\n * or popup), this method may never return. The app will reload after\n * authentication completes and re-initialize with a fresh token.\n *\n * @returns Promise resolving to StandardAuthToken or throws on failure\n *\n * @example\n * ```typescript\n * const token = await this.authBase.refreshToken();\n * return token.idToken; // Always succeeds or throws\n * ```\n */\n async refreshToken(): Promise<StandardAuthToken> {\n // Try silent refresh\n const result = await this.refreshTokenInternal();\n\n if (result.success && result.token) {\n // Update state if refresh succeeded\n try {\n const userInfo = await this.extractUserInfoInternal();\n if (userInfo) {\n this.updateUserInfo(userInfo);\n }\n } catch {\n // User info update failed, but token refresh succeeded\n // Don't fail the entire refresh for this\n }\n\n return result.token;\n }\n\n // Silent refresh failed - check if we can handle session expiry\n const errorType = result.error?.type;\n if (errorType === 'TOKEN_EXPIRED' || errorType === 'INTERACTION_REQUIRED') {\n // Let provider handle session expiry (may redirect and never return)\n await this.handleSessionExpiryInternal();\n\n // If we reach here (didn't redirect), retry refresh once\n const retryResult = await this.refreshTokenInternal();\n if (retryResult.success && retryResult.token) {\n // Update state with new token\n try {\n const userInfo = await this.extractUserInfoInternal();\n if (userInfo) {\n this.updateUserInfo(userInfo);\n }\n } catch {\n // Ignore user info update errors\n }\n\n return retryResult.token;\n }\n }\n\n // Complete failure - throw error\n throw new Error(result.error?.userMessage || 'Token refresh failed');\n }\n\n /**\n * Classify an error into standard error type\n *\n * Converts provider-specific errors into semantic categories.\n * Eliminates need for consumers to check error.name or error types.\n *\n * @example\n * ```typescript\n * const authError = this.authBase.classifyError(err);\n * if (authError.type === AuthErrorType.TOKEN_EXPIRED) {\n * this.showMessage(authError.userMessage);\n * }\n * ```\n */\n classifyError(error: unknown): StandardAuthError {\n return this.classifyErrorInternal(error);\n }\n\n /**\n * Get profile picture URL from auth provider\n *\n * Returns the user's profile picture URL if available from the auth provider.\n * This abstracts away provider-specific logic:\n * - Microsoft/MSAL: Fetches from Graph API\n * - Auth0/Okta: Returns from user claims\n *\n * @returns Promise resolving to image URL or null if not available\n *\n * @example\n * ```typescript\n * const pictureUrl = await this.authBase.getProfilePictureUrl();\n * if (pictureUrl) {\n * this.userAvatar = pictureUrl;\n * }\n * ```\n */\n async getProfilePictureUrl(): Promise<string | null> {\n return this.getProfilePictureUrlInternal();\n }\n\n // ============================================================================\n // HELPER METHODS (For subclasses to update state)\n // ============================================================================\n\n /**\n * Update authentication state\n *\n * Subclasses should call this when authentication state changes\n * (after login, logout, session check, etc.)\n */\n protected updateAuthState(isAuthenticated: boolean): void {\n this.isAuthenticated$.next(isAuthenticated);\n }\n\n /**\n * Update user info\n *\n * Subclasses should call this when user info is retrieved or updated.\n * This automatically updates the email stream as well.\n */\n protected updateUserInfo(userInfo: StandardUserInfo | null): void {\n this.userInfo$.next(userInfo);\n\n if (userInfo?.email) {\n this.userEmail$.next(userInfo.email);\n } else {\n this.userEmail$.next('');\n }\n }\n\n // ============================================================================\n // CONFIGURATION & VALIDATION\n // ============================================================================\n\n /**\n * Get required configuration fields\n *\n * Default implementation requires clientId.\n * Subclasses can override to add provider-specific requirements.\n */\n getRequiredConfig(): string[] {\n return ['clientId'];\n }\n\n /**\n * Validate provider configuration\n *\n * Checks that all required fields are present and non-empty.\n * Subclasses can override to add custom validation logic.\n */\n validateConfig(config: Record<string, unknown>): boolean {\n const requiredFields = this.getRequiredConfig();\n return requiredFields.every(field =>\n config[field] !== undefined && config[field] !== ''\n );\n }\n}\n"]}
1
+ {"version":3,"file":"mjexplorer-auth-base.service.js","sourceRoot":"","sources":["../../src/lib/mjexplorer-auth-base.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { Observable, BehaviorSubject, from } from 'rxjs';\nimport { IAngularAuthProvider, AngularAuthProviderConfig } from './IAuthProvider';\nimport {\n StandardUserInfo,\n StandardAuthToken,\n StandardAuthError,\n TokenRefreshResult\n} from './auth-types';\n\n/**\n * Base class for Angular authentication providers - v3.0.0\n *\n * Provides common functionality and enforces the provider interface.\n * All concrete providers (MSAL, Auth0, Okta) should extend this class.\n *\n * ## Key Improvements in v3.0:\n * - Proper abstraction - no more leaky provider-specific logic\n * - Standardized types - no more `any` types\n * - Clean token access - no more `__raw || idToken` patterns\n * - Semantic error handling - no more provider-specific error checks\n *\n * ## For Provider Implementers:\n * Extend this class and implement the abstract methods:\n * - `extractIdTokenInternal()` - Extract token from provider storage\n * - `extractTokenInfoInternal()` - Extract full token info\n * - `extractUserInfoInternal()` - Map claims to StandardUserInfo\n * - `refreshTokenInternal()` - Implement refresh mechanism\n * - `classifyErrorInternal()` - Map errors to AuthErrorType\n *\n * @version 3.0.0\n */\n@Injectable()\nexport abstract class MJAuthBase implements IAngularAuthProvider {\n protected config: AngularAuthProviderConfig;\n\n // State management with proper types (no more 'any'!)\n protected isAuthenticated$ = new BehaviorSubject<boolean>(false);\n protected userInfo$ = new BehaviorSubject<StandardUserInfo | null>(null);\n protected userEmail$ = new BehaviorSubject<string>('');\n\n private _initialPath: string | null = null;\n private _initialSearch: string | null = null;\n\n /**\n * Contains the initial path from window.location.pathname before any work was done by auth services\n */\n get initialPath(): string | null {\n return this._initialPath;\n }\n\n /**\n * Contains the initial search/query string from window.location.search before any work was done by auth services\n */\n get initialSearch(): string | null {\n return this._initialSearch;\n }\n\n /**\n * Provider type identifier\n * Must be implemented by concrete providers\n */\n abstract readonly type: string;\n\n constructor(config: AngularAuthProviderConfig) {\n this.config = config;\n this._initialPath = window.location.pathname;\n this._initialSearch = window.location.search;\n }\n\n // ============================================================================\n // ABSTRACT METHODS (Must be implemented by concrete providers)\n // ============================================================================\n\n /**\n * Initialize the provider\n *\n * Subclasses should override to set up provider-specific initialization,\n * handle redirect callbacks, restore sessions, etc.\n */\n abstract initialize(): Promise<void>;\n\n /**\n * Internal login implementation\n *\n * Subclasses implement provider-specific login flow.\n * This is called by the public login() method.\n */\n protected abstract loginInternal(options?: Record<string, unknown>): Promise<void>;\n\n /**\n * Provider-specific logout implementation\n *\n * Subclasses implement provider-specific logout flow (redirect, SDK logout, etc.).\n * The base class `logout()` calls `clearClientCaches()` before invoking this method,\n * so providers do NOT need to handle cache clearing themselves.\n */\n protected abstract logoutInternal(): Promise<void>;\n\n /**\n * Handle OAuth callback\n *\n * Subclasses implement provider-specific callback handling.\n */\n abstract handleCallback(): Promise<void>;\n\n /**\n * Extract ID token from provider-specific storage\n *\n * This is where providers hide their implementation details.\n * - Auth0: Extracts from claims.__raw\n * - MSAL: Extracts from response.idToken\n * - Okta: Extracts from authState.idToken\n *\n * @returns Promise resolving to token string or null if not authenticated\n */\n protected abstract extractIdTokenInternal(): Promise<string | null>;\n\n /**\n * Extract complete token info from provider-specific storage\n *\n * Maps provider-specific token structure to StandardAuthToken.\n *\n * @returns Promise resolving to StandardAuthToken or null if not authenticated\n */\n protected abstract extractTokenInfoInternal(): Promise<StandardAuthToken | null>;\n\n /**\n * Extract user info from provider-specific claims\n *\n * Maps provider-specific claim structure to StandardUserInfo.\n * This is where providers translate their claims (sub, email, name, etc.)\n * into the standard structure.\n *\n * @returns Promise resolving to StandardUserInfo or null if not authenticated\n */\n protected abstract extractUserInfoInternal(): Promise<StandardUserInfo | null>;\n\n /**\n * Refresh token using provider-specific mechanism\n *\n * Implements the provider's token refresh logic using whatever mechanism\n * is appropriate (silent refresh with refresh tokens, iframe-based token\n * acquisition, etc.).\n *\n * Should return success with token if refresh succeeds, or failure with\n * appropriate error type (TOKEN_EXPIRED, INTERACTION_REQUIRED, etc.) if\n * refresh fails.\n *\n * @returns Promise resolving to TokenRefreshResult indicating success/failure\n */\n protected abstract refreshTokenInternal(): Promise<TokenRefreshResult>;\n\n /**\n * Classify provider-specific error into standard error type\n *\n * Maps provider-specific errors to semantic AuthErrorType values.\n * Examines error objects, error codes, and messages to determine the\n * appropriate category (TOKEN_EXPIRED, INTERACTION_REQUIRED, NETWORK_ERROR, etc.).\n *\n * @param error The error to classify\n * @returns StandardAuthError with categorized type and user-friendly message\n */\n protected abstract classifyErrorInternal(error: unknown): StandardAuthError;\n\n /**\n * Get profile picture URL from auth provider\n *\n * Retrieves the user's profile picture using provider-specific mechanisms.\n * Some providers include the URL in user claims, others require API calls\n * to fetch the image.\n *\n * @returns Promise resolving to image URL or null if not available\n */\n protected abstract getProfilePictureUrlInternal(): Promise<string | null>;\n\n /**\n * Handle session expiry when silent refresh fails\n *\n * Called internally when silent token refresh fails with TOKEN_EXPIRED or\n * INTERACTION_REQUIRED errors. Providers that support refresh tokens can\n * implement this as a no-op. Providers that require interactive re-authentication\n * should initiate the appropriate flow (redirect, popup, etc.).\n *\n * Note: If this method redirects the page, it may never return. The app will\n * reload after authentication completes and re-initialize with a fresh token.\n *\n * @returns Promise that resolves if re-auth completed, or never returns if redirected\n */\n protected abstract handleSessionExpiryInternal(): Promise<void>;\n\n // ============================================================================\n // PUBLIC API (Concrete implementations using abstract internals)\n // ============================================================================\n\n /**\n * Public login method with Observable wrapper for backward compatibility\n *\n * Consumers can use either:\n * - `await this.authBase.login()` (Promise)\n * - `this.authBase.login().subscribe()` (Observable)\n */\n login(options?: Record<string, unknown>): Observable<void> {\n return from(this.loginInternal(options));\n }\n\n /**\n * Logout — clears all MJ client-side caches then delegates to the provider.\n *\n * Cache clearing happens universally regardless of auth provider so that a\n * subsequent login as a different user never sees the previous user's data.\n * Providers that need to clear additional caches should override\n * `logoutInternal()` and call `super.logoutInternal()` if applicable.\n */\n async logout(): Promise<void> {\n await this.clearClientCaches();\n await this.logoutInternal();\n }\n\n /**\n * localStorage keys that survive a logout (e.g. UI theme preference).\n *\n * Override this getter in a subclass to preserve additional keys specific\n * to your provider or application.\n */\n protected get preservedLocalStorageKeys(): Set<string> {\n // 'mj-theme' is the unified theme key used by the inline pre-paint\n // script in index.html, MJExplorerAppComponent's login screen, and\n // ThemeService post-login. Preserving across logout means the login\n // screen continues to show the user's last theme without flashing.\n return new Set(['mj-theme']);\n }\n\n /**\n * Clears MJ client-side caches before logout.\n *\n * Removes all localStorage entries except those returned by\n * `preservedLocalStorageKeys`, and deletes the `MJ_Metadata` IndexedDB\n * database so a subsequent user session starts with a clean slate.\n */\n protected async clearClientCaches(): Promise<void> {\n const preserved = this.preservedLocalStorageKeys;\n const keysToRemove: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && !preserved.has(key)) {\n keysToRemove.push(key);\n }\n }\n keysToRemove.forEach(key => localStorage.removeItem(key));\n\n await new Promise<void>((resolve) => {\n const req = indexedDB.deleteDatabase('MJ_Metadata');\n req.onsuccess = () => resolve();\n req.onerror = () => resolve();\n req.onblocked = () => resolve();\n });\n }\n\n /**\n * Check if user is authenticated (Observable stream)\n *\n * Returns a reactive stream that emits authentication state changes.\n * Consumers can subscribe to react to login/logout events.\n */\n isAuthenticated(): Observable<boolean> {\n return this.isAuthenticated$.asObservable();\n }\n\n /**\n * Get user info as Observable stream\n *\n * Returns standardized user info, hiding provider-specific claim structures.\n * No more need for consumers to merge claims or check provider-specific fields!\n */\n getUserInfo(): Observable<StandardUserInfo | null> {\n return this.userInfo$.asObservable();\n }\n\n /**\n * Get user email as Observable stream\n */\n getUserEmail(): Observable<string> {\n return this.userEmail$.asObservable();\n }\n\n /**\n * Get ID token string (primary token method)\n *\n * This is the clean abstraction - no provider-specific logic needed!\n * Replaces the old pattern of: `claims?.__raw || claims?.idToken`\n *\n * @example\n * ```typescript\n * const token = await this.authBase.getIdToken();\n * if (token) {\n * setupGraphQLClient(token, apiUrl);\n * }\n * ```\n */\n async getIdToken(): Promise<string | null> {\n return this.extractIdTokenInternal();\n }\n\n /**\n * Get complete token information\n *\n * Returns full token details including expiration and scopes.\n * Use this when you need more than just the token string.\n */\n async getTokenInfo(): Promise<StandardAuthToken | null> {\n return this.extractTokenInfoInternal();\n }\n\n /**\n * Refresh authentication token\n *\n * Attempts to obtain a fresh authentication token using the provider's\n * refresh mechanism. If silent refresh fails due to session expiry, the\n * provider will handle re-authentication automatically (which may involve\n * redirecting to the auth provider's login page).\n *\n * Returns StandardAuthToken on success, or throws on complete failure.\n *\n * IMPORTANT: If the provider requires interactive re-authentication (redirect\n * or popup), this method may never return. The app will reload after\n * authentication completes and re-initialize with a fresh token.\n *\n * @returns Promise resolving to StandardAuthToken or throws on failure\n *\n * @example\n * ```typescript\n * const token = await this.authBase.refreshToken();\n * return token.idToken; // Always succeeds or throws\n * ```\n */\n async refreshToken(): Promise<StandardAuthToken> {\n // Try silent refresh\n const result = await this.refreshTokenInternal();\n\n if (result.success && result.token) {\n // Update state if refresh succeeded\n try {\n const userInfo = await this.extractUserInfoInternal();\n if (userInfo) {\n this.updateUserInfo(userInfo);\n }\n } catch {\n // User info update failed, but token refresh succeeded\n // Don't fail the entire refresh for this\n }\n\n return result.token;\n }\n\n // Silent refresh failed - check if we can handle session expiry\n const errorType = result.error?.type;\n if (errorType === 'TOKEN_EXPIRED' || errorType === 'INTERACTION_REQUIRED') {\n // Let provider handle session expiry (may redirect and never return)\n await this.handleSessionExpiryInternal();\n\n // If we reach here (didn't redirect), retry refresh once\n const retryResult = await this.refreshTokenInternal();\n if (retryResult.success && retryResult.token) {\n // Update state with new token\n try {\n const userInfo = await this.extractUserInfoInternal();\n if (userInfo) {\n this.updateUserInfo(userInfo);\n }\n } catch {\n // Ignore user info update errors\n }\n\n return retryResult.token;\n }\n }\n\n // Complete failure - throw error\n throw new Error(result.error?.userMessage || 'Token refresh failed');\n }\n\n /**\n * Classify an error into standard error type\n *\n * Converts provider-specific errors into semantic categories.\n * Eliminates need for consumers to check error.name or error types.\n *\n * @example\n * ```typescript\n * const authError = this.authBase.classifyError(err);\n * if (authError.type === AuthErrorType.TOKEN_EXPIRED) {\n * this.showMessage(authError.userMessage);\n * }\n * ```\n */\n classifyError(error: unknown): StandardAuthError {\n return this.classifyErrorInternal(error);\n }\n\n /**\n * Get profile picture URL from auth provider\n *\n * Returns the user's profile picture URL if available from the auth provider.\n * This abstracts away provider-specific logic:\n * - Microsoft/MSAL: Fetches from Graph API\n * - Auth0/Okta: Returns from user claims\n *\n * @returns Promise resolving to image URL or null if not available\n *\n * @example\n * ```typescript\n * const pictureUrl = await this.authBase.getProfilePictureUrl();\n * if (pictureUrl) {\n * this.userAvatar = pictureUrl;\n * }\n * ```\n */\n async getProfilePictureUrl(): Promise<string | null> {\n return this.getProfilePictureUrlInternal();\n }\n\n // ============================================================================\n // HELPER METHODS (For subclasses to update state)\n // ============================================================================\n\n /**\n * Update authentication state\n *\n * Subclasses should call this when authentication state changes\n * (after login, logout, session check, etc.)\n */\n protected updateAuthState(isAuthenticated: boolean): void {\n this.isAuthenticated$.next(isAuthenticated);\n }\n\n /**\n * Update user info\n *\n * Subclasses should call this when user info is retrieved or updated.\n * This automatically updates the email stream as well.\n */\n protected updateUserInfo(userInfo: StandardUserInfo | null): void {\n this.userInfo$.next(userInfo);\n\n if (userInfo?.email) {\n this.userEmail$.next(userInfo.email);\n } else {\n this.userEmail$.next('');\n }\n }\n\n // ============================================================================\n // CONFIGURATION & VALIDATION\n // ============================================================================\n\n /**\n * Get required configuration fields\n *\n * Default implementation requires clientId.\n * Subclasses can override to add provider-specific requirements.\n */\n getRequiredConfig(): string[] {\n return ['clientId'];\n }\n\n /**\n * Validate provider configuration\n *\n * Checks that all required fields are present and non-empty.\n * Subclasses can override to add custom validation logic.\n */\n validateConfig(config: Record<string, unknown>): boolean {\n const requiredFields = this.getRequiredConfig();\n return requiredFields.every(field =>\n config[field] !== undefined && config[field] !== ''\n );\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-auth-services",
3
- "version": "5.30.1",
3
+ "version": "5.31.0",
4
4
  "description": "MemberJunction Explorer: Authentication Services",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -31,8 +31,8 @@
31
31
  "aws-amplify": "^6.0.0"
32
32
  },
33
33
  "dependencies": {
34
- "@memberjunction/core": "5.30.1",
35
- "@memberjunction/global": "5.30.1",
34
+ "@memberjunction/core": "5.31.0",
35
+ "@memberjunction/global": "5.31.0",
36
36
  "rxjs": "^7.8.2",
37
37
  "tslib": "^2.8.1"
38
38
  },