863 lines
32 KiB
TypeScript
863 lines
32 KiB
TypeScript
import { TestBed } from '@/testing';
|
|
import { lastValueFrom, of } from 'rxjs';
|
|
import { vi } from 'vitest';
|
|
import { JwkExtractor } from '../extractors/jwk.extractor';
|
|
import { LoggerService } from '../logging/logger.service';
|
|
import { mockProvider } from '../testing/mock';
|
|
import { CryptoService } from '../utils/crypto/crypto.service';
|
|
import { TokenHelperService } from '../utils/tokenHelper/token-helper.service';
|
|
import { JwkWindowCryptoService } from './jwk-window-crypto.service';
|
|
import { JwtWindowCryptoService } from './jwt-window-crypto.service';
|
|
import { TokenValidationService } from './token-validation.service';
|
|
|
|
describe('TokenValidationService', () => {
|
|
let tokenValidationService: TokenValidationService;
|
|
let tokenHelperService: TokenHelperService;
|
|
let jwtWindowCryptoService: JwtWindowCryptoService;
|
|
|
|
beforeEach(() => {
|
|
TestBed.configureTestingModule({
|
|
imports: [],
|
|
providers: [
|
|
TokenValidationService,
|
|
mockProvider(LoggerService),
|
|
mockProvider(TokenHelperService),
|
|
JwkExtractor,
|
|
JwkWindowCryptoService,
|
|
JwtWindowCryptoService,
|
|
CryptoService,
|
|
],
|
|
});
|
|
});
|
|
|
|
beforeEach(() => {
|
|
tokenValidationService = TestBed.inject(TokenValidationService);
|
|
tokenHelperService = TestBed.inject(TokenHelperService);
|
|
jwtWindowCryptoService = TestBed.inject(JwtWindowCryptoService);
|
|
});
|
|
|
|
it('should create', () => {
|
|
expect(tokenValidationService).toBeTruthy();
|
|
});
|
|
|
|
describe('validateIdTokenAud', () => {
|
|
it('returns true if aud is string and passed aud matches idToken.aud', () => {
|
|
const dataIdToken = { aud: 'banana' };
|
|
const valueTrue = tokenValidationService.validateIdTokenAud(
|
|
dataIdToken,
|
|
'banana',
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(valueTrue).toEqual(true);
|
|
});
|
|
|
|
it('returns false if aud is string and passed aud does not match idToken.aud', () => {
|
|
const dataIdToken = { aud: 'banana' };
|
|
|
|
const valueFalse = tokenValidationService.validateIdTokenAud(
|
|
dataIdToken,
|
|
'bananammmm',
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(valueFalse).toEqual(false);
|
|
});
|
|
|
|
it('returns true if aud is string array and passed aud is included in the array', () => {
|
|
const dataIdToken = {
|
|
aud: ['banana', 'apple', 'https://nice.dom'],
|
|
};
|
|
|
|
const audValidTrue = tokenValidationService.validateIdTokenAud(
|
|
dataIdToken,
|
|
'apple',
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(audValidTrue).toEqual(true);
|
|
});
|
|
|
|
it('returns false if aud is string array and passed aud is NOT included in the array', () => {
|
|
const dataIdToken = {
|
|
aud: ['banana', 'apple', 'https://nice.dom'],
|
|
};
|
|
|
|
const audValidFalse = tokenValidationService.validateIdTokenAud(
|
|
dataIdToken,
|
|
'https://nice.domunnnnnnkoem',
|
|
{
|
|
configId: 'configId1',
|
|
}
|
|
);
|
|
|
|
expect(audValidFalse).toEqual(false);
|
|
});
|
|
});
|
|
|
|
describe('validateIdTokenNonce', () => {
|
|
it('should validate id token nonce after code grant when match', () => {
|
|
expect(
|
|
tokenValidationService.validateIdTokenNonce(
|
|
{ nonce: 'test1' },
|
|
'test1',
|
|
false,
|
|
{ configId: 'configId1' }
|
|
)
|
|
).toBe(true);
|
|
});
|
|
|
|
it('should not validate id token nonce after code grant when no match', () => {
|
|
expect(
|
|
tokenValidationService.validateIdTokenNonce(
|
|
{ nonce: 'test1' },
|
|
'test2',
|
|
false,
|
|
{ configId: 'configId1' }
|
|
)
|
|
).toBe(false);
|
|
});
|
|
|
|
it('should validate id token nonce after refresh token grant when undefined and no ignore', () => {
|
|
expect(
|
|
tokenValidationService.validateIdTokenNonce(
|
|
{ nonce: undefined },
|
|
TokenValidationService.refreshTokenNoncePlaceholder,
|
|
false,
|
|
{
|
|
configId: 'configId1',
|
|
}
|
|
)
|
|
).toBe(true);
|
|
});
|
|
|
|
it('should validate id token nonce after refresh token grant when undefined and ignore', () => {
|
|
expect(
|
|
tokenValidationService.validateIdTokenNonce(
|
|
{ nonce: undefined },
|
|
TokenValidationService.refreshTokenNoncePlaceholder,
|
|
true,
|
|
{
|
|
configId: 'configId1',
|
|
}
|
|
)
|
|
).toBe(true);
|
|
});
|
|
|
|
it('should validate id token nonce after refresh token grant when defined and ignore', () => {
|
|
expect(
|
|
tokenValidationService.validateIdTokenNonce(
|
|
{ nonce: 'test1' },
|
|
TokenValidationService.refreshTokenNoncePlaceholder,
|
|
true,
|
|
{
|
|
configId: 'configId1',
|
|
}
|
|
)
|
|
).toBe(true);
|
|
});
|
|
|
|
it('should not validate id token nonce after refresh token grant when defined and no ignore', () => {
|
|
expect(
|
|
tokenValidationService.validateIdTokenNonce(
|
|
{ nonce: 'test1' },
|
|
TokenValidationService.refreshTokenNoncePlaceholder,
|
|
false,
|
|
{
|
|
configId: 'configId1',
|
|
}
|
|
)
|
|
).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('validateIdTokenAzpExistsIfMoreThanOneAud', () => {
|
|
it('returns false if aud is array, öength is bigger than 1 and has no azp property', () => {
|
|
const dataIdToken = {
|
|
aud: ['one', 'two'],
|
|
};
|
|
const result =
|
|
tokenValidationService.validateIdTokenAzpExistsIfMoreThanOneAud(
|
|
dataIdToken
|
|
);
|
|
|
|
expect(result).toBe(false);
|
|
});
|
|
|
|
it('returns false if aud is array, ength is bigger than 1 and has no azp property', () => {
|
|
const result =
|
|
tokenValidationService.validateIdTokenAzpExistsIfMoreThanOneAud(null);
|
|
|
|
expect(result).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('validateIdTokenAzpValid', () => {
|
|
it('returns true dataIdToken param is null', () => {
|
|
const result = tokenValidationService.validateIdTokenAzpValid(null, '');
|
|
|
|
expect(result).toBe(true);
|
|
});
|
|
|
|
it('returns false when aud is an array and client id is NOT in the aud array', () => {
|
|
const dataIdToken = {
|
|
aud: [
|
|
'banana',
|
|
'apple',
|
|
'188968487735-b1hh7k87nkkh6vv84548sinju2kpr7gn.apps.googleusercontent.com',
|
|
],
|
|
azp: '188968487735-b1hh7k87nkkh6vv84548sinju2kpr7gn.apps.googleusercontent.com',
|
|
};
|
|
|
|
const azpInvalid = tokenValidationService.validateIdTokenAzpValid(
|
|
dataIdToken,
|
|
'bananammmm'
|
|
);
|
|
|
|
expect(azpInvalid).toEqual(false);
|
|
});
|
|
|
|
it('returns true when aud is an array and client id is in the aud array', () => {
|
|
const dataIdToken = {
|
|
aud: [
|
|
'banana',
|
|
'apple',
|
|
'188968487735-b1hh7k87nkkh6vv84548sinju2kpr7gn.apps.googleusercontent.com',
|
|
],
|
|
azp: '188968487735-b1hh7k87nkkh6vv84548sinju2kpr7gn.apps.googleusercontent.com',
|
|
};
|
|
|
|
const azpValid = tokenValidationService.validateIdTokenAzpValid(
|
|
dataIdToken,
|
|
'188968487735-b1hh7k87nkkh6vv84548sinju2kpr7gn.apps.googleusercontent.com'
|
|
);
|
|
|
|
expect(azpValid).toEqual(true);
|
|
});
|
|
|
|
it('returns true if ID token has no azp property', () => {
|
|
const dataIdToken = {
|
|
noAzpProperty: 'something',
|
|
};
|
|
|
|
const azpValid = tokenValidationService.validateIdTokenAzpValid(
|
|
dataIdToken,
|
|
'bananammmm'
|
|
);
|
|
|
|
expect(azpValid).toEqual(true);
|
|
});
|
|
});
|
|
|
|
describe('validateIdTokenAzpExistsIfMoreThanOneAud', () => {
|
|
it('returns true if aud is array and aud contains azp', () => {
|
|
const dataIdToken = {
|
|
aud: [
|
|
'banana',
|
|
'apple',
|
|
'188968487735-b1hh7k87nkkh6vv84548sinju2kpr7gn.apps.googleusercontent.com',
|
|
],
|
|
azp: '188968487735-b1hh7k87nkkh6vv84548sinju2kpr7gn.apps.googleusercontent.com',
|
|
};
|
|
|
|
const valueTrue =
|
|
tokenValidationService.validateIdTokenAzpExistsIfMoreThanOneAud(
|
|
dataIdToken
|
|
);
|
|
|
|
expect(valueTrue).toEqual(true);
|
|
});
|
|
|
|
it('returns true if aud is array but only has one item', () => {
|
|
const dataIdToken = {
|
|
aud: ['banana'],
|
|
};
|
|
|
|
const valueTrue =
|
|
tokenValidationService.validateIdTokenAzpExistsIfMoreThanOneAud(
|
|
dataIdToken
|
|
);
|
|
|
|
expect(valueTrue).toEqual(true);
|
|
});
|
|
|
|
it('returns true if aud is NOT an array', () => {
|
|
const dataIdToken = {
|
|
aud: 'banana',
|
|
};
|
|
const valueTrue =
|
|
tokenValidationService.validateIdTokenAzpExistsIfMoreThanOneAud(
|
|
dataIdToken
|
|
);
|
|
|
|
expect(valueTrue).toEqual(true);
|
|
});
|
|
});
|
|
|
|
describe('validateRequiredIdToken', () => {
|
|
it('returns false if property iat is missing', () => {
|
|
const decodedIdToken = {
|
|
iss: 'https://damienbod.b2clogin.com/a0958f45-195b-4036-9259-de2f7e594db6/v2.0/',
|
|
sub: 'f836f380-3c64-4802-8dbc-011981c068f5',
|
|
aud: 'bad',
|
|
exp: 1589210086,
|
|
// iat: 1589206486,
|
|
};
|
|
|
|
const result = tokenValidationService.validateRequiredIdToken(
|
|
decodedIdToken,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(result).toEqual(false);
|
|
});
|
|
|
|
it('returns false if property exp is missing', () => {
|
|
const decodedIdToken = {
|
|
iss: 'https://damienbod.b2clogin.com/a0958f45-195b-4036-9259-de2f7e594db6/v2.0/',
|
|
sub: 'f836f380-3c64-4802-8dbc-011981c068f5',
|
|
aud: 'bad',
|
|
// exp: 1589210086,
|
|
iat: 1589206486,
|
|
};
|
|
|
|
const result = tokenValidationService.validateRequiredIdToken(
|
|
decodedIdToken,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(result).toEqual(false);
|
|
});
|
|
|
|
it('returns false if property aud is missing', () => {
|
|
const decodedIdToken = {
|
|
iss: 'https://damienbod.b2clogin.com/a0958f45-195b-4036-9259-de2f7e594db6/v2.0/',
|
|
sub: 'f836f380-3c64-4802-8dbc-011981c068f5',
|
|
// aud: 'bad',
|
|
exp: 1589210086,
|
|
iat: 1589206486,
|
|
};
|
|
|
|
const result = tokenValidationService.validateRequiredIdToken(
|
|
decodedIdToken,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(result).toEqual(false);
|
|
});
|
|
|
|
it('returns false if property sub is missing', () => {
|
|
const decodedIdToken = {
|
|
iss: 'https://damienbod.b2clogin.com/a0958f45-195b-4036-9259-de2f7e594db6/v2.0/',
|
|
// sub: 'f836f380-3c64-4802-8dbc-011981c068f5',
|
|
aud: 'bad',
|
|
exp: 1589210086,
|
|
iat: 1589206486,
|
|
};
|
|
|
|
const result = tokenValidationService.validateRequiredIdToken(
|
|
decodedIdToken,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(result).toEqual(false);
|
|
});
|
|
|
|
it('returns false if property iss is missing', () => {
|
|
const decodedIdToken = {
|
|
// iss: 'https://damienbod.b2clogin.com/a0958f45-195b-4036-9259-de2f7e594db6/v2.0/',
|
|
sub: 'f836f380-3c64-4802-8dbc-011981c068f5',
|
|
aud: 'bad',
|
|
exp: 1589210086,
|
|
iat: 1589206486,
|
|
};
|
|
|
|
const result = tokenValidationService.validateRequiredIdToken(
|
|
decodedIdToken,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(result).toEqual(false);
|
|
});
|
|
|
|
it('returns true if all is valid', () => {
|
|
const decodedIdToken = {
|
|
iss: 'https://damienbod.b2clogin.com/a0958f45-195b-4036-9259-de2f7e594db6/v2.0/',
|
|
sub: 'f836f380-3c64-4802-8dbc-011981c068f5',
|
|
aud: 'bad',
|
|
exp: 1589210086,
|
|
iat: 1589206486,
|
|
};
|
|
|
|
const result = tokenValidationService.validateRequiredIdToken(
|
|
decodedIdToken,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(result).toEqual(true);
|
|
});
|
|
});
|
|
|
|
describe('validateIdTokenIss', () => {
|
|
it('returns true if issuer matches iss in idToken', () => {
|
|
const decodedIdToken = {
|
|
iss: 'xc',
|
|
};
|
|
|
|
const valueTrue = tokenValidationService.validateIdTokenIss(
|
|
decodedIdToken,
|
|
'xc',
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(valueTrue).toEqual(true);
|
|
});
|
|
|
|
it('returns false if issuer does not match iss in idToken', () => {
|
|
const decodedIdToken = {
|
|
iss: 'xc',
|
|
};
|
|
|
|
const valueFalse = tokenValidationService.validateIdTokenIss(
|
|
decodedIdToken,
|
|
'xcjjjj',
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(valueFalse).toEqual(false);
|
|
});
|
|
});
|
|
|
|
describe('validateIdTokenIatMaxOffset', () => {
|
|
it('returns true if validationIsDisabled', () => {
|
|
const result = tokenValidationService.validateIdTokenIatMaxOffset(
|
|
null,
|
|
0,
|
|
true,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(result).toBe(true);
|
|
});
|
|
|
|
it('returns false if dataIdToken has no property "iat"', () => {
|
|
const dataIdToken = {
|
|
notIat: 'test',
|
|
};
|
|
const result = tokenValidationService.validateIdTokenIatMaxOffset(
|
|
dataIdToken,
|
|
0,
|
|
false,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(result).toBe(false);
|
|
});
|
|
|
|
it('returns true if time is Mon Jan 19 1970 10:26:46 GMT+0100, and the offset is big like 500000000000 seconds', () => {
|
|
const decodedIdToken = {
|
|
iat: 1589206486, // Mon Jan 19 1970 10:26:46 GMT+0100 (Central European Standard Time)
|
|
};
|
|
|
|
const valueTrue = tokenValidationService.validateIdTokenIatMaxOffset(
|
|
decodedIdToken,
|
|
500000000000,
|
|
false,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(valueTrue).toEqual(true);
|
|
});
|
|
|
|
it('returns false if time is Sat Nov 09 1985 02:47:57 GMT+0100, and the offset is 0 seconds', () => {
|
|
const decodedIdTokenNegIat = {
|
|
iat: 500348877430, // Sat Nov 09 1985 02:47:57 GMT+0100 (Central European Standard Time)
|
|
};
|
|
const valueFalseNeg = tokenValidationService.validateIdTokenIatMaxOffset(
|
|
decodedIdTokenNegIat,
|
|
0,
|
|
false,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(valueFalseNeg).toEqual(false);
|
|
});
|
|
|
|
it('returns true if time is Mon Jan 19 1970 10:26:46 GMT+0100, and the offset is small like 5 seconds', () => {
|
|
const decodedIdToken = {
|
|
iat: 1589206486, // Mon Jan 19 1970 10:26:46 GMT+0100 (Central European Standard Time)
|
|
};
|
|
const valueFalse = tokenValidationService.validateIdTokenIatMaxOffset(
|
|
decodedIdToken,
|
|
5,
|
|
false,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(valueFalse).toEqual(false);
|
|
});
|
|
});
|
|
|
|
describe('validateSignatureIdToken', () => {
|
|
it('returns false if no kwtKeys are passed', async () => {
|
|
const valueFalse$ = tokenValidationService.validateSignatureIdToken(
|
|
'some-id-token',
|
|
null,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
valueFalse$.subscribe((valueFalse) => {
|
|
expect(valueFalse).toEqual(false);
|
|
});
|
|
});
|
|
|
|
it('returns true if no idToken is passed', async () => {
|
|
const valueFalse$ = tokenValidationService.validateSignatureIdToken(
|
|
null as any,
|
|
'some-jwt-keys',
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
valueFalse$.subscribe((valueFalse) => {
|
|
expect(valueFalse).toEqual(true);
|
|
});
|
|
});
|
|
|
|
it('returns false if jwtkeys has no keys-property', async () => {
|
|
const valueFalse$ = tokenValidationService.validateSignatureIdToken(
|
|
'some-id-token',
|
|
{ notKeys: '' },
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
valueFalse$.subscribe((valueFalse) => {
|
|
expect(valueFalse).toEqual(false);
|
|
});
|
|
});
|
|
|
|
it('returns false if header data has no header data', async () => {
|
|
vi.spyOn(tokenHelperService, 'getHeaderFromToken').mockReturnValue({});
|
|
|
|
const jwtKeys = {
|
|
keys: 'someThing',
|
|
};
|
|
|
|
const valueFalse$ = tokenValidationService.validateSignatureIdToken(
|
|
'some-id-token',
|
|
jwtKeys,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
valueFalse$.subscribe((valueFalse) => {
|
|
expect(valueFalse).toEqual(false);
|
|
});
|
|
});
|
|
|
|
it('returns false if header data alg property does not exist in keyalgorithms', async () => {
|
|
vi.spyOn(tokenHelperService, 'getHeaderFromToken').mockReturnValue({
|
|
alg: 'NOT SUPPORTED ALG',
|
|
});
|
|
|
|
const jwtKeys = {
|
|
keys: 'someThing',
|
|
};
|
|
|
|
const valueFalse$ = tokenValidationService.validateSignatureIdToken(
|
|
'some-id-token',
|
|
jwtKeys,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
valueFalse$.subscribe((valueFalse) => {
|
|
expect(valueFalse).toEqual(false);
|
|
});
|
|
});
|
|
|
|
it('returns false if header data has kid property and jwtKeys has same kid property but they are not valid with the token', (done) => {
|
|
const kid = '5626CE6A8F4F5FCD79C6642345282CA76D337548';
|
|
|
|
vi.spyOn(tokenHelperService, 'getHeaderFromToken').mockReturnValue({
|
|
alg: 'RS256',
|
|
kid,
|
|
});
|
|
vi.spyOn(tokenHelperService, 'getSignatureFromToken').mockReturnValue('');
|
|
|
|
const jwtKeys = {
|
|
keys: [
|
|
{
|
|
kty: 'RSA',
|
|
use: 'sig',
|
|
kid,
|
|
x5t: 'VibOao9PX815xmQjRSgsp20zdUg',
|
|
e: 'AQAB',
|
|
n: 'uu3-HK4pLRHJHoEBzFhM516RWx6nybG5yQjH4NbKjfGQ8dtKy1BcGjqfMaEKF8KOK44NbAx7rtBKCO9EKNYkeFvcUzBzVeuu4jWG61XYdTekgv-Dh_Fj8245GocEkbvBbFW6cw-_N59JWqUuiCvb-EOfhcuubUcr44a0AQyNccYNpcXGRcMKy7_L1YhO0AMULqLDDVLFj5glh4TcJ2N5VnJedq1-_JKOxPqD1ni26UOQoWrW16G29KZ1_4Xxf2jX8TAq-4RJEHccdzgZVIO4F5B4MucMZGq8_jMCpiTUsUGDOAMA_AmjxIRHOtO5n6Pt0wofrKoAVhGh2sCTtaQf2Q',
|
|
x5c: [
|
|
'MIIDPzCCAiegAwIBAgIQF+HRVxLHII9IlOoQk6BxcjANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDDBBzdHMuZGV2LmNlcnQuY29tMB4XDTE5MDIyMDEwMTA0M1oXDTM5MDIyMDEwMTkyOVowGzEZMBcGA1UEAwwQc3RzLmRldi5jZXJ0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALrt/hyuKS0RyR6BAcxYTOdekVsep8mxuckIx+DWyo3xkPHbSstQXBo6nzGhChfCjiuODWwMe67QSgjvRCjWJHhb3FMwc1XrruI1hutV2HU3pIL/g4fxY/NuORqHBJG7wWxVunMPvzefSVqlLogr2/hDn4XLrm1HK+OGtAEMjXHGDaXFxkXDCsu/y9WITtADFC6iww1SxY+YJYeE3CdjeVZyXnatfvySjsT6g9Z4tulDkKFq1tehtvSmdf+F8X9o1/EwKvuESRB3HHc4GVSDuBeQeDLnDGRqvP4zAqYk1LFBgzgDAPwJo8SERzrTuZ+j7dMKH6yqAFYRodrAk7WkH9kCAwEAAaN/MH0wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAtBgNVHREEJjAkghBzdHMuZGV2LmNlcnQuY29tghBzdHMuZGV2LmNlcnQuY29tMB0GA1UdDgQWBBQuyHxWP3je6jGMOmOiY+hz47r36jANBgkqhkiG9w0BAQsFAAOCAQEAKEHG7Ga6nb2XiHXDc69KsIJwbO80+LE8HVJojvITILz3juN6/FmK0HmogjU6cYST7m1MyxsVhQQNwJASZ6haBNuBbNzBXfyyfb4kr62t1oDLNwhctHaHaM4sJSf/xIw+YO+Qf7BtfRAVsbM05+QXIi2LycGrzELiXu7KFM0E1+T8UOZ2Qyv7OlCb/pWkYuDgE4w97ox0MhDpvgluxZLpRanOLUCVGrfFaij7gRAhjYPUY3vAEcD8JcFBz1XijU8ozRO6FaG4qg8/JCe+VgoWsMDj3sKB9g0ob6KCyG9L2bdk99PGgvXDQvMYCpkpZzG3XsxOINPd5p0gc209ZOoxTg==',
|
|
],
|
|
alg: 'RS256',
|
|
},
|
|
],
|
|
};
|
|
|
|
const valueFalse$ = tokenValidationService.validateSignatureIdToken(
|
|
'someNOTMATCHINGIdToken',
|
|
jwtKeys,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
valueFalse$.subscribe((valueFalse) => {
|
|
expect(valueFalse).toEqual(false);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should return true if valid input is provided', (done) => {
|
|
const idToken =
|
|
'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwic3ViIjoiMTIzNDU2IiwiYXVkIjoibXlfY2xpZW50X2lkIiwiZXhwIjoxMzExMjgxOTcwLCJpYXQiOjEzMTEyODA5NzAsIm5hbWUiOiJKYW5lIERvZSIsImdpdmVuX25hbWUiOiJKYW5lIiwiZmFtaWx5X25hbWUiOiJEb2UiLCJiaXJ0aGRhdGUiOiIxOTkwLTEwLTMxIiwiZW1haWwiOiJqYW5lZG9lQGV4YW1wbGUuY29tIiwicGljdHVyZSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vamFuZWRvZS9tZS5qcGcifQ.SY0ilps7yKYmYCc41zNOatfmAFhOtDYwuIT80qrHMl_4FEO2WFWSv-aDl4QfTSKY9A6MMP6xy0Z_8Kk7NeRwIV7FVScMLnPvVzs9pxza0e_rl6hmZLb5P5n4AEINwn46X9XmRB5W3EZO_x2LG65_g3NZFiPrzOC1Fs_6taJl7TfI8lOveYDoJyXCWYQMS3Oh5MM9S8W-Hc29_qJLH-kixm1S01qoICRPDGMRwhtAu1DHjwWQp9Ycfz6g3uyb7N1imBvI49t1CwWy02_mQ3g-7e7bOP1Ax2kgrwnJgsVBDULnyCZG9PE8T0CHZl_fErZtvbJJ0jdoZ1fyr48906am2w';
|
|
const idTokenParts = idToken.split('.');
|
|
const key = {
|
|
kty: 'RSA',
|
|
n: 'u1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0_IzW7yWR7QkrmBL7jTKEn5u-qKhbwKfBstIs-bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW_VDL5AaWTg0nLVkjRo9z-40RQzuVaE8AkAFmxZzow3x-VJYKdjykkJ0iT9wCS0DRTXu269V264Vf_3jvredZiKRkgwlL9xNAwxXFg0x_XFw005UWVRIkdgcKWTjpBP2dPwVZ4WWC-9aGVd-Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbcmw',
|
|
e: 'AQAB',
|
|
alg: 'RS256',
|
|
kid: 'boop',
|
|
use: 'sig',
|
|
};
|
|
const jwtKeys = {
|
|
keys: [key],
|
|
};
|
|
|
|
vi.spyOn(tokenHelperService, 'getHeaderFromToken').mockReturnValue({
|
|
alg: 'RS256',
|
|
typ: 'JWT',
|
|
});
|
|
vi.spyOn(tokenHelperService, 'getSigningInputFromToken').mockReturnValue(
|
|
[idTokenParts[0], idTokenParts[1]].join('.')
|
|
);
|
|
vi.spyOn(tokenHelperService, 'getSignatureFromToken').mockReturnValue(
|
|
idTokenParts[2]
|
|
);
|
|
|
|
const valueTrue$ = tokenValidationService.validateSignatureIdToken(
|
|
idToken,
|
|
jwtKeys,
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
valueTrue$.subscribe((valueTrue) => {
|
|
expect(valueTrue).toEqual(true);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('validateIdTokenAtHash', () => {
|
|
it('returns true if sha is sha256 and generated hash equals atHash param', (done) => {
|
|
const accessToken = 'iGU3DhbPoDljiYtr0oepxi7zpT8BsjdU7aaXcdq-DPk';
|
|
const atHash = '-ODC_7Go_UIUTC8nP4k2cA';
|
|
|
|
const result$ = tokenValidationService.validateIdTokenAtHash(
|
|
accessToken,
|
|
atHash,
|
|
'256',
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
result$.subscribe((result) => {
|
|
expect(result).toEqual(true);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('returns false if sha is sha256 and generated hash does not equal atHash param', async () => {
|
|
const accessToken =
|
|
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1ODkyMTAwODYsIm5iZiI6MTU4OTIwNjQ4NiwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9kYW1pZW5ib2QuYjJjbG9naW4uY29tL2EwOTU4ZjQ1LTE5NWItNDAzNi05MjU5LWRlMmY3ZTU5NGRiNi92Mi4wLyIsInN1YiI6ImY4MzZmMzgwLTNjNjQtNDgwMi04ZGJjLTAxMTk4MWMwNjhmNSIsImF1ZCI6ImYxOTM0YTZlLTk1OGQtNDE5OC05ZjM2LTYxMjdjZmM0Y2RiMyIsIm5vbmNlIjoiMDA3YzQxNTNiNmEwNTE3YzBlNDk3NDc2ZmIyNDk5NDhlYzVjbE92UVEiLCJpYXQiOjE1ODkyMDY0ODYsImF1dGhfdGltZSI6MTU4OTIwNjQ4NiwibmFtZSI6ImRhbWllbmJvZCIsImVtYWlscyI6WyJkYW1pZW5AZGFtaWVuYm9kLm9ubWljcm9zb2Z0LmNvbSJdLCJ0ZnAiOiJCMkNfMV9iMmNwb2xpY3lkYW1pZW4iLCJhdF9oYXNoIjoiWmswZktKU19wWWhPcE04SUJhMTJmdyJ9.E5Z-0kOzNU7LBkeVHHMyNoER8TUapGzUUfXmW6gVu4v6QMM5fQ4sJ7KC8PHh8lBFYiCnaDiTtpn3QytUwjXEFnLDAX5qcZT1aPoEgL_OmZMC-8y-4GyHp35l7VFD4iNYM9fJmLE8SYHTVl7eWPlXSyz37Ip0ciiV0Fd6eoksD_aVc-hkIqngDfE4fR8ZKfv4yLTNN_SfknFfuJbZ56yN-zIBL4GkuHsbQCBYpjtWQ62v98p1jO7NhHKV5JP2ec_Ge6oYc_bKTrE6OIX38RJ2rIm7zU16mtdjnl_350Nw3ytHcTPnA1VpP_VLElCfe83jr5aDHc_UQRYaAcWlOgvmVg';
|
|
const atHash = 'bad';
|
|
|
|
const result = await lastValueFrom(
|
|
tokenValidationService.validateIdTokenAtHash(
|
|
accessToken,
|
|
atHash,
|
|
'256',
|
|
{ configId: 'configId1' }
|
|
)
|
|
);
|
|
|
|
expect(result).toEqual(false);
|
|
});
|
|
|
|
it('returns true if sha is sha256 and generated hash does equal atHash param', (done) => {
|
|
const accessToken =
|
|
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1ODkyMTAwODYsIm5iZiI6MTU4OTIwNjQ4NiwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9kYW1pZW5ib2QuYjJjbG9naW4uY29tL2EwOTU4ZjQ1LTE5NWItNDAzNi05MjU5LWRlMmY3ZTU5NGRiNi92Mi4wLyIsInN1YiI6ImY4MzZmMzgwLTNjNjQtNDgwMi04ZGJjLTAxMTk4MWMwNjhmNSIsImF1ZCI6ImYxOTM0YTZlLTk1OGQtNDE5OC05ZjM2LTYxMjdjZmM0Y2RiMyIsIm5vbmNlIjoiMDA3YzQxNTNiNmEwNTE3YzBlNDk3NDc2ZmIyNDk5NDhlYzVjbE92UVEiLCJpYXQiOjE1ODkyMDY0ODYsImF1dGhfdGltZSI6MTU4OTIwNjQ4NiwibmFtZSI6ImRhbWllbmJvZCIsImVtYWlscyI6WyJkYW1pZW5AZGFtaWVuYm9kLm9ubWljcm9zb2Z0LmNvbSJdLCJ0ZnAiOiJCMkNfMV9iMmNwb2xpY3lkYW1pZW4iLCJhdF9oYXNoIjoiWmswZktKU19wWWhPcE04SUJhMTJmdyJ9.E5Z-0kOzNU7LBkeVHHMyNoER8TUapGzUUfXmW6gVu4v6QMM5fQ4sJ7KC8PHh8lBFYiCnaDiTtpn3QytUwjXEFnLDAX5qcZT1aPoEgL_OmZMC-8y-4GyHp35l7VFD4iNYM9fJmLE8SYHTVl7eWPlXSyz37Ip0ciiV0Fd6eoksD_aVc-hkIqngDfE4fR8ZKfv4yLTNN_SfknFfuJbZ56yN-zIBL4GkuHsbQCBYpjtWQ62v98p1jO7NhHKV5JP2ec_Ge6oYc_bKTrE6OIX38RJ2rIm7zU16mtdjnl_350Nw3ytHcTPnA1VpP_VLElCfe83jr5aDHc_UQRYaAcWlOgvmVg';
|
|
const atHash = 'good';
|
|
|
|
vi.spyOn(jwtWindowCryptoService, 'generateAtHash').mockReturnValues(
|
|
of('notEqualsGood'),
|
|
of('good')
|
|
);
|
|
|
|
const result$ = tokenValidationService.validateIdTokenAtHash(
|
|
accessToken,
|
|
atHash,
|
|
'256',
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
result$.subscribe((result) => {
|
|
expect(result).toEqual(true);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('returns false if sha is sha384 and generated hash does not equal atHash param', (done) => {
|
|
const accessToken =
|
|
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1ODkyMTAwODYsIm5iZiI6MTU4OTIwNjQ4NiwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9kYW1pZW5ib2QuYjJjbG9naW4uY29tL2EwOTU4ZjQ1LTE5NWItNDAzNi05MjU5LWRlMmY3ZTU5NGRiNi92Mi4wLyIsInN1YiI6ImY4MzZmMzgwLTNjNjQtNDgwMi04ZGJjLTAxMTk4MWMwNjhmNSIsImF1ZCI6ImYxOTM0YTZlLTk1OGQtNDE5OC05ZjM2LTYxMjdjZmM0Y2RiMyIsIm5vbmNlIjoiMDA3YzQxNTNiNmEwNTE3YzBlNDk3NDc2ZmIyNDk5NDhlYzVjbE92UVEiLCJpYXQiOjE1ODkyMDY0ODYsImF1dGhfdGltZSI6MTU4OTIwNjQ4NiwibmFtZSI6ImRhbWllbmJvZCIsImVtYWlscyI6WyJkYW1pZW5AZGFtaWVuYm9kLm9ubWljcm9zb2Z0LmNvbSJdLCJ0ZnAiOiJCMkNfMV9iMmNwb2xpY3lkYW1pZW4iLCJhdF9oYXNoIjoiWmswZktKU19wWWhPcE04SUJhMTJmdyJ9.E5Z-0kOzNU7LBkeVHHMyNoER8TUapGzUUfXmW6gVu4v6QMM5fQ4sJ7KC8PHh8lBFYiCnaDiTtpn3QytUwjXEFnLDAX5qcZT1aPoEgL_OmZMC-8y-4GyHp35l7VFD4iNYM9fJmLE8SYHTVl7eWPlXSyz37Ip0ciiV0Fd6eoksD_aVc-hkIqngDfE4fR8ZKfv4yLTNN_SfknFfuJbZ56yN-zIBL4GkuHsbQCBYpjtWQ62v98p1jO7NhHKV5JP2ec_Ge6oYc_bKTrE6OIX38RJ2rIm7zU16mtdjnl_350Nw3ytHcTPnA1VpP_VLElCfe83jr5aDHc_UQRYaAcWlOgvmVg';
|
|
const atHash = 'bad';
|
|
|
|
const result$ = tokenValidationService.validateIdTokenAtHash(
|
|
accessToken,
|
|
atHash,
|
|
'384',
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
result$.subscribe((result) => {
|
|
expect(result).toEqual(false);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('returns false if sha is sha512 and generated hash does not equal atHash param', (done) => {
|
|
const accessToken =
|
|
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1ODkyMTAwODYsIm5iZiI6MTU4OTIwNjQ4NiwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9kYW1pZW5ib2QuYjJjbG9naW4uY29tL2EwOTU4ZjQ1LTE5NWItNDAzNi05MjU5LWRlMmY3ZTU5NGRiNi92Mi4wLyIsInN1YiI6ImY4MzZmMzgwLTNjNjQtNDgwMi04ZGJjLTAxMTk4MWMwNjhmNSIsImF1ZCI6ImYxOTM0YTZlLTk1OGQtNDE5OC05ZjM2LTYxMjdjZmM0Y2RiMyIsIm5vbmNlIjoiMDA3YzQxNTNiNmEwNTE3YzBlNDk3NDc2ZmIyNDk5NDhlYzVjbE92UVEiLCJpYXQiOjE1ODkyMDY0ODYsImF1dGhfdGltZSI6MTU4OTIwNjQ4NiwibmFtZSI6ImRhbWllbmJvZCIsImVtYWlscyI6WyJkYW1pZW5AZGFtaWVuYm9kLm9ubWljcm9zb2Z0LmNvbSJdLCJ0ZnAiOiJCMkNfMV9iMmNwb2xpY3lkYW1pZW4iLCJhdF9oYXNoIjoiWmswZktKU19wWWhPcE04SUJhMTJmdyJ9.E5Z-0kOzNU7LBkeVHHMyNoER8TUapGzUUfXmW6gVu4v6QMM5fQ4sJ7KC8PHh8lBFYiCnaDiTtpn3QytUwjXEFnLDAX5qcZT1aPoEgL_OmZMC-8y-4GyHp35l7VFD4iNYM9fJmLE8SYHTVl7eWPlXSyz37Ip0ciiV0Fd6eoksD_aVc-hkIqngDfE4fR8ZKfv4yLTNN_SfknFfuJbZ56yN-zIBL4GkuHsbQCBYpjtWQ62v98p1jO7NhHKV5JP2ec_Ge6oYc_bKTrE6OIX38RJ2rIm7zU16mtdjnl_350Nw3ytHcTPnA1VpP_VLElCfe83jr5aDHc_UQRYaAcWlOgvmVg';
|
|
const atHash = 'bad';
|
|
|
|
const result$ = tokenValidationService.validateIdTokenAtHash(
|
|
accessToken,
|
|
atHash,
|
|
'512',
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
result$.subscribe((result) => {
|
|
expect(result).toEqual(false);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('validateStateFromHashCallback', () => {
|
|
it('returns true when state and localstate match', () => {
|
|
const result = tokenValidationService.validateStateFromHashCallback(
|
|
'sssd',
|
|
'sssd',
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(result).toEqual(true);
|
|
});
|
|
|
|
it('returns false when state and local state do not match', () => {
|
|
const result = tokenValidationService.validateStateFromHashCallback(
|
|
'sssd',
|
|
'bad',
|
|
{ configId: 'configId1' }
|
|
);
|
|
|
|
expect(result).toEqual(false);
|
|
});
|
|
});
|
|
|
|
describe('validateIdTokenExpNotExpired', () => {
|
|
it('returns false when getTokenExpirationDate returns null', () => {
|
|
vi.spyOn(tokenHelperService, 'getTokenExpirationDate').mockReturnValue(
|
|
null as unknown as Date
|
|
);
|
|
const notExpired = tokenValidationService.validateIdTokenExpNotExpired(
|
|
'idToken',
|
|
{ configId: 'configId1' },
|
|
0
|
|
);
|
|
|
|
expect(notExpired).toEqual(false);
|
|
});
|
|
|
|
it('returns false if token is not expired', () => {
|
|
const idToken =
|
|
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1ODkyMTAwODYsIm5iZiI6MTU4OTIwNjQ4NiwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9kYW1pZW5ib2QuYjJjbG9naW4uY29tL2EwOTU4ZjQ1LTE5NWItNDAzNi05MjU5LWRlMmY3ZTU5NGRiNi92Mi4wLyIsInN1YiI6ImY4MzZmMzgwLTNjNjQtNDgwMi04ZGJjLTAxMTk4MWMwNjhmNSIsImF1ZCI6ImYxOTM0YTZlLTk1OGQtNDE5OC05ZjM2LTYxMjdjZmM0Y2RiMyIsIm5vbmNlIjoiMDA3YzQxNTNiNmEwNTE3YzBlNDk3NDc2ZmIyNDk5NDhlYzVjbE92UVEiLCJpYXQiOjE1ODkyMDY0ODYsImF1dGhfdGltZSI6MTU4OTIwNjQ4NiwibmFtZSI6ImRhbWllbmJvZCIsImVtYWlscyI6WyJkYW1pZW5AZGFtaWVuYm9kLm9ubWljcm9zb2Z0LmNvbSJdLCJ0ZnAiOiJCMkNfMV9iMmNwb2xpY3lkYW1pZW4iLCJhdF9oYXNoIjoiWmswZktKU19wWWhPcE04SUJhMTJmdyJ9.E5Z-0kOzNU7LBkeVHHMyNoER8TUapGzUUfXmW6gVu4v6QMM5fQ4sJ7KC8PHh8lBFYiCnaDiTtpn3QytUwjXEFnLDAX5qcZT1aPoEgL_OmZMC-8y-4GyHp35l7VFD4iNYM9fJmLE8SYHTVl7eWPlXSyz37Ip0ciiV0Fd6eoksD_aVc-hkIqngDfE4fR8ZKfv4yLTNN_SfknFfuJbZ56yN-zIBL4GkuHsbQCBYpjtWQ62v98p1jO7NhHKV5JP2ec_Ge6oYc_bKTrE6OIX38RJ2rIm7zU16mtdjnl_350Nw3ytHcTPnA1VpP_VLElCfe83jr5aDHc_UQRYaAcWlOgvmVg';
|
|
|
|
const notExpired = tokenValidationService.validateIdTokenExpNotExpired(
|
|
idToken,
|
|
{ configId: 'configId1' },
|
|
0
|
|
);
|
|
|
|
expect(notExpired).toEqual(false);
|
|
});
|
|
});
|
|
|
|
describe('validateAccessTokenNotExpired', () => {
|
|
const testCases = [
|
|
{
|
|
// Mon Jan 19 1970 10:26:50 GMT+0100,
|
|
date: new Date(1589210086),
|
|
offsetSeconds: 0,
|
|
expectedResult: false,
|
|
},
|
|
{
|
|
// Sun Nov 01 2550 00:00:00 GMT+0100
|
|
date: new Date(2550, 10),
|
|
offsetSeconds: 0,
|
|
expectedResult: true,
|
|
},
|
|
{
|
|
date: null,
|
|
offsetSeconds: 300,
|
|
expectedResult: true,
|
|
},
|
|
];
|
|
|
|
testCases.forEach(({ date, offsetSeconds, expectedResult }) => {
|
|
it(`returns ${expectedResult} if ${date} is given with an offset of ${offsetSeconds}`, () => {
|
|
const notExpired = tokenValidationService.validateAccessTokenNotExpired(
|
|
date as Date,
|
|
{ configId: 'configId1' },
|
|
offsetSeconds
|
|
);
|
|
|
|
expect(notExpired).toEqual(expectedResult);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('hasIdTokenExpired', () => {
|
|
it('returns true if token has expired', () => {
|
|
const idToken =
|
|
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1ODkyMTAwODYsIm5iZiI6MTU4OTIwNjQ4NiwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9kYW1pZW5ib2QuYjJjbG9naW4uY29tL2EwOTU4ZjQ1LTE5NWItNDAzNi05MjU5LWRlMmY3ZTU5NGRiNi92Mi4wLyIsInN1YiI6ImY4MzZmMzgwLTNjNjQtNDgwMi04ZGJjLTAxMTk4MWMwNjhmNSIsImF1ZCI6ImYxOTM0YTZlLTk1OGQtNDE5OC05ZjM2LTYxMjdjZmM0Y2RiMyIsIm5vbmNlIjoiMDA3YzQxNTNiNmEwNTE3YzBlNDk3NDc2ZmIyNDk5NDhlYzVjbE92UVEiLCJpYXQiOjE1ODkyMDY0ODYsImF1dGhfdGltZSI6MTU4OTIwNjQ4NiwibmFtZSI6ImRhbWllbmJvZCIsImVtYWlscyI6WyJkYW1pZW5AZGFtaWVuYm9kLm9ubWljcm9zb2Z0LmNvbSJdLCJ0ZnAiOiJCMkNfMV9iMmNwb2xpY3lkYW1pZW4iLCJhdF9oYXNoIjoiWmswZktKU19wWWhPcE04SUJhMTJmdyJ9.E5Z-0kOzNU7LBkeVHHMyNoER8TUapGzUUfXmW6gVu4v6QMM5fQ4sJ7KC8PHh8lBFYiCnaDiTtpn3QytUwjXEFnLDAX5qcZT1aPoEgL_OmZMC-8y-4GyHp35l7VFD4iNYM9fJmLE8SYHTVl7eWPlXSyz37Ip0ciiV0Fd6eoksD_aVc-hkIqngDfE4fR8ZKfv4yLTNN_SfknFfuJbZ56yN-zIBL4GkuHsbQCBYpjtWQ62v98p1jO7NhHKV5JP2ec_Ge6oYc_bKTrE6OIX38RJ2rIm7zU16mtdjnl_350Nw3ytHcTPnA1VpP_VLElCfe83jr5aDHc_UQRYaAcWlOgvmVg';
|
|
|
|
const result = tokenValidationService.hasIdTokenExpired(idToken, {
|
|
configId: 'configId1',
|
|
});
|
|
|
|
expect(result).toBe(true);
|
|
});
|
|
|
|
it('returns false if token has not expired using offset', () => {
|
|
// expires 2050-02-12T08:02:30.823Z
|
|
const tokenExpires = new Date('2050-02-12T08:02:30.823Z');
|
|
const idToken =
|
|
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTMxMTY5NTAsImV4cCI6MjUyODI2NTc1MCwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXX0.GHxRo23NghUTTeZx6VIzTSf05JEeEn7z9YYyFLxWv6M';
|
|
|
|
vi.spyOn(tokenHelperService, 'getTokenExpirationDate').mockReturnValue(
|
|
tokenExpires
|
|
);
|
|
|
|
const result = tokenValidationService.hasIdTokenExpired(idToken, {
|
|
configId: 'configId1',
|
|
});
|
|
|
|
expect(result).toBe(false);
|
|
});
|
|
});
|
|
});
|