passport-steam-openid 1.0.3 → 1.1.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/README.md +1 -1
- package/dist/strategy.d.ts +18 -0
- package/dist/strategy.d.ts.map +1 -1
- package/dist/strategy.js +23 -1
- package/dist/type.d.ts +15 -1
- package/dist/type.d.ts.map +1 -1
- package/dist/type.js +4 -0
- package/package.json +1 -1
- package/sample/package-lock.json +190 -100
- package/sample/package.json +1 -1
- package/src/strategy.ts +36 -1
- package/src/type.ts +14 -0
- package/test/setup/data.ts +15 -9
- package/test/strategy.ts +71 -1
package/README.md
CHANGED
|
@@ -59,7 +59,7 @@ Install using npm:
|
|
|
59
59
|
```
|
|
60
60
|
npm install passport-steam-openid
|
|
61
61
|
```
|
|
62
|
-
|
|
62
|
+
Library's API has been unchanged and stable for some time now. It will not change unless a breaking change is issued by steam (very unlikely).
|
|
63
63
|
|
|
64
64
|
## License
|
|
65
65
|
This library is released under MIT license.
|
package/dist/strategy.d.ts
CHANGED
|
@@ -34,12 +34,22 @@ export declare class SteamOpenIdStrategy<TOptions extends SteamOpenIdStrategyOpt
|
|
|
34
34
|
* optional callback, called when user is successfully authenticated
|
|
35
35
|
*/
|
|
36
36
|
protected verify?: VerifyCallback<TUser>;
|
|
37
|
+
/**
|
|
38
|
+
* Optional setting for validating nonce time delay,
|
|
39
|
+
* in seconds.
|
|
40
|
+
*
|
|
41
|
+
* Measures time between nonce creation date and verification.
|
|
42
|
+
*/
|
|
43
|
+
protected maxNonceTimeDelay: number | undefined;
|
|
37
44
|
/**
|
|
38
45
|
* @constructor
|
|
39
46
|
*
|
|
40
47
|
* @param options.returnURL where steam redirects after parameters are passed
|
|
41
48
|
* @param options.profile if set, we will fetch user's profile from steam api
|
|
42
49
|
* @param options.apiKey api key to fetch user profile, not used if profile is false
|
|
50
|
+
* @param options.maxNonceTimeDelay optional setting for validating nonce time delay,
|
|
51
|
+
* this is just an extra security measure, it is not required nor recommended, but
|
|
52
|
+
* might be extra layer of security you want to have.
|
|
43
53
|
* @param verify optional callback, called when user is successfully authenticated
|
|
44
54
|
*/
|
|
45
55
|
constructor(options: TOptions, verify?: VerifyCallback<TUser>);
|
|
@@ -64,6 +74,14 @@ export declare class SteamOpenIdStrategy<TOptions extends SteamOpenIdStrategyOpt
|
|
|
64
74
|
* @throws {Error} Non-recoverable errors, such as query object missing.
|
|
65
75
|
*/
|
|
66
76
|
handleRequest(req: any): Promise<TUser>;
|
|
77
|
+
/**
|
|
78
|
+
* Check if nonce date has expired against current delay setting,
|
|
79
|
+
* if no setting was set, then it is considered as not expired.
|
|
80
|
+
*
|
|
81
|
+
* @param nonceDate date when nonce was created
|
|
82
|
+
* @returns true, if nonce has expired and error should be thrown
|
|
83
|
+
*/
|
|
84
|
+
protected hasNonceExpired(query: SteamOpenIdQuery): boolean;
|
|
67
85
|
/**
|
|
68
86
|
* Checks if error is retryable,
|
|
69
87
|
* meaning user gets redirected to steam openid page.
|
package/dist/strategy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../src/strategy.ts"],"names":[],"mappings":";AAAA,OAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACjD,OAAc,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAUpC,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,gBAAgB,EAGhB,qCAAqC,EACrC,wCAAwC,EACxC,cAAc,EACf,MAAM,QAAQ,CAAC;AAEhB;;;;;;;GAOG;AACH,qBAAa,mBAAmB,CAC9B,QAAQ,SACJ,qCAAqC,GACrC,wCAAwC,EAC5C,KAAK,SACD,eAAe,GACf,sBAAsB,GAAG,QAAQ,SAAS,qCAAqC,GAC/E,sBAAsB,GACtB,eAAe,CACnB,SAAQ,QAAQ;IAChB;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAExC;;;;OAIG;IACH,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAErC;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAEnC;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAEpC;;OAEG;IACH,SAAS,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;IAEzC
|
|
1
|
+
{"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../src/strategy.ts"],"names":[],"mappings":";AAAA,OAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACjD,OAAc,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAUpC,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,gBAAgB,EAGhB,qCAAqC,EACrC,wCAAwC,EACxC,cAAc,EACf,MAAM,QAAQ,CAAC;AAEhB;;;;;;;GAOG;AACH,qBAAa,mBAAmB,CAC9B,QAAQ,SACJ,qCAAqC,GACrC,wCAAwC,EAC5C,KAAK,SACD,eAAe,GACf,sBAAsB,GAAG,QAAQ,SAAS,qCAAqC,GAC/E,sBAAsB,GACtB,eAAe,CACnB,SAAQ,QAAQ;IAChB;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAExC;;;;OAIG;IACH,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAErC;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAEnC;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAEpC;;OAEG;IACH,SAAS,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;IAEzC;;;;;OAKG;IACH,SAAS,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IAEhD;;;;;;;;;;OAUG;gBACS,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC;IAY7D;;;;OAIG;IACmB,YAAY,CAAC,GAAG,EAAE,GAAG;IA+B3C;;;;;;;;;;;;;OAaG;IACU,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC;IAmCpD;;;;;;OAMG;IACH,SAAS,CAAC,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO;IAW3D;;;;;;;;OAQG;IACH,SAAS,CAAC,gBAAgB,CAAC,GAAG,EAAE,OAAO;IAOvC;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,cAAc;IAQ5C;;;;;;OAMG;IACH,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,cAAc;IAI5C;;;;OAIG;IACI,gBAAgB;IAYvB;;;;;;;OAOG;IACH,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,IAAI,gBAAgB;IAcxE;;;;;;OAMG;IACH,SAAS,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IASpD;;;;;;OAMG;IACH,SAAS,CAAC,oBAAoB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBzE;;;;OAIG;IACH,SAAS,CAAC,8BAA8B,CAAC,KAAK,EAAE,gBAAgB;IAMhE;;;;;;OAMG;IACH,SAAS,CAAC,oBAAoB,CAAC,QAAQ,EAAE,GAAG;IAQ5C;;;;;OAKG;IACH,SAAS,CAAC,UAAU,CAAC,KAAK,EAAE,gBAAgB;IAM5C;;;;;;;;OAQG;cACa,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IASxD;;;;;;;;;;OAUG;cACa,kBAAkB,CAChC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,sBAAsB,CAAC;CAiCnC"}
|
package/dist/strategy.js
CHANGED
|
@@ -23,6 +23,9 @@ class SteamOpenIdStrategy extends passport_1.Strategy {
|
|
|
23
23
|
* @param options.returnURL where steam redirects after parameters are passed
|
|
24
24
|
* @param options.profile if set, we will fetch user's profile from steam api
|
|
25
25
|
* @param options.apiKey api key to fetch user profile, not used if profile is false
|
|
26
|
+
* @param options.maxNonceTimeDelay optional setting for validating nonce time delay,
|
|
27
|
+
* this is just an extra security measure, it is not required nor recommended, but
|
|
28
|
+
* might be extra layer of security you want to have.
|
|
26
29
|
* @param verify optional callback, called when user is successfully authenticated
|
|
27
30
|
*/
|
|
28
31
|
constructor(options, verify) {
|
|
@@ -31,6 +34,7 @@ class SteamOpenIdStrategy extends passport_1.Strategy {
|
|
|
31
34
|
this.axios = axios_1.default.create();
|
|
32
35
|
this.returnURL = options.returnURL;
|
|
33
36
|
this.profile = options.profile;
|
|
37
|
+
this.maxNonceTimeDelay = options.maxNonceTimeDelay;
|
|
34
38
|
if (options.profile)
|
|
35
39
|
this.apiKey = options.apiKey;
|
|
36
40
|
if (verify)
|
|
@@ -93,7 +97,9 @@ class SteamOpenIdStrategy extends passport_1.Strategy {
|
|
|
93
97
|
if (!this.isQueryValid(query)) {
|
|
94
98
|
throw new error_1.SteamOpenIdError('Supplied query is invalid.', type_1.SteamOpenIdErrorType.InvalidQuery);
|
|
95
99
|
}
|
|
96
|
-
|
|
100
|
+
if (this.hasNonceExpired(query)) {
|
|
101
|
+
throw new error_1.SteamOpenIdError('Nonce time delay was too big.', type_1.SteamOpenIdErrorType.NonceExpired);
|
|
102
|
+
}
|
|
97
103
|
const valid = yield this.validateAgainstSteam(query);
|
|
98
104
|
if (!valid) {
|
|
99
105
|
throw new error_1.SteamOpenIdError('Failed to validate query against steam.', type_1.SteamOpenIdErrorType.Unauthorized);
|
|
@@ -102,6 +108,22 @@ class SteamOpenIdStrategy extends passport_1.Strategy {
|
|
|
102
108
|
return yield this.getUser(steamId);
|
|
103
109
|
});
|
|
104
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Check if nonce date has expired against current delay setting,
|
|
113
|
+
* if no setting was set, then it is considered as not expired.
|
|
114
|
+
*
|
|
115
|
+
* @param nonceDate date when nonce was created
|
|
116
|
+
* @returns true, if nonce has expired and error should be thrown
|
|
117
|
+
*/
|
|
118
|
+
hasNonceExpired(query) {
|
|
119
|
+
if (typeof this.maxNonceTimeDelay == 'undefined') {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
const nonceDate = new Date(query['openid.response_nonce'].slice(0, 20));
|
|
123
|
+
const nonceSeconds = Math.floor(nonceDate.getTime() / 1000);
|
|
124
|
+
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
125
|
+
return nowSeconds - nonceSeconds > this.maxNonceTimeDelay;
|
|
126
|
+
}
|
|
105
127
|
/**
|
|
106
128
|
* Checks if error is retryable,
|
|
107
129
|
* meaning user gets redirected to steam openid page.
|
package/dist/type.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { DoneCallback } from 'passport';
|
|
2
2
|
export type BaseSteamOpenIdStrategyOptions = {
|
|
3
3
|
returnURL: string;
|
|
4
|
+
/**
|
|
5
|
+
* Maximum time delay between the nonce creation and the nonce verification,
|
|
6
|
+
* in seconds.
|
|
7
|
+
*
|
|
8
|
+
* nonce includes a timestamp we can validate against the current time,
|
|
9
|
+
* while the steam server validates this as well, you might want to
|
|
10
|
+
* set maximum number of seconds between the nonce creation and the nonce
|
|
11
|
+
* verification.
|
|
12
|
+
*/
|
|
13
|
+
maxNonceTimeDelay?: number;
|
|
4
14
|
};
|
|
5
15
|
export type SteamOpenIdStrategyOptionsWithProfile = {
|
|
6
16
|
profile: true;
|
|
@@ -31,7 +41,11 @@ export declare enum SteamOpenIdErrorType {
|
|
|
31
41
|
/**
|
|
32
42
|
* SteamId is not valid.
|
|
33
43
|
*/
|
|
34
|
-
InvalidSteamId = 3
|
|
44
|
+
InvalidSteamId = 3,
|
|
45
|
+
/**
|
|
46
|
+
* Nonce has expired.
|
|
47
|
+
*/
|
|
48
|
+
NonceExpired = 4
|
|
35
49
|
}
|
|
36
50
|
/** When profile is not used, we just send a steamid. */
|
|
37
51
|
export type SteamOpenIdUser = {
|
package/dist/type.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,MAAM,8BAA8B,GAAG;IAC3C,SAAS,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,MAAM,8BAA8B,GAAG;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,qCAAqC,GAAG;IAClD,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,8BAA8B,CAAC;AAEnC,MAAM,MAAM,wCAAwC,GAAG;IACrD,OAAO,EAAE,KAAK,CAAC;CAChB,GAAG,8BAA8B,CAAC;AAEnC,MAAM,MAAM,0BAA0B,GAClC,qCAAqC,GACrC,wCAAwC,CAAC;AAE7C;;;;GAIG;AACH,oBAAY,oBAAoB;IAC9B;;OAEG;IACH,WAAW,IAAI;IACf;;OAEG;IACH,YAAY,IAAI;IAChB;;OAEG;IACH,YAAY,IAAI;IAChB;;OAEG;IACH,cAAc,IAAI;IAClB;;OAEG;IACH,YAAY,IAAI;CACjB;AAED,wDAAwD;AACxD,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,+BAA+B;AAC/B,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE;QACR,OAAO,EAAE,sBAAsB,EAAE,CAAC;KACnC,CAAC;CACH,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB,EAAE,MAAM,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,CACxB,KAAK,SAAS,eAAe,GAAG,sBAAsB,IACpD,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,KAAK,GAAG,CAAC;AAE9E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,uBAAuB,EAAE,MAAM,CAAC;IAChC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC"}
|
package/dist/type.js
CHANGED
|
@@ -24,4 +24,8 @@ var SteamOpenIdErrorType;
|
|
|
24
24
|
* SteamId is not valid.
|
|
25
25
|
*/
|
|
26
26
|
SteamOpenIdErrorType[SteamOpenIdErrorType["InvalidSteamId"] = 3] = "InvalidSteamId";
|
|
27
|
+
/**
|
|
28
|
+
* Nonce has expired.
|
|
29
|
+
*/
|
|
30
|
+
SteamOpenIdErrorType[SteamOpenIdErrorType["NonceExpired"] = 4] = "NonceExpired";
|
|
27
31
|
})(SteamOpenIdErrorType || (exports.SteamOpenIdErrorType = SteamOpenIdErrorType = {}));
|
package/package.json
CHANGED
package/sample/package-lock.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"dotenv": "^16.3.1",
|
|
13
|
-
"express": "^4.
|
|
13
|
+
"express": "^4.19.2",
|
|
14
14
|
"express-session": "^1.17.3",
|
|
15
15
|
"passport": "^0.6.0",
|
|
16
16
|
"passport-steam-openid": "^1.0.0"
|
|
@@ -710,6 +710,29 @@
|
|
|
710
710
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
|
711
711
|
"dev": true
|
|
712
712
|
},
|
|
713
|
+
"node_modules/body-parser": {
|
|
714
|
+
"version": "1.20.2",
|
|
715
|
+
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
|
|
716
|
+
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
|
|
717
|
+
"dependencies": {
|
|
718
|
+
"bytes": "3.1.2",
|
|
719
|
+
"content-type": "~1.0.5",
|
|
720
|
+
"debug": "2.6.9",
|
|
721
|
+
"depd": "2.0.0",
|
|
722
|
+
"destroy": "1.2.0",
|
|
723
|
+
"http-errors": "2.0.0",
|
|
724
|
+
"iconv-lite": "0.4.24",
|
|
725
|
+
"on-finished": "2.4.1",
|
|
726
|
+
"qs": "6.11.0",
|
|
727
|
+
"raw-body": "2.5.2",
|
|
728
|
+
"type-is": "~1.6.18",
|
|
729
|
+
"unpipe": "1.0.0"
|
|
730
|
+
},
|
|
731
|
+
"engines": {
|
|
732
|
+
"node": ">= 0.8",
|
|
733
|
+
"npm": "1.2.8000 || >= 1.4.16"
|
|
734
|
+
}
|
|
735
|
+
},
|
|
713
736
|
"node_modules/brace-expansion": {
|
|
714
737
|
"version": "1.1.11",
|
|
715
738
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
|
@@ -741,12 +764,18 @@
|
|
|
741
764
|
}
|
|
742
765
|
},
|
|
743
766
|
"node_modules/call-bind": {
|
|
744
|
-
"version": "1.0.
|
|
745
|
-
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.
|
|
746
|
-
"integrity": "sha512-
|
|
767
|
+
"version": "1.0.7",
|
|
768
|
+
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
|
|
769
|
+
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
|
|
747
770
|
"dependencies": {
|
|
748
|
-
"
|
|
749
|
-
"
|
|
771
|
+
"es-define-property": "^1.0.0",
|
|
772
|
+
"es-errors": "^1.3.0",
|
|
773
|
+
"function-bind": "^1.1.2",
|
|
774
|
+
"get-intrinsic": "^1.2.4",
|
|
775
|
+
"set-function-length": "^1.2.1"
|
|
776
|
+
},
|
|
777
|
+
"engines": {
|
|
778
|
+
"node": ">= 0.4"
|
|
750
779
|
},
|
|
751
780
|
"funding": {
|
|
752
781
|
"url": "https://github.com/sponsors/ljharb"
|
|
@@ -832,9 +861,9 @@
|
|
|
832
861
|
}
|
|
833
862
|
},
|
|
834
863
|
"node_modules/cookie": {
|
|
835
|
-
"version": "0.
|
|
836
|
-
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.
|
|
837
|
-
"integrity": "sha512-
|
|
864
|
+
"version": "0.6.0",
|
|
865
|
+
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
|
866
|
+
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
|
838
867
|
"engines": {
|
|
839
868
|
"node": ">= 0.6"
|
|
840
869
|
}
|
|
@@ -872,6 +901,22 @@
|
|
|
872
901
|
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
|
|
873
902
|
"dev": true
|
|
874
903
|
},
|
|
904
|
+
"node_modules/define-data-property": {
|
|
905
|
+
"version": "1.1.4",
|
|
906
|
+
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
|
907
|
+
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
|
908
|
+
"dependencies": {
|
|
909
|
+
"es-define-property": "^1.0.0",
|
|
910
|
+
"es-errors": "^1.3.0",
|
|
911
|
+
"gopd": "^1.0.1"
|
|
912
|
+
},
|
|
913
|
+
"engines": {
|
|
914
|
+
"node": ">= 0.4"
|
|
915
|
+
},
|
|
916
|
+
"funding": {
|
|
917
|
+
"url": "https://github.com/sponsors/ljharb"
|
|
918
|
+
}
|
|
919
|
+
},
|
|
875
920
|
"node_modules/delayed-stream": {
|
|
876
921
|
"version": "1.0.0",
|
|
877
922
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
|
@@ -945,6 +990,25 @@
|
|
|
945
990
|
"node": ">= 0.8"
|
|
946
991
|
}
|
|
947
992
|
},
|
|
993
|
+
"node_modules/es-define-property": {
|
|
994
|
+
"version": "1.0.0",
|
|
995
|
+
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
|
996
|
+
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
|
997
|
+
"dependencies": {
|
|
998
|
+
"get-intrinsic": "^1.2.4"
|
|
999
|
+
},
|
|
1000
|
+
"engines": {
|
|
1001
|
+
"node": ">= 0.4"
|
|
1002
|
+
}
|
|
1003
|
+
},
|
|
1004
|
+
"node_modules/es-errors": {
|
|
1005
|
+
"version": "1.3.0",
|
|
1006
|
+
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
|
1007
|
+
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
|
1008
|
+
"engines": {
|
|
1009
|
+
"node": ">= 0.4"
|
|
1010
|
+
}
|
|
1011
|
+
},
|
|
948
1012
|
"node_modules/escape-html": {
|
|
949
1013
|
"version": "1.0.3",
|
|
950
1014
|
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
|
@@ -1222,16 +1286,16 @@
|
|
|
1222
1286
|
}
|
|
1223
1287
|
},
|
|
1224
1288
|
"node_modules/express": {
|
|
1225
|
-
"version": "4.
|
|
1226
|
-
"resolved": "https://registry.npmjs.org/express/-/express-4.
|
|
1227
|
-
"integrity": "sha512-
|
|
1289
|
+
"version": "4.19.2",
|
|
1290
|
+
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
|
|
1291
|
+
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
|
|
1228
1292
|
"dependencies": {
|
|
1229
1293
|
"accepts": "~1.3.8",
|
|
1230
1294
|
"array-flatten": "1.1.1",
|
|
1231
|
-
"body-parser": "1.20.
|
|
1295
|
+
"body-parser": "1.20.2",
|
|
1232
1296
|
"content-disposition": "0.5.4",
|
|
1233
1297
|
"content-type": "~1.0.4",
|
|
1234
|
-
"cookie": "0.
|
|
1298
|
+
"cookie": "0.6.0",
|
|
1235
1299
|
"cookie-signature": "1.0.6",
|
|
1236
1300
|
"debug": "2.6.9",
|
|
1237
1301
|
"depd": "2.0.0",
|
|
@@ -1288,57 +1352,6 @@
|
|
|
1288
1352
|
"node": ">= 0.6"
|
|
1289
1353
|
}
|
|
1290
1354
|
},
|
|
1291
|
-
"node_modules/express/node_modules/body-parser": {
|
|
1292
|
-
"version": "1.20.1",
|
|
1293
|
-
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
|
|
1294
|
-
"integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
|
|
1295
|
-
"dependencies": {
|
|
1296
|
-
"bytes": "3.1.2",
|
|
1297
|
-
"content-type": "~1.0.4",
|
|
1298
|
-
"debug": "2.6.9",
|
|
1299
|
-
"depd": "2.0.0",
|
|
1300
|
-
"destroy": "1.2.0",
|
|
1301
|
-
"http-errors": "2.0.0",
|
|
1302
|
-
"iconv-lite": "0.4.24",
|
|
1303
|
-
"on-finished": "2.4.1",
|
|
1304
|
-
"qs": "6.11.0",
|
|
1305
|
-
"raw-body": "2.5.1",
|
|
1306
|
-
"type-is": "~1.6.18",
|
|
1307
|
-
"unpipe": "1.0.0"
|
|
1308
|
-
},
|
|
1309
|
-
"engines": {
|
|
1310
|
-
"node": ">= 0.8",
|
|
1311
|
-
"npm": "1.2.8000 || >= 1.4.16"
|
|
1312
|
-
}
|
|
1313
|
-
},
|
|
1314
|
-
"node_modules/express/node_modules/qs": {
|
|
1315
|
-
"version": "6.11.0",
|
|
1316
|
-
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
|
1317
|
-
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
|
1318
|
-
"dependencies": {
|
|
1319
|
-
"side-channel": "^1.0.4"
|
|
1320
|
-
},
|
|
1321
|
-
"engines": {
|
|
1322
|
-
"node": ">=0.6"
|
|
1323
|
-
},
|
|
1324
|
-
"funding": {
|
|
1325
|
-
"url": "https://github.com/sponsors/ljharb"
|
|
1326
|
-
}
|
|
1327
|
-
},
|
|
1328
|
-
"node_modules/express/node_modules/raw-body": {
|
|
1329
|
-
"version": "2.5.1",
|
|
1330
|
-
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
|
|
1331
|
-
"integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
|
|
1332
|
-
"dependencies": {
|
|
1333
|
-
"bytes": "3.1.2",
|
|
1334
|
-
"http-errors": "2.0.0",
|
|
1335
|
-
"iconv-lite": "0.4.24",
|
|
1336
|
-
"unpipe": "1.0.0"
|
|
1337
|
-
},
|
|
1338
|
-
"engines": {
|
|
1339
|
-
"node": ">= 0.8"
|
|
1340
|
-
}
|
|
1341
|
-
},
|
|
1342
1355
|
"node_modules/fast-deep-equal": {
|
|
1343
1356
|
"version": "3.1.3",
|
|
1344
1357
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
|
@@ -1477,9 +1490,9 @@
|
|
|
1477
1490
|
"dev": true
|
|
1478
1491
|
},
|
|
1479
1492
|
"node_modules/follow-redirects": {
|
|
1480
|
-
"version": "1.15.
|
|
1481
|
-
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.
|
|
1482
|
-
"integrity": "sha512-
|
|
1493
|
+
"version": "1.15.6",
|
|
1494
|
+
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
|
1495
|
+
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
|
|
1483
1496
|
"funding": [
|
|
1484
1497
|
{
|
|
1485
1498
|
"type": "individual",
|
|
@@ -1531,19 +1544,26 @@
|
|
|
1531
1544
|
"dev": true
|
|
1532
1545
|
},
|
|
1533
1546
|
"node_modules/function-bind": {
|
|
1534
|
-
"version": "1.1.
|
|
1535
|
-
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.
|
|
1536
|
-
"integrity": "sha512-
|
|
1547
|
+
"version": "1.1.2",
|
|
1548
|
+
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
|
1549
|
+
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
|
1550
|
+
"funding": {
|
|
1551
|
+
"url": "https://github.com/sponsors/ljharb"
|
|
1552
|
+
}
|
|
1537
1553
|
},
|
|
1538
1554
|
"node_modules/get-intrinsic": {
|
|
1539
|
-
"version": "1.2.
|
|
1540
|
-
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.
|
|
1541
|
-
"integrity": "sha512-
|
|
1555
|
+
"version": "1.2.4",
|
|
1556
|
+
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
|
1557
|
+
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
|
1542
1558
|
"dependencies": {
|
|
1543
|
-
"
|
|
1544
|
-
"
|
|
1559
|
+
"es-errors": "^1.3.0",
|
|
1560
|
+
"function-bind": "^1.1.2",
|
|
1545
1561
|
"has-proto": "^1.0.1",
|
|
1546
|
-
"has-symbols": "^1.0.3"
|
|
1562
|
+
"has-symbols": "^1.0.3",
|
|
1563
|
+
"hasown": "^2.0.0"
|
|
1564
|
+
},
|
|
1565
|
+
"engines": {
|
|
1566
|
+
"node": ">= 0.4"
|
|
1547
1567
|
},
|
|
1548
1568
|
"funding": {
|
|
1549
1569
|
"url": "https://github.com/sponsors/ljharb"
|
|
@@ -1616,6 +1636,17 @@
|
|
|
1616
1636
|
"url": "https://github.com/sponsors/sindresorhus"
|
|
1617
1637
|
}
|
|
1618
1638
|
},
|
|
1639
|
+
"node_modules/gopd": {
|
|
1640
|
+
"version": "1.0.1",
|
|
1641
|
+
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
|
1642
|
+
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
|
1643
|
+
"dependencies": {
|
|
1644
|
+
"get-intrinsic": "^1.1.3"
|
|
1645
|
+
},
|
|
1646
|
+
"funding": {
|
|
1647
|
+
"url": "https://github.com/sponsors/ljharb"
|
|
1648
|
+
}
|
|
1649
|
+
},
|
|
1619
1650
|
"node_modules/grapheme-splitter": {
|
|
1620
1651
|
"version": "1.0.4",
|
|
1621
1652
|
"resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
|
|
@@ -1628,17 +1659,6 @@
|
|
|
1628
1659
|
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
|
|
1629
1660
|
"dev": true
|
|
1630
1661
|
},
|
|
1631
|
-
"node_modules/has": {
|
|
1632
|
-
"version": "1.0.3",
|
|
1633
|
-
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
|
1634
|
-
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
|
1635
|
-
"dependencies": {
|
|
1636
|
-
"function-bind": "^1.1.1"
|
|
1637
|
-
},
|
|
1638
|
-
"engines": {
|
|
1639
|
-
"node": ">= 0.4.0"
|
|
1640
|
-
}
|
|
1641
|
-
},
|
|
1642
1662
|
"node_modules/has-flag": {
|
|
1643
1663
|
"version": "4.0.0",
|
|
1644
1664
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
|
@@ -1648,10 +1668,21 @@
|
|
|
1648
1668
|
"node": ">=8"
|
|
1649
1669
|
}
|
|
1650
1670
|
},
|
|
1671
|
+
"node_modules/has-property-descriptors": {
|
|
1672
|
+
"version": "1.0.2",
|
|
1673
|
+
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
|
1674
|
+
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
|
1675
|
+
"dependencies": {
|
|
1676
|
+
"es-define-property": "^1.0.0"
|
|
1677
|
+
},
|
|
1678
|
+
"funding": {
|
|
1679
|
+
"url": "https://github.com/sponsors/ljharb"
|
|
1680
|
+
}
|
|
1681
|
+
},
|
|
1651
1682
|
"node_modules/has-proto": {
|
|
1652
|
-
"version": "1.0.
|
|
1653
|
-
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.
|
|
1654
|
-
"integrity": "sha512-
|
|
1683
|
+
"version": "1.0.3",
|
|
1684
|
+
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
|
|
1685
|
+
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
|
|
1655
1686
|
"engines": {
|
|
1656
1687
|
"node": ">= 0.4"
|
|
1657
1688
|
},
|
|
@@ -1670,6 +1701,17 @@
|
|
|
1670
1701
|
"url": "https://github.com/sponsors/ljharb"
|
|
1671
1702
|
}
|
|
1672
1703
|
},
|
|
1704
|
+
"node_modules/hasown": {
|
|
1705
|
+
"version": "2.0.2",
|
|
1706
|
+
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
|
1707
|
+
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
|
1708
|
+
"dependencies": {
|
|
1709
|
+
"function-bind": "^1.1.2"
|
|
1710
|
+
},
|
|
1711
|
+
"engines": {
|
|
1712
|
+
"node": ">= 0.4"
|
|
1713
|
+
}
|
|
1714
|
+
},
|
|
1673
1715
|
"node_modules/http-errors": {
|
|
1674
1716
|
"version": "2.0.0",
|
|
1675
1717
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
|
@@ -1979,9 +2021,9 @@
|
|
|
1979
2021
|
}
|
|
1980
2022
|
},
|
|
1981
2023
|
"node_modules/object-inspect": {
|
|
1982
|
-
"version": "1.
|
|
1983
|
-
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.
|
|
1984
|
-
"integrity": "sha512-
|
|
2024
|
+
"version": "1.13.1",
|
|
2025
|
+
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
|
|
2026
|
+
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
|
|
1985
2027
|
"funding": {
|
|
1986
2028
|
"url": "https://github.com/sponsors/ljharb"
|
|
1987
2029
|
}
|
|
@@ -2236,6 +2278,20 @@
|
|
|
2236
2278
|
"node": ">=6"
|
|
2237
2279
|
}
|
|
2238
2280
|
},
|
|
2281
|
+
"node_modules/qs": {
|
|
2282
|
+
"version": "6.11.0",
|
|
2283
|
+
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
|
2284
|
+
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
|
2285
|
+
"dependencies": {
|
|
2286
|
+
"side-channel": "^1.0.4"
|
|
2287
|
+
},
|
|
2288
|
+
"engines": {
|
|
2289
|
+
"node": ">=0.6"
|
|
2290
|
+
},
|
|
2291
|
+
"funding": {
|
|
2292
|
+
"url": "https://github.com/sponsors/ljharb"
|
|
2293
|
+
}
|
|
2294
|
+
},
|
|
2239
2295
|
"node_modules/queue-microtask": {
|
|
2240
2296
|
"version": "1.2.3",
|
|
2241
2297
|
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
|
@@ -2272,6 +2328,20 @@
|
|
|
2272
2328
|
"node": ">= 0.6"
|
|
2273
2329
|
}
|
|
2274
2330
|
},
|
|
2331
|
+
"node_modules/raw-body": {
|
|
2332
|
+
"version": "2.5.2",
|
|
2333
|
+
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
|
|
2334
|
+
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
|
|
2335
|
+
"dependencies": {
|
|
2336
|
+
"bytes": "3.1.2",
|
|
2337
|
+
"http-errors": "2.0.0",
|
|
2338
|
+
"iconv-lite": "0.4.24",
|
|
2339
|
+
"unpipe": "1.0.0"
|
|
2340
|
+
},
|
|
2341
|
+
"engines": {
|
|
2342
|
+
"node": ">= 0.8"
|
|
2343
|
+
}
|
|
2344
|
+
},
|
|
2275
2345
|
"node_modules/resolve-from": {
|
|
2276
2346
|
"version": "4.0.0",
|
|
2277
2347
|
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
|
@@ -2410,6 +2480,22 @@
|
|
|
2410
2480
|
"node": ">= 0.8.0"
|
|
2411
2481
|
}
|
|
2412
2482
|
},
|
|
2483
|
+
"node_modules/set-function-length": {
|
|
2484
|
+
"version": "1.2.2",
|
|
2485
|
+
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
|
2486
|
+
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
|
2487
|
+
"dependencies": {
|
|
2488
|
+
"define-data-property": "^1.1.4",
|
|
2489
|
+
"es-errors": "^1.3.0",
|
|
2490
|
+
"function-bind": "^1.1.2",
|
|
2491
|
+
"get-intrinsic": "^1.2.4",
|
|
2492
|
+
"gopd": "^1.0.1",
|
|
2493
|
+
"has-property-descriptors": "^1.0.2"
|
|
2494
|
+
},
|
|
2495
|
+
"engines": {
|
|
2496
|
+
"node": ">= 0.4"
|
|
2497
|
+
}
|
|
2498
|
+
},
|
|
2413
2499
|
"node_modules/setprototypeof": {
|
|
2414
2500
|
"version": "1.2.0",
|
|
2415
2501
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
|
@@ -2437,13 +2523,17 @@
|
|
|
2437
2523
|
}
|
|
2438
2524
|
},
|
|
2439
2525
|
"node_modules/side-channel": {
|
|
2440
|
-
"version": "1.0.
|
|
2441
|
-
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.
|
|
2442
|
-
"integrity": "sha512-
|
|
2526
|
+
"version": "1.0.6",
|
|
2527
|
+
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
|
|
2528
|
+
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
|
|
2443
2529
|
"dependencies": {
|
|
2444
|
-
"call-bind": "^1.0.
|
|
2445
|
-
"
|
|
2446
|
-
"
|
|
2530
|
+
"call-bind": "^1.0.7",
|
|
2531
|
+
"es-errors": "^1.3.0",
|
|
2532
|
+
"get-intrinsic": "^1.2.4",
|
|
2533
|
+
"object-inspect": "^1.13.1"
|
|
2534
|
+
},
|
|
2535
|
+
"engines": {
|
|
2536
|
+
"node": ">= 0.4"
|
|
2447
2537
|
},
|
|
2448
2538
|
"funding": {
|
|
2449
2539
|
"url": "https://github.com/sponsors/ljharb"
|
package/sample/package.json
CHANGED
package/src/strategy.ts
CHANGED
|
@@ -66,12 +66,23 @@ export class SteamOpenIdStrategy<
|
|
|
66
66
|
*/
|
|
67
67
|
protected verify?: VerifyCallback<TUser>;
|
|
68
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Optional setting for validating nonce time delay,
|
|
71
|
+
* in seconds.
|
|
72
|
+
*
|
|
73
|
+
* Measures time between nonce creation date and verification.
|
|
74
|
+
*/
|
|
75
|
+
protected maxNonceTimeDelay: number | undefined;
|
|
76
|
+
|
|
69
77
|
/**
|
|
70
78
|
* @constructor
|
|
71
79
|
*
|
|
72
80
|
* @param options.returnURL where steam redirects after parameters are passed
|
|
73
81
|
* @param options.profile if set, we will fetch user's profile from steam api
|
|
74
82
|
* @param options.apiKey api key to fetch user profile, not used if profile is false
|
|
83
|
+
* @param options.maxNonceTimeDelay optional setting for validating nonce time delay,
|
|
84
|
+
* this is just an extra security measure, it is not required nor recommended, but
|
|
85
|
+
* might be extra layer of security you want to have.
|
|
75
86
|
* @param verify optional callback, called when user is successfully authenticated
|
|
76
87
|
*/
|
|
77
88
|
constructor(options: TOptions, verify?: VerifyCallback<TUser>) {
|
|
@@ -81,6 +92,7 @@ export class SteamOpenIdStrategy<
|
|
|
81
92
|
this.axios = axios.create();
|
|
82
93
|
this.returnURL = options.returnURL;
|
|
83
94
|
this.profile = options.profile;
|
|
95
|
+
this.maxNonceTimeDelay = options.maxNonceTimeDelay;
|
|
84
96
|
if (options.profile) this.apiKey = options.apiKey;
|
|
85
97
|
if (verify) this.verify = verify;
|
|
86
98
|
}
|
|
@@ -151,7 +163,12 @@ export class SteamOpenIdStrategy<
|
|
|
151
163
|
);
|
|
152
164
|
}
|
|
153
165
|
|
|
154
|
-
|
|
166
|
+
if (this.hasNonceExpired(query)) {
|
|
167
|
+
throw new SteamOpenIdError(
|
|
168
|
+
'Nonce time delay was too big.',
|
|
169
|
+
SteamOpenIdErrorType.NonceExpired,
|
|
170
|
+
);
|
|
171
|
+
}
|
|
155
172
|
|
|
156
173
|
const valid = await this.validateAgainstSteam(query);
|
|
157
174
|
if (!valid) {
|
|
@@ -165,6 +182,24 @@ export class SteamOpenIdStrategy<
|
|
|
165
182
|
return await this.getUser(steamId);
|
|
166
183
|
}
|
|
167
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Check if nonce date has expired against current delay setting,
|
|
187
|
+
* if no setting was set, then it is considered as not expired.
|
|
188
|
+
*
|
|
189
|
+
* @param nonceDate date when nonce was created
|
|
190
|
+
* @returns true, if nonce has expired and error should be thrown
|
|
191
|
+
*/
|
|
192
|
+
protected hasNonceExpired(query: SteamOpenIdQuery): boolean {
|
|
193
|
+
if (typeof this.maxNonceTimeDelay == 'undefined') {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const nonceDate = new Date(query['openid.response_nonce'].slice(0, 20));
|
|
198
|
+
const nonceSeconds = Math.floor(nonceDate.getTime() / 1000);
|
|
199
|
+
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
200
|
+
return nowSeconds - nonceSeconds > this.maxNonceTimeDelay;
|
|
201
|
+
}
|
|
202
|
+
|
|
168
203
|
/**
|
|
169
204
|
* Checks if error is retryable,
|
|
170
205
|
* meaning user gets redirected to steam openid page.
|
package/src/type.ts
CHANGED
|
@@ -2,6 +2,16 @@ import { DoneCallback } from 'passport';
|
|
|
2
2
|
|
|
3
3
|
export type BaseSteamOpenIdStrategyOptions = {
|
|
4
4
|
returnURL: string;
|
|
5
|
+
/**
|
|
6
|
+
* Maximum time delay between the nonce creation and the nonce verification,
|
|
7
|
+
* in seconds.
|
|
8
|
+
*
|
|
9
|
+
* nonce includes a timestamp we can validate against the current time,
|
|
10
|
+
* while the steam server validates this as well, you might want to
|
|
11
|
+
* set maximum number of seconds between the nonce creation and the nonce
|
|
12
|
+
* verification.
|
|
13
|
+
*/
|
|
14
|
+
maxNonceTimeDelay?: number;
|
|
5
15
|
};
|
|
6
16
|
|
|
7
17
|
export type SteamOpenIdStrategyOptionsWithProfile = {
|
|
@@ -39,6 +49,10 @@ export enum SteamOpenIdErrorType {
|
|
|
39
49
|
* SteamId is not valid.
|
|
40
50
|
*/
|
|
41
51
|
InvalidSteamId = 3,
|
|
52
|
+
/**
|
|
53
|
+
* Nonce has expired.
|
|
54
|
+
*/
|
|
55
|
+
NonceExpired = 4,
|
|
42
56
|
}
|
|
43
57
|
|
|
44
58
|
/** When profile is not used, we just send a steamid. */
|
package/test/setup/data.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
SteamOpenIdQuery,
|
|
3
|
+
VALID_NONCE,
|
|
4
|
+
VALID_OPENID_ENDPOINT,
|
|
5
|
+
} from '../../src';
|
|
2
6
|
|
|
3
7
|
export const RETURN_URL = '/auth/steam';
|
|
4
8
|
|
|
9
|
+
export const getISODate = (date: Date) => date.toISOString().split('.')[0] + 'Z';
|
|
10
|
+
|
|
5
11
|
export const query: {
|
|
6
|
-
properties:
|
|
7
|
-
get():
|
|
8
|
-
change(change:
|
|
9
|
-
remove(property:
|
|
12
|
+
properties: SteamOpenIdQuery;
|
|
13
|
+
get(): SteamOpenIdQuery;
|
|
14
|
+
change(change: Partial<SteamOpenIdQuery>): SteamOpenIdQuery;
|
|
15
|
+
remove(property: keyof SteamOpenIdQuery): SteamOpenIdQuery;
|
|
10
16
|
} = {
|
|
11
17
|
/**
|
|
12
18
|
* Valid query properties
|
|
@@ -18,22 +24,22 @@ export const query: {
|
|
|
18
24
|
'openid.claimed_id': `https://steamcommunity.com/openid/id/76561197960435530`,
|
|
19
25
|
'openid.return_to': RETURN_URL,
|
|
20
26
|
'openid.op_endpoint': VALID_OPENID_ENDPOINT,
|
|
21
|
-
'openid.response_nonce': `${new Date()
|
|
27
|
+
'openid.response_nonce': `${getISODate(new Date())}8df86bac92ad1addaf3735a5aabdc6e2a7`,
|
|
22
28
|
'openid.assoc_handle': '1234567890',
|
|
23
29
|
'openid.signed':
|
|
24
30
|
'signed,op_endpoint,claimed_id,identity,return_to,response_nonce,assoc_handle',
|
|
25
31
|
'openid.sig': 'dc6e2a79de2c6aceac495ad5f4c6b6e0bfe30',
|
|
26
32
|
},
|
|
27
33
|
|
|
28
|
-
get() {
|
|
34
|
+
get(): SteamOpenIdQuery {
|
|
29
35
|
return { ...this.properties };
|
|
30
36
|
},
|
|
31
37
|
|
|
32
|
-
change(change:
|
|
38
|
+
change(change: Partial<SteamOpenIdQuery>): SteamOpenIdQuery {
|
|
33
39
|
return { ...this.get(), ...change };
|
|
34
40
|
},
|
|
35
41
|
|
|
36
|
-
remove(property:
|
|
42
|
+
remove(property: keyof SteamOpenIdQuery): SteamOpenIdQuery {
|
|
37
43
|
const properties = this.get();
|
|
38
44
|
delete properties[property];
|
|
39
45
|
return properties;
|
package/test/strategy.ts
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
VALID_OPENID_ENDPOINT,
|
|
16
16
|
PLAYER_SUMMARY_URL,
|
|
17
17
|
} from '../src';
|
|
18
|
-
import { RETURN_URL, query } from './setup/data';
|
|
18
|
+
import { RETURN_URL, getISODate, query } from './setup/data';
|
|
19
19
|
|
|
20
20
|
chai.use(chaiAsPromised);
|
|
21
21
|
|
|
@@ -214,12 +214,14 @@ describe('SteamOpenIdStrategy Unit Test', () => {
|
|
|
214
214
|
let getQueryStub: sinon.SinonStub;
|
|
215
215
|
let hasAuthQueryStub: sinon.SinonStub;
|
|
216
216
|
let isQueryValidStub: sinon.SinonStub;
|
|
217
|
+
let hasNonceExpiredStub: sinon.SinonStub;
|
|
217
218
|
let validateAgainstSteamStub: sinon.SinonStub;
|
|
218
219
|
|
|
219
220
|
beforeEach(() => {
|
|
220
221
|
getQueryStub = sinon.stub(strategy as any, 'getQuery').returns(query);
|
|
221
222
|
hasAuthQueryStub = sinon.stub(strategy as any, 'hasAuthQuery');
|
|
222
223
|
isQueryValidStub = sinon.stub(strategy as any, 'isQueryValid');
|
|
224
|
+
hasNonceExpiredStub = sinon.stub(strategy as any, 'hasNonceExpired');
|
|
223
225
|
validateAgainstSteamStub = sinon.stub(
|
|
224
226
|
strategy as any,
|
|
225
227
|
'validateAgainstSteam',
|
|
@@ -237,6 +239,7 @@ describe('SteamOpenIdStrategy Unit Test', () => {
|
|
|
237
239
|
hasAuthQueryStub.returns(true);
|
|
238
240
|
isQueryValidStub.returns(true);
|
|
239
241
|
validateAgainstSteamStub.resolves(true);
|
|
242
|
+
hasNonceExpiredStub.returns(false);
|
|
240
243
|
|
|
241
244
|
const steamid = '76561197960435530';
|
|
242
245
|
const user = { steamid: '76561197960435530' };
|
|
@@ -253,6 +256,8 @@ describe('SteamOpenIdStrategy Unit Test', () => {
|
|
|
253
256
|
expect(getUserStub.calledWithExactly(steamid)).equal(true);
|
|
254
257
|
expect(isQueryValidStub.callCount).equal(1);
|
|
255
258
|
expect(isQueryValidStub.calledWithExactly(query)).equal(true);
|
|
259
|
+
expect(hasNonceExpiredStub.callCount).equal(1);
|
|
260
|
+
expect(hasNonceExpiredStub.calledWithExactly(query)).equal(true);
|
|
256
261
|
expect(validateAgainstSteamStub.callCount).equal(1);
|
|
257
262
|
expect(validateAgainstSteamStub.calledWithExactly(query)).equal(true);
|
|
258
263
|
});
|
|
@@ -269,6 +274,9 @@ describe('SteamOpenIdStrategy Unit Test', () => {
|
|
|
269
274
|
|
|
270
275
|
expect(err).to.be.instanceOf(SteamOpenIdError);
|
|
271
276
|
expect(err).to.have.property('code', SteamOpenIdErrorType.InvalidMode);
|
|
277
|
+
expect(isQueryValidStub.callCount).equal(0);
|
|
278
|
+
expect(hasNonceExpiredStub.callCount).equal(0);
|
|
279
|
+
expect(validateAgainstSteamStub.callCount).equal(0);
|
|
272
280
|
});
|
|
273
281
|
|
|
274
282
|
it('Query is invalid', async () => {
|
|
@@ -286,11 +294,35 @@ describe('SteamOpenIdStrategy Unit Test', () => {
|
|
|
286
294
|
expect(err).to.have.property('code', SteamOpenIdErrorType.InvalidQuery);
|
|
287
295
|
expect(isQueryValidStub.callCount).equal(1);
|
|
288
296
|
expect(isQueryValidStub.calledWithExactly(query)).equal(true);
|
|
297
|
+
expect(hasNonceExpiredStub.callCount).equal(0);
|
|
298
|
+
expect(validateAgainstSteamStub.callCount).equal(0);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it('Nonce has expired', async () => {
|
|
302
|
+
hasAuthQueryStub.returns(true);
|
|
303
|
+
isQueryValidStub.returns(true);
|
|
304
|
+
hasNonceExpiredStub.returns(true);
|
|
305
|
+
|
|
306
|
+
let err: any;
|
|
307
|
+
try {
|
|
308
|
+
await strategy.handleRequest(request);
|
|
309
|
+
} catch (e) {
|
|
310
|
+
err = e;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
expect(err).to.be.instanceOf(SteamOpenIdError);
|
|
314
|
+
expect(err).to.have.property('code', SteamOpenIdErrorType.NonceExpired);
|
|
315
|
+
expect(isQueryValidStub.callCount).equal(1);
|
|
316
|
+
expect(isQueryValidStub.calledWithExactly(query)).equal(true);
|
|
317
|
+
expect(hasNonceExpiredStub.callCount).equal(1);
|
|
318
|
+
expect(hasNonceExpiredStub.calledWithExactly(query)).equal(true);
|
|
319
|
+
expect(validateAgainstSteamStub.callCount).equal(0);
|
|
289
320
|
});
|
|
290
321
|
|
|
291
322
|
it('Steam rejects this authentication request', async () => {
|
|
292
323
|
hasAuthQueryStub.returns(true);
|
|
293
324
|
isQueryValidStub.returns(true);
|
|
325
|
+
hasNonceExpiredStub.returns(false);
|
|
294
326
|
validateAgainstSteamStub.resolves(false);
|
|
295
327
|
|
|
296
328
|
let err: any;
|
|
@@ -304,6 +336,8 @@ describe('SteamOpenIdStrategy Unit Test', () => {
|
|
|
304
336
|
expect(err).to.have.property('code', SteamOpenIdErrorType.Unauthorized);
|
|
305
337
|
expect(isQueryValidStub.callCount).equal(1);
|
|
306
338
|
expect(isQueryValidStub.calledWithExactly(query)).equal(true);
|
|
339
|
+
expect(hasNonceExpiredStub.callCount).equal(1);
|
|
340
|
+
expect(hasNonceExpiredStub.calledWithExactly(query)).equal(true);
|
|
307
341
|
expect(validateAgainstSteamStub.callCount).equal(1);
|
|
308
342
|
expect(validateAgainstSteamStub.calledWithExactly(query)).equal(true);
|
|
309
343
|
});
|
|
@@ -722,4 +756,40 @@ describe('SteamOpenIdStrategy Unit Test', () => {
|
|
|
722
756
|
expect(err).to.have.property('code', SteamOpenIdErrorType.InvalidSteamId);
|
|
723
757
|
});
|
|
724
758
|
});
|
|
759
|
+
|
|
760
|
+
describe('hasNonceExpired', () => {
|
|
761
|
+
const HOUR = 1000 * 60 * 60;
|
|
762
|
+
|
|
763
|
+
it('No setting set, could not expire', () => {
|
|
764
|
+
expect(strategy['hasNonceExpired'](query.properties)).equal(false);
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
it('Setting set, nonce expired', () => {
|
|
768
|
+
strategy['maxNonceTimeDelay'] = HOUR / 1000;
|
|
769
|
+
|
|
770
|
+
expect(
|
|
771
|
+
strategy['hasNonceExpired'](
|
|
772
|
+
query.change({
|
|
773
|
+
'openid.response_nonce': `${getISODate(
|
|
774
|
+
new Date(Date.now() - 2 * HOUR),
|
|
775
|
+
)}8df86bac92ad1addaf3735a5aabdc6e2a7`,
|
|
776
|
+
}),
|
|
777
|
+
),
|
|
778
|
+
).equal(true);
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
it('Setting set, nonce not expired', () => {
|
|
782
|
+
strategy['maxNonceTimeDelay'] = HOUR / 1000;
|
|
783
|
+
|
|
784
|
+
expect(
|
|
785
|
+
strategy['hasNonceExpired'](
|
|
786
|
+
query.change({
|
|
787
|
+
'openid.response_nonce': `${getISODate(
|
|
788
|
+
new Date(Date.now() + HOUR / 2),
|
|
789
|
+
)}8df86bac92ad1addaf3735a5aabdc6e2a7`,
|
|
790
|
+
}),
|
|
791
|
+
),
|
|
792
|
+
).equal(false);
|
|
793
|
+
});
|
|
794
|
+
});
|
|
725
795
|
});
|