@axa-fr/react-oidc 6.15.8 → 6.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/{copy.js → copy.cjs} +5 -2
- package/dist/service_worker/OidcServiceWorker.d.ts +2 -0
- package/dist/service_worker/OidcServiceWorker.d.ts.map +1 -0
- package/dist/service_worker/OidcServiceWorker.js +369 -0
- package/dist/service_worker/OidcServiceWorker.js.map +1 -0
- package/dist/service_worker/constants.d.ts +18 -0
- package/dist/service_worker/constants.d.ts.map +1 -0
- package/dist/service_worker/types.d.ts +80 -0
- package/dist/service_worker/types.d.ts.map +1 -0
- package/dist/service_worker/utils/domains.d.ts +6 -0
- package/dist/service_worker/utils/domains.d.ts.map +1 -0
- package/dist/service_worker/utils/index.d.ts +6 -0
- package/dist/service_worker/utils/index.d.ts.map +1 -0
- package/dist/service_worker/utils/serializeHeaders.d.ts +3 -0
- package/dist/service_worker/utils/serializeHeaders.d.ts.map +1 -0
- package/dist/service_worker/utils/sleep.d.ts +3 -0
- package/dist/service_worker/utils/sleep.d.ts.map +1 -0
- package/dist/service_worker/utils/strings.d.ts +8 -0
- package/dist/service_worker/utils/strings.d.ts.map +1 -0
- package/dist/service_worker/utils/tokens.d.ts +12 -0
- package/dist/service_worker/utils/tokens.d.ts.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/vanilla/initWorker.js +1 -1
- package/dist/vanilla/initWorker.js.map +1 -1
- package/package.json +17 -9
- package/service_worker/.eslintrc.cjs +18 -0
- package/service_worker/OidcServiceWorker.ts +387 -0
- package/service_worker/constants.ts +32 -0
- package/service_worker/dist/OidcServiceWorker.d.ts +2 -0
- package/service_worker/dist/OidcServiceWorker.d.ts.map +1 -0
- package/service_worker/dist/OidcServiceWorker.js +369 -0
- package/service_worker/dist/OidcServiceWorker.js.map +1 -0
- package/service_worker/dist/constants.d.ts +18 -0
- package/service_worker/dist/constants.d.ts.map +1 -0
- package/service_worker/dist/types.d.ts +80 -0
- package/service_worker/dist/types.d.ts.map +1 -0
- package/service_worker/dist/utils/domains.d.ts +6 -0
- package/service_worker/dist/utils/domains.d.ts.map +1 -0
- package/service_worker/dist/utils/index.d.ts +6 -0
- package/service_worker/dist/utils/index.d.ts.map +1 -0
- package/service_worker/dist/utils/serializeHeaders.d.ts +3 -0
- package/service_worker/dist/utils/serializeHeaders.d.ts.map +1 -0
- package/service_worker/dist/utils/sleep.d.ts +3 -0
- package/service_worker/dist/utils/sleep.d.ts.map +1 -0
- package/service_worker/dist/utils/strings.d.ts +8 -0
- package/service_worker/dist/utils/strings.d.ts.map +1 -0
- package/service_worker/dist/utils/tokens.d.ts +12 -0
- package/service_worker/dist/utils/tokens.d.ts.map +1 -0
- package/service_worker/tsconfig.json +26 -0
- package/service_worker/types.ts +93 -0
- package/service_worker/utils/__tests__/domains.spec.ts +63 -0
- package/service_worker/utils/__tests__/serializeHeaders.spec.ts +11 -0
- package/service_worker/utils/__tests__/strings.spec.ts +9 -0
- package/service_worker/utils/__tests__/testHelper.ts +346 -0
- package/service_worker/utils/__tests__/tokens.spec.ts +68 -0
- package/service_worker/utils/domains.ts +95 -0
- package/service_worker/utils/index.ts +5 -0
- package/service_worker/utils/serializeHeaders.ts +12 -0
- package/service_worker/utils/sleep.ts +2 -0
- package/service_worker/utils/strings.ts +9 -0
- package/service_worker/utils/tokens.ts +198 -0
- package/src/oidc/vanilla/initWorker.ts +1 -1
- package/dist/OidcServiceWorker.d.ts +0 -119
- package/dist/OidcServiceWorker.d.ts.map +0 -1
- package/dist/OidcServiceWorker.js +0 -498
- package/dist/OidcServiceWorker.js.map +0 -1
- /package/{dist → service_worker}/OidcTrustedDomains.js +0 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { OidcConfig, OidcServerConfiguration, Tokens } from '../types';
|
|
2
|
+
declare function b64DecodeUnicode(str: string): string;
|
|
3
|
+
declare function computeTimeLeft(refreshTimeBeforeTokensExpirationInSecond: number, expiresAt: number): number;
|
|
4
|
+
declare function isTokensValid(tokens: Tokens | null): boolean;
|
|
5
|
+
declare const extractTokenPayload: (token?: string) => any;
|
|
6
|
+
declare const isTokensOidcValid: (tokens: Tokens, nonce: string | null, oidcServerConfiguration: OidcServerConfiguration) => {
|
|
7
|
+
isValid: boolean;
|
|
8
|
+
reason: string;
|
|
9
|
+
};
|
|
10
|
+
declare function hideTokens(currentDatabaseElement: OidcConfig): (response: Response) => Response | Promise<Response>;
|
|
11
|
+
export { b64DecodeUnicode, computeTimeLeft, isTokensValid, extractTokenPayload, isTokensOidcValid, hideTokens };
|
|
12
|
+
//# sourceMappingURL=tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../utils/tokens.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAqB,uBAAuB,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAQ1F,iBAAS,gBAAgB,CAAC,GAAG,EAAE,MAAM,UASpC;AAED,iBAAS,eAAe,CACtB,yCAAyC,EAAE,MAAM,EACjD,SAAS,EAAE,MAAM,UAQlB;AAED,iBAAS,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,WAK3C;AAED,QAAA,MAAM,mBAAmB,WAAY,MAAM,QAc1C,CAAC;AAIF,QAAA,MAAM,iBAAiB,WACb,MAAM,SACP,MAAM,GAAG,IAAI,2BACK,uBAAuB,KAC/C;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CA8BpC,CAAC;AAEF,iBAAS,UAAU,CAAC,sBAAsB,EAAE,UAAU,cAElC,QAAQ,kCA6F3B;AAED,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACX,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"strict": true,
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"forceConsistentCasingInFileNames": true,
|
|
6
|
+
"composite": true,
|
|
7
|
+
"module": "ESNext",
|
|
8
|
+
"target": "ESNext",
|
|
9
|
+
"moduleResolution": "Node",
|
|
10
|
+
"sourceMap": true,
|
|
11
|
+
"declarationMap": true,
|
|
12
|
+
"outDir": "../dist",
|
|
13
|
+
// From https://joshuatz.com/posts/2021/strongly-typed-service-workers/
|
|
14
|
+
"lib": ["webworker", "ESNext"],
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"esModuleInterop": true,
|
|
17
|
+
"noEmit": true,
|
|
18
|
+
"noUnusedLocals": true,
|
|
19
|
+
"noUnusedParameters": true,
|
|
20
|
+
"noImplicitReturns": true,
|
|
21
|
+
"skipLibCheck": true,
|
|
22
|
+
"types": [] // Don't include the default node types or will get conflicts.
|
|
23
|
+
},
|
|
24
|
+
"include": ["./**/*.ts"],
|
|
25
|
+
"exclude": ["node_modules", "dist", "build", "coverage", "scripts"]
|
|
26
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export type Domain = string | RegExp;
|
|
2
|
+
|
|
3
|
+
export type TrustedDomains = {
|
|
4
|
+
[key: string]: Domain[]
|
|
5
|
+
}
|
|
6
|
+
export type OidcServerConfiguration = {
|
|
7
|
+
revocationEndpoint: string;
|
|
8
|
+
issuer: string;
|
|
9
|
+
authorizationEndpoint: string;
|
|
10
|
+
tokenEndpoint: string;
|
|
11
|
+
userInfoEndpoint: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type OidcConfiguration = {
|
|
15
|
+
token_renew_mode: string;
|
|
16
|
+
service_worker_convert_all_requests_to_cors: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
// Uncertain why the Headers interface in lib.webworker.d.ts does not have a keys() function, so extending
|
|
21
|
+
export interface FetchHeaders extends Headers {
|
|
22
|
+
keys(): string[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type Status = 'LOGGED' | 'LOGGED_IN' | 'LOGGED_OUT' | 'NOT_CONNECTED' | 'LOGOUT_FROM_ANOTHER_TAB' | 'SESSION_LOST' | 'REQUIRE_SYNC_TOKENS' | 'FORCE_REFRESH' | null;
|
|
26
|
+
export type MessageEventType = 'clear' | 'init' | 'setState' | 'getState' | 'setCodeVerifier' | 'getCodeVerifier' | 'setSessionState' | 'getSessionState' | 'setNonce';
|
|
27
|
+
|
|
28
|
+
export type MessageData = {
|
|
29
|
+
status: Status;
|
|
30
|
+
oidcServerConfiguration: OidcServerConfiguration;
|
|
31
|
+
oidcConfiguration: OidcConfiguration;
|
|
32
|
+
where: string;
|
|
33
|
+
state: string;
|
|
34
|
+
codeVerifier: string;
|
|
35
|
+
sessionState: string;
|
|
36
|
+
nonce: Nonce;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type MessageEventData = {
|
|
40
|
+
configurationName: string;
|
|
41
|
+
type: MessageEventType;
|
|
42
|
+
data: MessageData;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type Nonce = {
|
|
46
|
+
nonce: string;
|
|
47
|
+
} | null;
|
|
48
|
+
|
|
49
|
+
export type OidcConfig = {
|
|
50
|
+
configurationName: string;
|
|
51
|
+
tokens: Tokens | null;
|
|
52
|
+
status: Status;
|
|
53
|
+
state: string | null;
|
|
54
|
+
codeVerifier: string | null;
|
|
55
|
+
nonce: Nonce;
|
|
56
|
+
oidcServerConfiguration: OidcServerConfiguration | null;
|
|
57
|
+
oidcConfiguration?: OidcConfiguration;
|
|
58
|
+
sessionState?: string | null;
|
|
59
|
+
items?: MessageData;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type IdTokenPayload = {
|
|
63
|
+
iss: string;
|
|
64
|
+
/**
|
|
65
|
+
* (Expiration Time) Claim
|
|
66
|
+
*/
|
|
67
|
+
exp: number;
|
|
68
|
+
/**
|
|
69
|
+
* (Issued At) Claim
|
|
70
|
+
*/
|
|
71
|
+
iat: number;
|
|
72
|
+
nonce: string | null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export type AccessTokenPayload = {
|
|
76
|
+
exp: number;
|
|
77
|
+
sub: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type Tokens = {
|
|
81
|
+
issued_at: number;
|
|
82
|
+
access_token: string;
|
|
83
|
+
accessTokenPayload: AccessTokenPayload | null;
|
|
84
|
+
id_token: null | string;
|
|
85
|
+
idTokenPayload: IdTokenPayload;
|
|
86
|
+
refresh_token?: string;
|
|
87
|
+
expiresAt: number;
|
|
88
|
+
expires_in: number;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export type Database = {
|
|
92
|
+
[key: string]: OidcConfig
|
|
93
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { TrustedDomains, Database } from './../../types';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import { checkDomain, getCurrentDatabaseDomain } from '..';
|
|
4
|
+
import { openidWellknownUrlEndWith } from '../../constants';
|
|
5
|
+
|
|
6
|
+
describe('domains', () => {
|
|
7
|
+
describe('can check domain matches', () => {
|
|
8
|
+
it('can check string domains and return void', () => {
|
|
9
|
+
const result = () =>
|
|
10
|
+
checkDomain(
|
|
11
|
+
['https://securesite.com:3000'],
|
|
12
|
+
'https://securesite.com:3000'
|
|
13
|
+
);
|
|
14
|
+
expect(result()).toBeUndefined();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('can check regExp domains and return void when valid', () => {
|
|
18
|
+
const result = () =>
|
|
19
|
+
checkDomain(
|
|
20
|
+
[/^https:\/\/securesite\.com/],
|
|
21
|
+
'https://securesite.com:3000'
|
|
22
|
+
);
|
|
23
|
+
expect(result()).toBeUndefined();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('will throw error when domain is not trusted', () => {
|
|
27
|
+
const result = () =>
|
|
28
|
+
checkDomain(
|
|
29
|
+
['https://notsecuresite.com'],
|
|
30
|
+
'https://securesite.com:3000'
|
|
31
|
+
);
|
|
32
|
+
expect(result).toThrowError();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('will return void when endpoint is falsy', () => {
|
|
36
|
+
const result = () => checkDomain(['https://securesite.com:3000'], '');
|
|
37
|
+
expect(result()).toBeUndefined();
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
describe('getCurrentDatabaseDomain', () => {
|
|
41
|
+
it('will return null when url ends with openidWellknownUrlEndWith', () => {
|
|
42
|
+
const trustedDomains: TrustedDomains = {
|
|
43
|
+
default: [
|
|
44
|
+
'https://demo.duendesoftware.com',
|
|
45
|
+
'https://kdhttps.auth0.com',
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
const db: Database = {
|
|
49
|
+
default: {
|
|
50
|
+
configurationName: 'config',
|
|
51
|
+
tokens: null,
|
|
52
|
+
status: 'NOT_CONNECTED',
|
|
53
|
+
state: null,
|
|
54
|
+
codeVerifier: null,
|
|
55
|
+
nonce: null,
|
|
56
|
+
oidcServerConfiguration: null,
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
const url = 'http://url' + openidWellknownUrlEndWith;
|
|
60
|
+
getCurrentDatabaseDomain(db, url, trustedDomains);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { serializeHeaders } from '..';
|
|
3
|
+
|
|
4
|
+
describe('serializeHeaders', () => {
|
|
5
|
+
it('can serialize basic header', () => {
|
|
6
|
+
const result = serializeHeaders(
|
|
7
|
+
new Headers({ 'Content-Type': 'application/json' })
|
|
8
|
+
); // Error: Argument of type 'Headers' is not assignable to parameter of type 'Headers'.(2345
|
|
9
|
+
expect(result).toEqual({ 'content-type': 'application/json' });
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
AccessTokenPayload,
|
|
4
|
+
IdTokenPayload,
|
|
5
|
+
Nonce,
|
|
6
|
+
OidcConfig,
|
|
7
|
+
OidcConfiguration,
|
|
8
|
+
OidcServerConfiguration,
|
|
9
|
+
Status,
|
|
10
|
+
Tokens,
|
|
11
|
+
} from '../../types';
|
|
12
|
+
|
|
13
|
+
const currentTimeUnixSeconds = (): number => {
|
|
14
|
+
return new Date().getTime() / 1000;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const createToken = (expires: number, issued_at: number): Tokens => {
|
|
18
|
+
return {
|
|
19
|
+
expiresAt: expires,
|
|
20
|
+
issued_at: issued_at,
|
|
21
|
+
expires_in: 60,
|
|
22
|
+
id_token: null,
|
|
23
|
+
accessTokenPayload: null,
|
|
24
|
+
access_token: '',
|
|
25
|
+
idTokenPayload: { iss: '', exp: 0, iat: 0, nonce: null },
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
class TokenBuilder {
|
|
30
|
+
private tokens: Tokens = {
|
|
31
|
+
expiresAt: 0,
|
|
32
|
+
issued_at: 0,
|
|
33
|
+
expires_in: 0,
|
|
34
|
+
id_token: null,
|
|
35
|
+
accessTokenPayload: null,
|
|
36
|
+
access_token: '',
|
|
37
|
+
idTokenPayload: { iss: '', exp: 0, iat: 0, nonce: null },
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
constructor() {}
|
|
41
|
+
|
|
42
|
+
public withExpiredToken(): TokenBuilder {
|
|
43
|
+
this.withExpiresIn(currentTimeUnixSeconds() - 10);
|
|
44
|
+
this.withIssuedAt(currentTimeUnixSeconds() - 60);
|
|
45
|
+
return this;
|
|
46
|
+
}
|
|
47
|
+
public WithNonExpiredToken(): TokenBuilder {
|
|
48
|
+
this.withExpiresAt(currentTimeUnixSeconds() + 60);
|
|
49
|
+
this.withExpiresIn(currentTimeUnixSeconds() + 60);
|
|
50
|
+
this.withIssuedAt(currentTimeUnixSeconds() - 60);
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public withExpiresAt(expiresAt: number): TokenBuilder {
|
|
55
|
+
this.tokens.expiresAt = expiresAt;
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public withIssuedAt(issued_at: number): TokenBuilder {
|
|
60
|
+
this.tokens.issued_at = issued_at;
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public withExpiresIn(expires_in: number): TokenBuilder {
|
|
65
|
+
this.tokens.expires_in = expires_in;
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public withIdToken(id_token: string): TokenBuilder {
|
|
70
|
+
this.tokens.id_token = id_token;
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public withAccessTokenPayload(
|
|
75
|
+
accessTokenPayload: AccessTokenPayload
|
|
76
|
+
): TokenBuilder {
|
|
77
|
+
this.tokens.accessTokenPayload = accessTokenPayload;
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public withAccessToken(access_token: string): TokenBuilder {
|
|
82
|
+
this.tokens.access_token = access_token;
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public withIdTokenPayload(idTokenPayload: IdTokenPayload): TokenBuilder {
|
|
87
|
+
this.tokens.idTokenPayload = idTokenPayload;
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public build(): Tokens {
|
|
92
|
+
return this.tokens;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
class OidcConfigurationBuilder {
|
|
97
|
+
private oidcConfiguration: OidcConfiguration = {
|
|
98
|
+
token_renew_mode: 'offline',
|
|
99
|
+
service_worker_convert_all_requests_to_cors: true,
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
constructor() {}
|
|
103
|
+
|
|
104
|
+
public withTokenRenewMode(
|
|
105
|
+
token_renew_mode: string
|
|
106
|
+
): OidcConfigurationBuilder {
|
|
107
|
+
this.oidcConfiguration.token_renew_mode = token_renew_mode;
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public withServiceWorkerConvertAllRequestsToCors(
|
|
112
|
+
service_worker_convert_all_requests_to_cors: boolean
|
|
113
|
+
): OidcConfigurationBuilder {
|
|
114
|
+
this.oidcConfiguration.service_worker_convert_all_requests_to_cors =
|
|
115
|
+
service_worker_convert_all_requests_to_cors;
|
|
116
|
+
return this;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public build(): OidcConfiguration {
|
|
120
|
+
return this.oidcConfiguration;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
class OidcConfigBuilder {
|
|
125
|
+
private oidcConfig: OidcConfig = {
|
|
126
|
+
configurationName: '',
|
|
127
|
+
tokens: null,
|
|
128
|
+
status: 'NOT_CONNECTED',
|
|
129
|
+
state: '',
|
|
130
|
+
codeVerifier: '',
|
|
131
|
+
nonce: null,
|
|
132
|
+
oidcServerConfiguration: null,
|
|
133
|
+
oidcConfiguration: undefined,
|
|
134
|
+
sessionState: null,
|
|
135
|
+
items: undefined,
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
constructor() {}
|
|
139
|
+
|
|
140
|
+
public withTestingDefault(): OidcConfigBuilder {
|
|
141
|
+
this.oidcConfig.configurationName = 'test';
|
|
142
|
+
this.oidcConfig.tokens = new TokenBuilder().WithNonExpiredToken().build();
|
|
143
|
+
this.oidcConfig.status = 'NOT_CONNECTED';
|
|
144
|
+
this.oidcConfig.state = 'state';
|
|
145
|
+
this.oidcConfig.codeVerifier = 'codeVerifier';
|
|
146
|
+
this.oidcConfig.nonce = null;
|
|
147
|
+
this.oidcConfig.oidcConfiguration = new OidcConfigurationBuilder().build();
|
|
148
|
+
this.oidcConfig.oidcServerConfiguration = new OidcServerConfigBuilder()
|
|
149
|
+
.withTestingDefault()
|
|
150
|
+
.build();
|
|
151
|
+
this.oidcConfig.sessionState = null;
|
|
152
|
+
this.oidcConfig.items = undefined;
|
|
153
|
+
return this;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
public withConfigurationName(configurationName: string): OidcConfigBuilder {
|
|
157
|
+
this.oidcConfig.configurationName = configurationName;
|
|
158
|
+
return this;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
public withTokens(tokens: Tokens): OidcConfigBuilder {
|
|
162
|
+
this.oidcConfig.tokens = tokens;
|
|
163
|
+
return this;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
public withStatus(status: Status): OidcConfigBuilder {
|
|
167
|
+
this.oidcConfig.status = status;
|
|
168
|
+
return this;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
public withState(state: string): OidcConfigBuilder {
|
|
172
|
+
this.oidcConfig.state = state;
|
|
173
|
+
return this;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
public withCodeVerifier(codeVerifier: string): OidcConfigBuilder {
|
|
177
|
+
this.oidcConfig.codeVerifier = codeVerifier;
|
|
178
|
+
return this;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
public withNonce(nonce: Nonce): OidcConfigBuilder {
|
|
182
|
+
this.oidcConfig.nonce = nonce;
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
public withOidcServerConfiguration(
|
|
187
|
+
oidcServerConfiguration: OidcServerConfiguration
|
|
188
|
+
): OidcConfigBuilder {
|
|
189
|
+
this.oidcConfig.oidcServerConfiguration = oidcServerConfiguration;
|
|
190
|
+
return this;
|
|
191
|
+
}
|
|
192
|
+
public build() {
|
|
193
|
+
return this.oidcConfig;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
class OidcServerConfigBuilder {
|
|
198
|
+
private oidcServerConfig: OidcServerConfiguration = {
|
|
199
|
+
revocationEndpoint: '',
|
|
200
|
+
issuer: '',
|
|
201
|
+
authorizationEndpoint: '',
|
|
202
|
+
tokenEndpoint: '',
|
|
203
|
+
userInfoEndpoint: '',
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
constructor() {}
|
|
207
|
+
|
|
208
|
+
public withTestingDefault(): OidcServerConfigBuilder {
|
|
209
|
+
this.oidcServerConfig.revocationEndpoint =
|
|
210
|
+
'http://localhost:3000/revocation';
|
|
211
|
+
this.oidcServerConfig.issuer = 'http://localhost:3000';
|
|
212
|
+
this.oidcServerConfig.authorizationEndpoint =
|
|
213
|
+
'http://localhost:3000/authorization';
|
|
214
|
+
this.oidcServerConfig.tokenEndpoint = 'http://localhost:3000/token';
|
|
215
|
+
this.oidcServerConfig.userInfoEndpoint = 'http://localhost:3000/userinfo';
|
|
216
|
+
return this;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
public withRevocationEndpoint(
|
|
220
|
+
revocationEndpoint: string
|
|
221
|
+
): OidcServerConfigBuilder {
|
|
222
|
+
this.oidcServerConfig.revocationEndpoint = revocationEndpoint;
|
|
223
|
+
return this;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
public withIssuer(issuer: string): OidcServerConfigBuilder {
|
|
227
|
+
this.oidcServerConfig.issuer = issuer;
|
|
228
|
+
return this;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
public withAuthorizationEndpoint(
|
|
232
|
+
authorizationEndpoint: string
|
|
233
|
+
): OidcServerConfigBuilder {
|
|
234
|
+
this.oidcServerConfig.authorizationEndpoint = authorizationEndpoint;
|
|
235
|
+
return this;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
public withTokenEndpoint(tokenEndpoint: string): OidcServerConfigBuilder {
|
|
239
|
+
this.oidcServerConfig.tokenEndpoint = tokenEndpoint;
|
|
240
|
+
return this;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
public withUserInfoEndpoint(
|
|
244
|
+
userInfoEndpoint: string
|
|
245
|
+
): OidcServerConfigBuilder {
|
|
246
|
+
this.oidcServerConfig.userInfoEndpoint = userInfoEndpoint;
|
|
247
|
+
return this;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
public build(): OidcServerConfiguration {
|
|
251
|
+
return this.oidcServerConfig;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
interface TestingResponse extends Response {
|
|
256
|
+
bodyContent?: any;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
class ResponseBuilder {
|
|
260
|
+
private response: any = {
|
|
261
|
+
status: 200,
|
|
262
|
+
body: '',
|
|
263
|
+
headers: {},
|
|
264
|
+
bodyContent: { issued_at: 343434 },
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
constructor() {}
|
|
268
|
+
|
|
269
|
+
public withStatus(status: number): ResponseBuilder {
|
|
270
|
+
this.response.status = status;
|
|
271
|
+
return this;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
public withBody(body: string): ResponseBuilder {
|
|
275
|
+
this.response.body = body;
|
|
276
|
+
return this;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
public withHeaders(headers: Headers): ResponseBuilder {
|
|
280
|
+
this.response.headers = headers;
|
|
281
|
+
return this;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Custom property for Testing setup
|
|
286
|
+
* @param body
|
|
287
|
+
* @returns
|
|
288
|
+
*/
|
|
289
|
+
public withBodyContent(body: any): ResponseBuilder {
|
|
290
|
+
this.response.bodyContent = body;
|
|
291
|
+
return this;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
public build(): TestingResponse {
|
|
295
|
+
return {
|
|
296
|
+
...{
|
|
297
|
+
status: 200,
|
|
298
|
+
headers: {
|
|
299
|
+
append: vi.fn(),
|
|
300
|
+
delete: vi.fn(),
|
|
301
|
+
forEach: vi.fn(),
|
|
302
|
+
get: vi.fn(),
|
|
303
|
+
has: vi.fn(),
|
|
304
|
+
set: vi.fn(),
|
|
305
|
+
},
|
|
306
|
+
ok: true,
|
|
307
|
+
redirected: false,
|
|
308
|
+
statusText: '',
|
|
309
|
+
type: 'basic',
|
|
310
|
+
url: '',
|
|
311
|
+
clone: function (): Response {
|
|
312
|
+
throw new Error('Function not implemented.');
|
|
313
|
+
},
|
|
314
|
+
body: null,
|
|
315
|
+
bodyUsed: false,
|
|
316
|
+
arrayBuffer: function (): Promise<ArrayBuffer> {
|
|
317
|
+
throw new Error('Function not implemented.');
|
|
318
|
+
},
|
|
319
|
+
blob: function (): Promise<Blob> {
|
|
320
|
+
throw new Error('Function not implemented.');
|
|
321
|
+
},
|
|
322
|
+
formData: function (): Promise<FormData> {
|
|
323
|
+
throw new Error('Function not implemented.');
|
|
324
|
+
},
|
|
325
|
+
json: function (): Promise<any> {
|
|
326
|
+
return new Promise<any>((resolve) => {
|
|
327
|
+
resolve(this.bodyContent);
|
|
328
|
+
});
|
|
329
|
+
},
|
|
330
|
+
text: function (): Promise<string> {
|
|
331
|
+
throw new Error('Function not implemented.');
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
...this.response,
|
|
335
|
+
} as TestingResponse;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export {
|
|
340
|
+
currentTimeUnixSeconds,
|
|
341
|
+
createToken,
|
|
342
|
+
TokenBuilder,
|
|
343
|
+
OidcServerConfigBuilder,
|
|
344
|
+
OidcConfigBuilder,
|
|
345
|
+
ResponseBuilder,
|
|
346
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { OidcServerConfiguration } from '../../types';
|
|
3
|
+
import { extractTokenPayload, isTokensOidcValid, isTokensValid } from '..';
|
|
4
|
+
import { OidcServerConfigBuilder, TokenBuilder } from './testHelper';
|
|
5
|
+
|
|
6
|
+
describe('tokens', () => {
|
|
7
|
+
let oidcServerConfig: OidcServerConfiguration;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
oidcServerConfig = new OidcServerConfigBuilder()
|
|
11
|
+
.withTestingDefault()
|
|
12
|
+
.build();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe('isTokensValid', () => {
|
|
16
|
+
it('can check expired token', () => {
|
|
17
|
+
expect(
|
|
18
|
+
isTokensValid(new TokenBuilder().withExpiredToken().build())
|
|
19
|
+
).toBeFalsy();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('can check non-expired token', () => {
|
|
23
|
+
const token = new TokenBuilder().WithNonExpiredToken().build();
|
|
24
|
+
expect(isTokensValid(token)).toBeTruthy();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('can check null token', () => {
|
|
28
|
+
expect(isTokensValid(null)).toBeFalsy();
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('extractTokenPayload', () => {
|
|
33
|
+
it('can extract token payload', () => {
|
|
34
|
+
const result = extractTokenPayload(
|
|
35
|
+
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'
|
|
36
|
+
);
|
|
37
|
+
expect(result).toEqual({
|
|
38
|
+
sub: '1234567890',
|
|
39
|
+
name: 'John Doe',
|
|
40
|
+
iat: 1516239022,
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
it('returns null if undefined', () => {
|
|
44
|
+
expect(extractTokenPayload(undefined)).toBeNull();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('returns null if invalid token', () => {
|
|
48
|
+
expect(extractTokenPayload('invalid token')).toBeNull();
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('isTokensOidcValid', () => {
|
|
53
|
+
it('can validate valid token', () => {
|
|
54
|
+
const token = new TokenBuilder()
|
|
55
|
+
.WithNonExpiredToken()
|
|
56
|
+
.withIdTokenPayload({
|
|
57
|
+
iss: oidcServerConfig.issuer,
|
|
58
|
+
exp: 0,
|
|
59
|
+
iat: 0,
|
|
60
|
+
nonce: null,
|
|
61
|
+
})
|
|
62
|
+
.build();
|
|
63
|
+
const result = isTokensOidcValid(token, null, oidcServerConfig);
|
|
64
|
+
expect(result.isValid).toBeTruthy();
|
|
65
|
+
expect(result.reason).toBe('');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|