fix: fix all biome
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { JwtKeys } from '../validation/jwtkeys';
|
||||
import { StateValidationResult } from '../validation/state-validation-result';
|
||||
import type { JwtKeys } from '../validation/jwtkeys';
|
||||
import type { StateValidationResult } from '../validation/state-validation-result';
|
||||
|
||||
export interface CallbackContext {
|
||||
code: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { HttpErrorResponse, HttpHeaders } from '@ngify/http';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
@@ -32,9 +32,6 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
mockProvider(DataService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(CodeFlowCallbackHandlerService);
|
||||
dataService = TestBed.inject(DataService);
|
||||
urlService = TestBed.inject(UrlService);
|
||||
@@ -58,13 +55,13 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
() => ''
|
||||
);
|
||||
|
||||
service
|
||||
.codeFlowCallback('test-url', { configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.codeFlowCallback('test-url', { configId: 'configId1' })
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('throws error if no code is given', async () => {
|
||||
@@ -72,15 +69,19 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
.spyOn(urlService, 'getUrlParameter')
|
||||
.mockReturnValue('params');
|
||||
|
||||
getUrlParameterSpy.withArgs('test-url', 'code').mockReturnValue('');
|
||||
mockImplementationWhenArgsEqual(
|
||||
getUrlParameterSpy,
|
||||
['test-url', 'code'],
|
||||
() => ''
|
||||
);
|
||||
|
||||
service
|
||||
.codeFlowCallback('test-url', { configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.codeFlowCallback('test-url', { configId: 'configId1' })
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('returns callbackContext if all params are good', async () => {
|
||||
@@ -98,9 +99,10 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
existingIdToken: null,
|
||||
} as CallbackContext;
|
||||
|
||||
const callbackContext = await lastValueFrom(service
|
||||
.codeFlowCallback('test-url', { configId: 'configId1' }));
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
const callbackContext = await lastValueFrom(
|
||||
service.codeFlowCallback('test-url', { configId: 'configId1' })
|
||||
);
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -119,13 +121,15 @@ expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
'validateStateFromHashCallback'
|
||||
).mockReturnValue(false);
|
||||
|
||||
service
|
||||
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, {
|
||||
configId: 'configId1',
|
||||
})
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('throws error if authWellknownEndpoints is null is given', async () => {
|
||||
@@ -139,13 +143,15 @@ expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
() => null
|
||||
);
|
||||
|
||||
service
|
||||
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, {
|
||||
configId: 'configId1',
|
||||
})
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('throws error if tokenendpoint is null is given', async () => {
|
||||
@@ -159,13 +165,15 @@ expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
() => ({ tokenEndpoint: null })
|
||||
);
|
||||
|
||||
service
|
||||
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, {
|
||||
configId: 'configId1',
|
||||
})
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('calls dataService if all params are good', async () => {
|
||||
@@ -182,14 +190,17 @@ expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
'validateStateFromHashCallback'
|
||||
).mockReturnValue(true);
|
||||
|
||||
await lastValueFrom(service
|
||||
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' }));
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'tokenEndpoint',
|
||||
undefined,
|
||||
{ configId: 'configId1' },
|
||||
expect.any(HttpHeaders)
|
||||
);
|
||||
await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, {
|
||||
configId: 'configId1',
|
||||
})
|
||||
);
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'tokenEndpoint',
|
||||
undefined,
|
||||
{ configId: 'configId1' },
|
||||
expect.any(HttpHeaders)
|
||||
);
|
||||
});
|
||||
|
||||
it('calls url service with custom token params', async () => {
|
||||
@@ -215,12 +226,13 @@ expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
|
||||
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
|
||||
|
||||
await lastValueFrom(service
|
||||
.codeFlowCodeRequest({ code: 'foo' } as CallbackContext, config));
|
||||
expect(urlServiceSpy).toHaveBeenCalledExactlyOnceWith('foo', config, {
|
||||
foo: 'bar',
|
||||
});;
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
await lastValueFrom(
|
||||
service.codeFlowCodeRequest({ code: 'foo' } as CallbackContext, config)
|
||||
);
|
||||
expect(urlServiceSpy).toHaveBeenCalledExactlyOnceWith('foo', config, {
|
||||
foo: 'bar',
|
||||
});
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('calls dataService with correct headers if all params are good', async () => {
|
||||
@@ -241,13 +253,14 @@ expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
'validateStateFromHashCallback'
|
||||
).mockReturnValue(true);
|
||||
|
||||
await lastValueFrom(service
|
||||
.codeFlowCodeRequest({} as CallbackContext, config));
|
||||
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();;
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config)
|
||||
);
|
||||
const httpHeaders = postSpy.mock.calls.at(-1)?.[3] as HttpHeaders;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
});
|
||||
|
||||
it('returns error in case of http error', async () => {
|
||||
@@ -266,11 +279,13 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config).subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('retries request in case of no connection http error and succeeds', async () => {
|
||||
@@ -297,16 +312,15 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'validateStateFromHashCallback'
|
||||
).mockReturnValue(true);
|
||||
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config).subscribe({
|
||||
next: (res) => {
|
||||
expect(res).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
error: (err) => {
|
||||
// fails if there should be a result
|
||||
expect(err).toBeFalsy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
const res = await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config)
|
||||
);
|
||||
expect(res).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeFalsy();
|
||||
}
|
||||
});
|
||||
|
||||
it('retries request in case of no connection http error and fails because of http error afterwards', async () => {
|
||||
@@ -333,16 +347,15 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'validateStateFromHashCallback'
|
||||
).mockReturnValue(true);
|
||||
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config).subscribe({
|
||||
next: (res) => {
|
||||
// fails if there should be a result
|
||||
expect(res).toBeFalsy();
|
||||
},
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
});
|
||||
try {
|
||||
const res = await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config)
|
||||
);
|
||||
expect(res).toBeFalsy();
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, of, throwError, timer } from 'rxjs';
|
||||
import { type Observable, of, throwError, timer } from 'rxjs';
|
||||
import { catchError, mergeMap, retryWhen, switchMap } from 'rxjs/operators';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import { UrlService } from '../../utils/url/url.service';
|
||||
import { TokenValidationService } from '../../validation/token-validation.service';
|
||||
import { AuthResult, CallbackContext } from '../callback-context';
|
||||
import type { AuthResult, CallbackContext } from '../callback-context';
|
||||
import { FlowsDataService } from '../flows-data.service';
|
||||
import { isNetworkError } from './error-helper';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
@@ -83,17 +83,18 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({ keys: [] } as JwtKeys)
|
||||
);
|
||||
await lastValueFrom(service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
));
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);;
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
)
|
||||
);
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('writes refresh_token into the storage without reuse (refresh token rotation)', async () => {
|
||||
@@ -120,17 +121,18 @@ expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
of({ keys: [] } as JwtKeys)
|
||||
);
|
||||
|
||||
await lastValueFrom(service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
));
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);;
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
)
|
||||
);
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('writes refresh_token into the storage with reuse (without refresh token rotation)', async () => {
|
||||
@@ -157,18 +159,19 @@ expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({ keys: [] } as JwtKeys)
|
||||
);
|
||||
await lastValueFrom(service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
));
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['reusable_refresh_token', 'dummy_refresh_token', allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);;
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(3);
|
||||
)
|
||||
);
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['reusable_refresh_token', 'dummy_refresh_token', allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
it('resetBrowserHistory if historyCleanup is turned on and is not in a renewProcess', async () => {
|
||||
@@ -191,13 +194,14 @@ expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(3);
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({ keys: [] } as JwtKeys)
|
||||
);
|
||||
await lastValueFrom(service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
));
|
||||
expect(windowSpy).toHaveBeenCalledTimes(1);
|
||||
)
|
||||
);
|
||||
expect(windowSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('returns callbackContext with jwtkeys filled if everything works fine', async () => {
|
||||
@@ -219,17 +223,18 @@ expect(windowSpy).toHaveBeenCalledTimes(1);
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({ keys: [{ kty: 'henlo' } as JwtKey] } as JwtKeys)
|
||||
);
|
||||
const result = await lastValueFrom(service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
const result = await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
));
|
||||
expect(result).toEqual({
|
||||
isRenewProcess: false,
|
||||
authResult: DUMMY_AUTH_RESULT,
|
||||
jwtKeys: { keys: [{ kty: 'henlo' }] },
|
||||
} as CallbackContext);
|
||||
)
|
||||
);
|
||||
expect(result).toEqual({
|
||||
isRenewProcess: false,
|
||||
authResult: DUMMY_AUTH_RESULT,
|
||||
jwtKeys: { keys: [{ kty: 'henlo' }] },
|
||||
} as CallbackContext);
|
||||
});
|
||||
|
||||
it('returns error if no jwtKeys have been in the call --> keys are null', async () => {
|
||||
@@ -251,19 +256,19 @@ expect(result).toEqual({
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({} as JwtKeys)
|
||||
);
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve signing key with error: Error: Failed to retrieve signing key'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve signing key with error: Error: Failed to retrieve signing key'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('returns error if no jwtKeys have been in the call --> keys throw an error', async () => {
|
||||
@@ -284,19 +289,19 @@ expect(result).toEqual({
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
throwError(() => new Error('error'))
|
||||
);
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve signing key with error: Error: Error: error'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve signing key with error: Error: Error: error'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('returns error if callbackContext.authresult has an error property filled', async () => {
|
||||
@@ -310,19 +315,19 @@ expect(result).toEqual({
|
||||
},
|
||||
];
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toEqual(
|
||||
'AuthCallback AuthResult came with error: someError'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err.message).toEqual(
|
||||
'AuthCallback AuthResult came with error: someError'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('calls resetAuthorizationData, resets nonce and authStateService in case of an error', async () => {
|
||||
@@ -347,25 +352,23 @@ expect(result).toEqual({
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(setNonceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
updateAndPublishAuthStateSpy
|
||||
).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.SecureTokenServerError,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
},
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(setNonceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.SecureTokenServerError,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it('calls authStateService.updateAndPublishAuthState with login required if the error is `login_required`', async () => {
|
||||
@@ -390,25 +393,23 @@ expect(result).toEqual({
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(setNonceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
updateAndPublishAuthStateSpy
|
||||
).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.LoginRequired,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
},
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(setNonceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.LoginRequired,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it('should store jwtKeys', async () => {
|
||||
@@ -434,26 +435,23 @@ expect(result).toEqual({
|
||||
of(DUMMY_JWT_KEYS)
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
next: (callbackContext: CallbackContext) => {
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', DUMMY_JWT_KEYS, allConfigs[0]],
|
||||
]);
|
||||
|
||||
expect(callbackContext.jwtKeys).toEqual(DUMMY_JWT_KEYS);
|
||||
},
|
||||
error: (err) => {
|
||||
expect(err).toBeFalsy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
const callbackContext: CallbackContext = await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', DUMMY_JWT_KEYS, allConfigs[0]],
|
||||
]);
|
||||
expect(callbackContext.jwtKeys).toEqual(DUMMY_JWT_KEYS);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeFalsy();
|
||||
}
|
||||
});
|
||||
|
||||
it('should not store jwtKeys on error', async () => {
|
||||
@@ -480,29 +478,23 @@ expect(result).toEqual({
|
||||
throwError(() => new Error('Error'))
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
next: (callbackContext: CallbackContext) => {
|
||||
expect(callbackContext).toBeFalsy();
|
||||
},
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
|
||||
// storagePersistenceService.write() should not have been called with jwtKeys
|
||||
expect(
|
||||
storagePersistenceServiceSpy
|
||||
).toHaveBeenCalledExactlyOnceWith(
|
||||
'authnResult',
|
||||
authResult,
|
||||
allConfigs[0]
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
const callbackContext: CallbackContext = await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
expect(callbackContext).toBeFalsy();
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'authnResult',
|
||||
authResult,
|
||||
allConfigs[0]
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should fallback to stored jwtKeys on error', async () => {
|
||||
@@ -530,23 +522,22 @@ expect(result).toEqual({
|
||||
throwError(() => new Error('Error'))
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
next: (callbackContext: CallbackContext) => {
|
||||
expect(
|
||||
storagePersistenceServiceSpy
|
||||
).toHaveBeenCalledExactlyOnceWith('jwtKeys', allConfigs[0]);
|
||||
expect(callbackContext.jwtKeys).toEqual(DUMMY_JWT_KEYS);
|
||||
},
|
||||
error: (err) => {
|
||||
expect(err).toBeFalsy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
const callbackContext: CallbackContext = await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'jwtKeys',
|
||||
allConfigs[0]
|
||||
);
|
||||
expect(callbackContext.jwtKeys).toEqual(DUMMY_JWT_KEYS);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeFalsy();
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw error if no jwtKeys are stored', async () => {
|
||||
@@ -568,20 +559,18 @@ expect(result).toEqual({
|
||||
throwError(() => new Error('Error'))
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
next: (callbackContext: CallbackContext) => {
|
||||
expect(callbackContext).toBeFalsy();
|
||||
},
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
const callbackContext: CallbackContext = await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
expect(callbackContext).toBeFalsy();
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -98,10 +98,10 @@ export class HistoryJwtKeysCallbackHandlerService {
|
||||
// fallback: try to load jwtKeys from storage
|
||||
const storedJwtKeys = this.readSigningKeys(config);
|
||||
|
||||
if (!!storedJwtKeys) {
|
||||
if (storedJwtKeys) {
|
||||
this.loggerService.logWarning(
|
||||
config,
|
||||
`Failed to retrieve signing keys, fallback to stored keys`
|
||||
'Failed to retrieve signing keys, fallback to stored keys'
|
||||
);
|
||||
|
||||
return of(storedJwtKeys);
|
||||
@@ -116,7 +116,7 @@ export class HistoryJwtKeysCallbackHandlerService {
|
||||
return of(callbackContext);
|
||||
}
|
||||
|
||||
const errorMessage = `Failed to retrieve signing key`;
|
||||
const errorMessage = 'Failed to retrieve signing key';
|
||||
|
||||
this.loggerService.logWarning(config, errorMessage);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
@@ -57,9 +58,10 @@ describe('ImplicitFlowCallbackHandlerService', () => {
|
||||
},
|
||||
];
|
||||
|
||||
await lastValueFrom(service
|
||||
.implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash'));
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalled();
|
||||
await lastValueFrom(
|
||||
service.implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash')
|
||||
);
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does NOT calls "resetAuthorizationData" if silent renew is running', async () => {
|
||||
@@ -74,9 +76,10 @@ expect(resetAuthorizationDataSpy).toHaveBeenCalled();
|
||||
},
|
||||
];
|
||||
|
||||
await lastValueFrom(service
|
||||
.implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash'));
|
||||
expect(resetAuthorizationDataSpy).not.toHaveBeenCalled();
|
||||
await lastValueFrom(
|
||||
service.implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash')
|
||||
);
|
||||
expect(resetAuthorizationDataSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('returns callbackContext if all params are good', async () => {
|
||||
@@ -99,9 +102,10 @@ expect(resetAuthorizationDataSpy).not.toHaveBeenCalled();
|
||||
},
|
||||
];
|
||||
|
||||
const callbackContext = await lastValueFrom(service
|
||||
.implicitFlowCallback(allConfigs[0]!, allConfigs, 'anyHash'));
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
const callbackContext = await lastValueFrom(
|
||||
service.implicitFlowCallback(allConfigs[0]!, allConfigs, 'anyHash')
|
||||
);
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
});
|
||||
|
||||
it('uses window location hash if no hash is passed', async () => {
|
||||
@@ -124,9 +128,10 @@ expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
},
|
||||
];
|
||||
|
||||
const callbackContext = await lastValueFrom(service
|
||||
.implicitFlowCallback(allConfigs[0]!, allConfigs));
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
const callbackContext = await lastValueFrom(
|
||||
service.implicitFlowCallback(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
@@ -21,9 +22,6 @@ describe('RefreshSessionCallbackHandlerService', () => {
|
||||
mockProvider(FlowsDataService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(RefreshSessionCallbackHandlerService);
|
||||
flowsDataService = TestBed.inject(FlowsDataService);
|
||||
authStateService = TestBed.inject(AuthStateService);
|
||||
@@ -56,9 +54,10 @@ describe('RefreshSessionCallbackHandlerService', () => {
|
||||
existingIdToken: 'henlo-legger',
|
||||
} as CallbackContext;
|
||||
|
||||
const callbackContext = await lastValueFrom(service
|
||||
.refreshSessionWithRefreshTokens({ configId: 'configId1' }));
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
const callbackContext = await lastValueFrom(
|
||||
service.refreshSessionWithRefreshTokens({ configId: 'configId1' })
|
||||
);
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
});
|
||||
|
||||
it('throws error if no refresh token is given', async () => {
|
||||
@@ -69,13 +68,13 @@ expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
vi.spyOn(authStateService, 'getRefreshToken').mockReturnValue('');
|
||||
vi.spyOn(authStateService, 'getIdToken').mockReturnValue('henlo-legger');
|
||||
|
||||
service
|
||||
.refreshSessionWithRefreshTokens({ configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.refreshSessionWithRefreshTokens({ configId: 'configId1' })
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, of, throwError } from 'rxjs';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { TokenValidationService } from '../../validation/token-validation.service';
|
||||
import { CallbackContext } from '../callback-context';
|
||||
import type { CallbackContext } from '../callback-context';
|
||||
import { FlowsDataService } from '../flows-data.service';
|
||||
|
||||
@Injectable()
|
||||
@@ -24,7 +24,7 @@ export class RefreshSessionCallbackHandlerService {
|
||||
|
||||
this.loggerService.logDebug(
|
||||
config,
|
||||
'RefreshSession created. Adding myautostate: ' + stateData
|
||||
`RefreshSession created. Adding myautostate: ${stateData}`
|
||||
);
|
||||
const refreshToken = this.authStateService.getRefreshToken(config);
|
||||
const idToken = this.authStateService.getIdToken(config);
|
||||
@@ -53,12 +53,11 @@ export class RefreshSessionCallbackHandlerService {
|
||||
);
|
||||
|
||||
return of(callbackContext);
|
||||
} else {
|
||||
const errorMessage = 'no refresh token found, please login';
|
||||
|
||||
this.loggerService.logError(config, errorMessage);
|
||||
|
||||
return throwError(() => new Error(errorMessage));
|
||||
}
|
||||
const errorMessage = 'no refresh token found, please login';
|
||||
|
||||
this.loggerService.logError(config, errorMessage);
|
||||
|
||||
return throwError(() => new Error(errorMessage));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { HttpErrorResponse, HttpHeaders } from '@ngify/http';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
@@ -26,9 +26,6 @@ describe('RefreshTokenCallbackHandlerService', () => {
|
||||
mockProvider(StoragePersistenceService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(RefreshTokenCallbackHandlerService);
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
dataService = TestBed.inject(DataService);
|
||||
@@ -48,13 +45,13 @@ describe('RefreshTokenCallbackHandlerService', () => {
|
||||
});
|
||||
|
||||
it('throws error if no tokenEndpoint is given', async () => {
|
||||
(service as any)
|
||||
.refreshTokensRequestTokens({} as CallbackContext)
|
||||
.subscribe({
|
||||
error: (err: unknown) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
(service as any).refreshTokensRequestTokens({} as CallbackContext)
|
||||
);
|
||||
} catch (err: unknown) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('calls data service if all params are good', async () => {
|
||||
@@ -66,21 +63,22 @@ describe('RefreshTokenCallbackHandlerService', () => {
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
await lastValueFrom(service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, {
|
||||
await lastValueFrom(
|
||||
service.refreshTokensRequestTokens({} as CallbackContext, {
|
||||
configId: 'configId1',
|
||||
}));
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'tokenEndpoint',
|
||||
undefined,
|
||||
{ configId: 'configId1' },
|
||||
expect.any(HttpHeaders)
|
||||
);;
|
||||
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();;
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
})
|
||||
);
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'tokenEndpoint',
|
||||
undefined,
|
||||
{ configId: 'configId1' },
|
||||
expect.any(HttpHeaders)
|
||||
);
|
||||
const httpHeaders = postSpy.mock.calls.at(-1)?.[3] as HttpHeaders;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
});
|
||||
|
||||
it('calls data service with correct headers if all params are good', async () => {
|
||||
@@ -92,15 +90,16 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
await lastValueFrom(service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, {
|
||||
await lastValueFrom(
|
||||
service.refreshTokensRequestTokens({} as CallbackContext, {
|
||||
configId: 'configId1',
|
||||
}));
|
||||
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();;
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
})
|
||||
);
|
||||
const httpHeaders = postSpy.mock.calls.at(-1)?.[3] as HttpHeaders;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
});
|
||||
|
||||
it('returns error in case of http error', async () => {
|
||||
@@ -115,13 +114,13 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('retries request in case of no connection http error and succeeds', async () => {
|
||||
@@ -139,18 +138,15 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
.subscribe({
|
||||
next: (res) => {
|
||||
expect(res).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
error: (err) => {
|
||||
// fails if there should be a result
|
||||
expect(err).toBeFalsy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
const res = await lastValueFrom(
|
||||
service.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
);
|
||||
expect(res).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeFalsy();
|
||||
}
|
||||
});
|
||||
|
||||
it('retries request in case of no connection http error and fails because of http error afterwards', async () => {
|
||||
@@ -168,18 +164,15 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
.subscribe({
|
||||
next: (res) => {
|
||||
// fails if there should be a result
|
||||
expect(res).toBeFalsy();
|
||||
},
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
});
|
||||
try {
|
||||
const res = await lastValueFrom(
|
||||
service.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
);
|
||||
expect(res).toBeFalsy();
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, of, throwError, timer } from 'rxjs';
|
||||
import { type Observable, of, throwError, timer } from 'rxjs';
|
||||
import { catchError, mergeMap, retryWhen, switchMap } from 'rxjs/operators';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import { UrlService } from '../../utils/url/url.service';
|
||||
import { AuthResult, CallbackContext } from '../callback-context';
|
||||
import type { AuthResult, CallbackContext } from '../callback-context';
|
||||
import { isNetworkError } from './error-helper';
|
||||
|
||||
@Injectable()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { lastValueFrom, of } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { DOCUMENT } from '../../dom';
|
||||
@@ -42,9 +42,6 @@ describe('StateValidationCallbackHandlerService', () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(StateValidationCallbackHandlerService);
|
||||
stateValidationService = TestBed.inject(StateValidationService);
|
||||
loggerService = TestBed.inject(LoggerService);
|
||||
@@ -69,18 +66,19 @@ describe('StateValidationCallbackHandlerService', () => {
|
||||
);
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
const newCallbackContext = await lastValueFrom(service
|
||||
.callbackStateValidation(
|
||||
const newCallbackContext = await lastValueFrom(
|
||||
service.callbackStateValidation(
|
||||
{} as CallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
));
|
||||
expect(newCallbackContext).toEqual({
|
||||
validationResult: {
|
||||
idToken: 'idTokenJustForTesting',
|
||||
authResponseIsValid: true,
|
||||
},
|
||||
} as CallbackContext);
|
||||
)
|
||||
);
|
||||
expect(newCallbackContext).toEqual({
|
||||
validationResult: {
|
||||
idToken: 'idTokenJustForTesting',
|
||||
authResponseIsValid: true,
|
||||
},
|
||||
} as CallbackContext);
|
||||
});
|
||||
|
||||
it('logs error in case of an error', async () => {
|
||||
@@ -96,20 +94,20 @@ expect(newCallbackContext).toEqual({
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logWarning');
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
service
|
||||
.callbackStateValidation(
|
||||
{} as CallbackContext,
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackStateValidation(
|
||||
{} as CallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch {
|
||||
expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]!,
|
||||
'authorizedCallback, token(s) validation failed, resetting. Hash: &anyFakeHash'
|
||||
);
|
||||
},
|
||||
});
|
||||
'authorizedCallback, token(s) validation failed, resetting. Hash: &anyFakeHash'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('calls resetAuthDataService.resetAuthorizationData and authStateService.updateAndPublishAuthState in case of an error', async () => {
|
||||
@@ -133,24 +131,22 @@ expect(newCallbackContext).toEqual({
|
||||
);
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
service
|
||||
.callbackStateValidation(
|
||||
{ isRenewProcess: true } as CallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
updateAndPublishAuthStateSpy
|
||||
).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.LoginRequired,
|
||||
isRenewProcess: true,
|
||||
});
|
||||
},
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackStateValidation(
|
||||
{ isRenewProcess: true } as CallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.LoginRequired,
|
||||
isRenewProcess: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,21 +43,20 @@ export class StateValidationCallbackHandlerService {
|
||||
);
|
||||
|
||||
return callbackContext;
|
||||
} else {
|
||||
const errorMessage = `authorizedCallback, token(s) validation failed, resetting. Hash: ${this.document.location.hash}`;
|
||||
|
||||
this.loggerService.logWarning(configuration, errorMessage);
|
||||
this.resetAuthDataService.resetAuthorizationData(
|
||||
configuration,
|
||||
allConfigs
|
||||
);
|
||||
this.publishUnauthorizedState(
|
||||
callbackContext.validationResult,
|
||||
callbackContext.isRenewProcess
|
||||
);
|
||||
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
const errorMessage = `authorizedCallback, token(s) validation failed, resetting. Hash: ${this.document.location.hash}`;
|
||||
|
||||
this.loggerService.logWarning(configuration, errorMessage);
|
||||
this.resetAuthDataService.resetAuthorizationData(
|
||||
configuration,
|
||||
allConfigs
|
||||
);
|
||||
this.publishUnauthorizedState(
|
||||
callbackContext.validationResult,
|
||||
callbackContext.isRenewProcess
|
||||
);
|
||||
|
||||
throw new Error(errorMessage);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { lastValueFrom, of } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
@@ -30,9 +30,6 @@ describe('UserCallbackHandlerService', () => {
|
||||
mockProvider(ResetAuthDataService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(UserCallbackHandlerService);
|
||||
flowsDataService = TestBed.inject(FlowsDataService);
|
||||
authStateService = TestBed.inject(AuthStateService);
|
||||
@@ -73,10 +70,11 @@ describe('UserCallbackHandlerService', () => {
|
||||
|
||||
const spy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('mystate', allConfigs[0]);;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('mystate', allConfigs[0]);
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('does NOT call flowsDataService.setSessionState if autoUserInfo is false, isRenewProcess is true and refreshToken is null', async () => {
|
||||
@@ -105,10 +103,11 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
];
|
||||
const spy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(spy).not.toHaveBeenCalled();;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('does NOT call flowsDataService.setSessionState if autoUserInfo is false isRenewProcess is false, refreshToken has value', async () => {
|
||||
@@ -137,10 +136,11 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
];
|
||||
const spy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(spy).not.toHaveBeenCalled();;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('does NOT call flowsDataService.setSessionState if autoUserInfo is false isRenewProcess is false, refreshToken has value, id_token is false', async () => {
|
||||
@@ -165,10 +165,11 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
|
||||
const spy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(spy).not.toHaveBeenCalled();;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is false', async () => {
|
||||
@@ -202,14 +203,15 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: true,
|
||||
validationResult: ValidationResult.NotSet,
|
||||
isRenewProcess: false,
|
||||
});;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: true,
|
||||
validationResult: ValidationResult.NotSet,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('calls userService.getAndPersistUserDataInStore with correct params if autoUserInfo is true', async () => {
|
||||
@@ -242,18 +244,17 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
.spyOn(userService, 'getAndPersistUserDataInStore')
|
||||
.mockReturnValue(of({ user: 'some_data' }));
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(
|
||||
getAndPersistUserDataInStoreSpy
|
||||
).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]!,
|
||||
allConfigs,
|
||||
false,
|
||||
'idtoken',
|
||||
'decoded'
|
||||
);;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(getAndPersistUserDataInStoreSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]!,
|
||||
allConfigs,
|
||||
false,
|
||||
'idtoken',
|
||||
'decoded'
|
||||
);
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is true', async () => {
|
||||
@@ -291,14 +292,15 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: true,
|
||||
validationResult: ValidationResult.MaxOffsetExpired,
|
||||
isRenewProcess: false,
|
||||
});;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: true,
|
||||
validationResult: ValidationResult.MaxOffsetExpired,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('calls flowsDataService.setSessionState with correct params if user data is present and NOT refresh token', async () => {
|
||||
@@ -333,13 +335,14 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
);
|
||||
const setSessionStateSpy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(setSessionStateSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'mystate',
|
||||
allConfigs[0]
|
||||
);;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(setSessionStateSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'mystate',
|
||||
allConfigs[0]
|
||||
);
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('calls authStateService.publishUnauthorizedState with correct params if user info which are coming back are null', async () => {
|
||||
@@ -377,22 +380,20 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
|
||||
service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(
|
||||
updateAndPublishAuthStateSpy
|
||||
).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.MaxOffsetExpired,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve user info with error: Error: Called for userData but they were null'
|
||||
);
|
||||
},
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.MaxOffsetExpired,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve user info with error: Error: Called for userData but they were null'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('calls resetAuthDataService.resetAuthorizationData if user info which are coming back are null', async () => {
|
||||
@@ -430,16 +431,16 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
|
||||
service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve user info with error: Error: Called for userData but they were null'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve user info with error: Error: Called for userData but they were null'
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,6 +35,7 @@ export class UserCallbackHandlerService {
|
||||
if (!autoUserInfo) {
|
||||
if (!isRenewProcess || renewUserInfoAfterTokenRenew) {
|
||||
// userData is set to the id_token decoded, auto get user data set to false
|
||||
// biome-ignore lint/nursery/useCollapsedIf: <explanation>
|
||||
if (validationResult?.decodedIdToken) {
|
||||
this.userService.setUserDataToStore(
|
||||
validationResult.decodedIdToken,
|
||||
@@ -66,7 +67,7 @@ export class UserCallbackHandlerService {
|
||||
)
|
||||
.pipe(
|
||||
switchMap((userData) => {
|
||||
if (!!userData) {
|
||||
if (userData) {
|
||||
if (!refreshToken) {
|
||||
this.flowsDataService.setSessionState(
|
||||
authResult?.session_state,
|
||||
@@ -77,18 +78,17 @@ export class UserCallbackHandlerService {
|
||||
this.publishAuthState(validationResult, isRenewProcess);
|
||||
|
||||
return of(callbackContext);
|
||||
} else {
|
||||
this.resetAuthDataService.resetAuthorizationData(
|
||||
configuration,
|
||||
allConfigs
|
||||
);
|
||||
this.publishUnauthenticatedState(validationResult, isRenewProcess);
|
||||
const errorMessage = `Called for userData but they were ${userData}`;
|
||||
|
||||
this.loggerService.logWarning(configuration, errorMessage);
|
||||
|
||||
return throwError(() => new Error(errorMessage));
|
||||
}
|
||||
this.resetAuthDataService.resetAuthorizationData(
|
||||
configuration,
|
||||
allConfigs
|
||||
);
|
||||
this.publishUnauthenticatedState(validationResult, isRenewProcess);
|
||||
const errorMessage = `Called for userData but they were ${userData}`;
|
||||
|
||||
this.loggerService.logWarning(configuration, errorMessage);
|
||||
|
||||
return throwError(() => new Error(errorMessage));
|
||||
}),
|
||||
catchError((err) => {
|
||||
const errorMessage = `Failed to retrieve user info with error: ${err}`;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
@@ -21,15 +21,13 @@ describe('Flows Data Service', () => {
|
||||
mockProvider(StoragePersistenceService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(FlowsDataService);
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
});
|
||||
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: <explanation>
|
||||
afterEach(() => {
|
||||
jasmine.clock().uninstall();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
@@ -141,10 +139,11 @@ describe('Flows Data Service', () => {
|
||||
|
||||
describe('codeVerifier', () => {
|
||||
it('getCodeVerifier returns value from the store', () => {
|
||||
const spy = vi
|
||||
.spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('codeVerifier', { configId: 'configId1' })
|
||||
.mockReturnValue('Genesis');
|
||||
const spy = mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['codeVerifier', { configId: 'configId1' }],
|
||||
() => 'Genesis'
|
||||
);
|
||||
|
||||
const result = service.getCodeVerifier({ configId: 'configId1' });
|
||||
|
||||
@@ -173,11 +172,12 @@ describe('Flows Data Service', () => {
|
||||
configId: 'configId1',
|
||||
};
|
||||
|
||||
jasmine.clock().uninstall();
|
||||
jasmine.clock().install();
|
||||
vi.useRealTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
const baseTime = new Date();
|
||||
|
||||
jasmine.clock().mockDate(baseTime);
|
||||
vi.setSystemTime(baseTime);
|
||||
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
@@ -212,11 +212,11 @@ describe('Flows Data Service', () => {
|
||||
|
||||
describe('setCodeFlowInProgress', () => {
|
||||
it('set setCodeFlowInProgress to `in progress` when called', () => {
|
||||
jasmine.clock().uninstall();
|
||||
jasmine.clock().install();
|
||||
vi.useRealTimers();
|
||||
vi.useFakeTimers();
|
||||
const baseTime = new Date();
|
||||
|
||||
jasmine.clock().mockDate(baseTime);
|
||||
vi.setSystemTime(baseTime);
|
||||
|
||||
const spy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
@@ -253,23 +253,27 @@ describe('Flows Data Service', () => {
|
||||
configId: 'configId1',
|
||||
};
|
||||
|
||||
jasmine.clock().uninstall();
|
||||
jasmine.clock().install();
|
||||
vi.useRealTimers();
|
||||
vi.useFakeTimers();
|
||||
const baseTime = new Date();
|
||||
|
||||
jasmine.clock().mockDate(baseTime);
|
||||
vi.setSystemTime(baseTime);
|
||||
|
||||
const storageObject = {
|
||||
state: 'running',
|
||||
dateOfLaunchedProcessUtc: baseTime.toISOString(),
|
||||
};
|
||||
|
||||
vi.spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('storageSilentRenewRunning', config)
|
||||
.mockReturnValue(JSON.stringify(storageObject));
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['storageSilentRenewRunning', config],
|
||||
() => JSON.stringify(storageObject)
|
||||
);
|
||||
const spyWrite = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
jasmine.clock().tick((config.silentRenewTimeoutInSeconds + 1) * 1000);
|
||||
vi.advanceTimersByTimeAsync(
|
||||
(config.silentRenewTimeoutInSeconds + 1) * 1000
|
||||
);
|
||||
|
||||
const isSilentRenewRunningResult = service.isSilentRenewRunning(config);
|
||||
|
||||
@@ -287,20 +291,22 @@ describe('Flows Data Service', () => {
|
||||
configId: 'configId1',
|
||||
};
|
||||
|
||||
jasmine.clock().uninstall();
|
||||
jasmine.clock().install();
|
||||
vi.useRealTimers();
|
||||
vi.useFakeTimers();
|
||||
const baseTime = new Date();
|
||||
|
||||
jasmine.clock().mockDate(baseTime);
|
||||
vi.setSystemTime(baseTime);
|
||||
|
||||
const storageObject = {
|
||||
state: 'running',
|
||||
dateOfLaunchedProcessUtc: baseTime.toISOString(),
|
||||
};
|
||||
|
||||
vi.spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('storageSilentRenewRunning', config)
|
||||
.mockReturnValue(JSON.stringify(storageObject));
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['storageSilentRenewRunning', config],
|
||||
() => JSON.stringify(storageObject)
|
||||
);
|
||||
const spyWrite = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
const isSilentRenewRunningResult = service.isSilentRenewRunning(config);
|
||||
@@ -326,11 +332,11 @@ describe('Flows Data Service', () => {
|
||||
|
||||
describe('setSilentRenewRunning', () => {
|
||||
it('set setSilentRenewRunning to `running` with lauched time when called', () => {
|
||||
jasmine.clock().uninstall();
|
||||
jasmine.clock().install();
|
||||
vi.useRealTimers();
|
||||
vi.useFakeTimers();
|
||||
const baseTime = new Date();
|
||||
|
||||
jasmine.clock().mockDate(baseTime);
|
||||
vi.setSystemTime(baseTime);
|
||||
|
||||
const storageObject = {
|
||||
state: 'running',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { lastValueFrom, of } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import type { CallbackContext } from './callback-context';
|
||||
@@ -35,9 +35,6 @@ describe('Flows Service', () => {
|
||||
mockProvider(RefreshTokenCallbackHandlerService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(FlowsService);
|
||||
codeFlowCallbackHandlerService = TestBed.inject(
|
||||
CodeFlowCallbackHandlerService
|
||||
@@ -90,17 +87,22 @@ describe('Flows Service', () => {
|
||||
},
|
||||
];
|
||||
|
||||
const value = await lastValueFrom(service
|
||||
.processCodeFlowCallback('some-url1234', allConfigs[0]!, allConfigs));
|
||||
expect(value).toEqual({} as CallbackContext);;
|
||||
expect(codeFlowCallbackSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'some-url1234',
|
||||
allConfigs[0]
|
||||
);;
|
||||
expect(codeFlowCodeRequestSpy).toHaveBeenCalledTimes(1);;
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalledTimes(1);;
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalledTimes(1);;
|
||||
expect(callbackUserSpy).toHaveBeenCalledTimes(1);
|
||||
const value = await lastValueFrom(
|
||||
service.processCodeFlowCallback(
|
||||
'some-url1234',
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
expect(value).toEqual({} as CallbackContext);
|
||||
expect(codeFlowCallbackSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'some-url1234',
|
||||
allConfigs[0]
|
||||
);
|
||||
expect(codeFlowCodeRequestSpy).toHaveBeenCalledTimes(1);
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalledTimes(1);
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalledTimes(1);
|
||||
expect(callbackUserSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -127,17 +129,18 @@ expect(callbackUserSpy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
];
|
||||
|
||||
const value = await lastValueFrom(service
|
||||
.processSilentRenewCodeFlowCallback(
|
||||
const value = await lastValueFrom(
|
||||
service.processSilentRenewCodeFlowCallback(
|
||||
{} as CallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
));
|
||||
expect(value).toEqual({} as CallbackContext);;
|
||||
expect(codeFlowCodeRequestSpy).toHaveBeenCalled();;
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();;
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();;
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
)
|
||||
);
|
||||
expect(value).toEqual({} as CallbackContext);
|
||||
expect(codeFlowCodeRequestSpy).toHaveBeenCalled();
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -164,13 +167,18 @@ expect(callbackUserSpy).toHaveBeenCalled();
|
||||
},
|
||||
];
|
||||
|
||||
const value = await lastValueFrom(service
|
||||
.processImplicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash'));
|
||||
expect(value).toEqual({} as CallbackContext);;
|
||||
expect(implicitFlowCallbackSpy).toHaveBeenCalled();;
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();;
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();;
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
const value = await lastValueFrom(
|
||||
service.processImplicitFlowCallback(
|
||||
allConfigs[0]!,
|
||||
allConfigs,
|
||||
'any-hash'
|
||||
)
|
||||
);
|
||||
expect(value).toEqual({} as CallbackContext);
|
||||
expect(implicitFlowCallbackSpy).toHaveBeenCalled();
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -203,14 +211,15 @@ expect(callbackUserSpy).toHaveBeenCalled();
|
||||
},
|
||||
];
|
||||
|
||||
const value = await lastValueFrom(service
|
||||
.processRefreshToken(allConfigs[0]!, allConfigs));
|
||||
expect(value).toEqual({} as CallbackContext);;
|
||||
expect(refreshSessionWithRefreshTokensSpy).toHaveBeenCalled();;
|
||||
expect(refreshTokensRequestTokensSpy).toHaveBeenCalled();;
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();;
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();;
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
const value = await lastValueFrom(
|
||||
service.processRefreshToken(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(value).toEqual({} as CallbackContext);
|
||||
expect(refreshSessionWithRefreshTokensSpy).toHaveBeenCalled();
|
||||
expect(refreshTokensRequestTokensSpy).toHaveBeenCalled();
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import { CryptoService } from '../../utils/crypto/crypto.service';
|
||||
@@ -12,9 +11,6 @@ describe('RandomService Tests', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [RandomService, mockProvider(LoggerService), CryptoService],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
randomService = TestBed.inject(RandomService);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { CryptoService } from '../../utils/crypto/crypto.service';
|
||||
|
||||
@@ -37,7 +37,7 @@ export class RandomService {
|
||||
}
|
||||
|
||||
private toHex(dec: number): string {
|
||||
return ('0' + dec.toString(16)).substr(-2);
|
||||
return `0${dec.toString(16)}`.substr(-2);
|
||||
}
|
||||
|
||||
private randomString(length: number): string {
|
||||
|
||||
@@ -23,9 +23,6 @@ describe('ResetAuthDataService', () => {
|
||||
mockProvider(LoggerService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(ResetAuthDataService);
|
||||
userService = TestBed.inject(UserService);
|
||||
flowsDataService = TestBed.inject(FlowsDataService);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { HttpResponse } from '@ngify/http';
|
||||
import { isObservable, of, throwError } from 'rxjs';
|
||||
import { EmptyError, isObservable, lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from '../api/data.service';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
@@ -40,9 +40,6 @@ describe('Signin Key Data Service', () => {
|
||||
mockProvider(StoragePersistenceService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(SigninKeyDataService);
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
dataService = TestBed.inject(DataService);
|
||||
@@ -62,11 +59,11 @@ describe('Signin Key Data Service', () => {
|
||||
);
|
||||
const result = service.getSigningKeys({ configId: 'configId1' });
|
||||
|
||||
result.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(result);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('throws error when no jwksUri given', async () => {
|
||||
@@ -77,11 +74,11 @@ describe('Signin Key Data Service', () => {
|
||||
);
|
||||
const result = service.getSigningKeys({ configId: 'configId1' });
|
||||
|
||||
result.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(result);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('calls dataservice if jwksurl is given', async () => {
|
||||
@@ -94,13 +91,15 @@ describe('Signin Key Data Service', () => {
|
||||
|
||||
const result = service.getSigningKeys({ configId: 'configId1' });
|
||||
|
||||
result.subscribe({
|
||||
complete: () => {
|
||||
try {
|
||||
await lastValueFrom(result);
|
||||
} catch (err: any) {
|
||||
if (err instanceof EmptyError) {
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('someUrl', {
|
||||
configId: 'configId1',
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should retry once', async () => {
|
||||
@@ -116,12 +115,11 @@ describe('Signin Key Data Service', () => {
|
||||
)
|
||||
);
|
||||
|
||||
service.getSigningKeys({ configId: 'configId1' }).subscribe({
|
||||
next: (res) => {
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual(DUMMY_JWKS);
|
||||
},
|
||||
});
|
||||
const res = await lastValueFrom(
|
||||
service.getSigningKeys({ configId: 'configId1' })
|
||||
);
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual(DUMMY_JWKS);
|
||||
});
|
||||
|
||||
it('should retry twice', async () => {
|
||||
@@ -138,12 +136,11 @@ describe('Signin Key Data Service', () => {
|
||||
)
|
||||
);
|
||||
|
||||
service.getSigningKeys({ configId: 'configId1' }).subscribe({
|
||||
next: (res) => {
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual(DUMMY_JWKS);
|
||||
},
|
||||
});
|
||||
const res = await lastValueFrom(
|
||||
service.getSigningKeys({ configId: 'configId1' })
|
||||
);
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual(DUMMY_JWKS);
|
||||
});
|
||||
|
||||
it('should fail after three tries', async () => {
|
||||
@@ -161,16 +158,16 @@ describe('Signin Key Data Service', () => {
|
||||
)
|
||||
);
|
||||
|
||||
service.getSigningKeys({ configId: 'configId1' }).subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(service.getSigningKeys({ configId: 'configId1' }));
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleErrorGetSigningKeys', () => {
|
||||
it('keeps observable if error is catched', async () => {
|
||||
it('keeps observable if error is catched', () => {
|
||||
const result = (service as any).handleErrorGetSigningKeys(
|
||||
new HttpResponse()
|
||||
);
|
||||
@@ -182,52 +179,54 @@ describe('Signin Key Data Service', () => {
|
||||
it('logs error if error is response', async () => {
|
||||
const logSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
(service as any)
|
||||
.handleErrorGetSigningKeys(
|
||||
new HttpResponse({ status: 400, statusText: 'nono' }),
|
||||
{ configId: 'configId1' }
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'400 - nono {}'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
(service as any).handleErrorGetSigningKeys(
|
||||
new HttpResponse({ status: 400, statusText: 'nono' }),
|
||||
{ configId: 'configId1' }
|
||||
)
|
||||
);
|
||||
} catch {
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'400 - nono {}'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('logs error if error is not a response', async () => {
|
||||
const logSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
(service as any)
|
||||
.handleErrorGetSigningKeys('Just some Error', { configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'Just some Error'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
(service as any).handleErrorGetSigningKeys('Just some Error', {
|
||||
configId: 'configId1',
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'Just some Error'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('logs error if error with message property is not a response', async () => {
|
||||
const logSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
(service as any)
|
||||
.handleErrorGetSigningKeys(
|
||||
{ message: 'Just some Error' },
|
||||
{ configId: 'configId1' }
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'Just some Error'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
(service as any).handleErrorGetSigningKeys(
|
||||
{ message: 'Just some Error' },
|
||||
{ configId: 'configId1' }
|
||||
)
|
||||
);
|
||||
} catch {
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'Just some Error'
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { HttpResponse } from '@ngify/http';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { catchError, retry } from 'rxjs/operators';
|
||||
import { DataService } from '../api/data.service';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { JwtKeys } from '../validation/jwtkeys';
|
||||
import type { JwtKeys } from '../validation/jwtkeys';
|
||||
|
||||
@Injectable()
|
||||
export class SigninKeyDataService {
|
||||
@@ -62,7 +62,7 @@ export class SigninKeyDataService {
|
||||
} else {
|
||||
const { message } = errorResponse;
|
||||
|
||||
errMsg = !!message ? message : `${errorResponse}`;
|
||||
errMsg = message ? message : `${errorResponse}`;
|
||||
}
|
||||
this.loggerService.logError(currentConfiguration, errMsg);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user