@runtypelabs/cli 1.2.0 → 1.3.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/dist/index.js +21 -2
- package/dist/index.js.map +1 -1
- package/package.json +4 -9
package/dist/index.js
CHANGED
|
@@ -151,6 +151,7 @@ var CallbackServer = class {
|
|
|
151
151
|
codeResolve;
|
|
152
152
|
codeReject;
|
|
153
153
|
codePromise;
|
|
154
|
+
expectedState;
|
|
154
155
|
constructor() {
|
|
155
156
|
this.app = express();
|
|
156
157
|
this.codePromise = new Promise((resolve, reject) => {
|
|
@@ -158,12 +159,23 @@ var CallbackServer = class {
|
|
|
158
159
|
this.codeReject = reject;
|
|
159
160
|
});
|
|
160
161
|
this.app.get("/callback", (req, res) => {
|
|
161
|
-
const { token, error } = req.query;
|
|
162
|
+
const { token, code, state, error } = req.query;
|
|
162
163
|
if (error) {
|
|
163
164
|
res.send(this.errorHTML(error));
|
|
164
165
|
this.codeReject(new Error(error));
|
|
165
166
|
return;
|
|
166
167
|
}
|
|
168
|
+
if (code) {
|
|
169
|
+
if (this.expectedState && state !== this.expectedState) {
|
|
170
|
+
res.send(this.errorHTML("State parameter mismatch - possible CSRF attack"));
|
|
171
|
+
this.codeReject(new Error("OAuth2 state parameter mismatch"));
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
res.send(this.successHTML());
|
|
175
|
+
this.codeResolve(code);
|
|
176
|
+
setTimeout(() => this.stop(), 1e3);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
167
179
|
if (!token) {
|
|
168
180
|
res.send(this.errorHTML("No authentication token received"));
|
|
169
181
|
this.codeReject(new Error("No authentication token received"));
|
|
@@ -177,6 +189,10 @@ var CallbackServer = class {
|
|
|
177
189
|
res.json({ status: "ok" });
|
|
178
190
|
});
|
|
179
191
|
}
|
|
192
|
+
/** Set expected state parameter for OAuth2 CSRF validation */
|
|
193
|
+
setExpectedState(state) {
|
|
194
|
+
this.expectedState = state;
|
|
195
|
+
}
|
|
180
196
|
async start(port = 8765) {
|
|
181
197
|
return new Promise((resolveStart, rejectStart) => {
|
|
182
198
|
this.server = this.app.listen(port, () => {
|
|
@@ -382,6 +398,9 @@ var CallbackServer = class {
|
|
|
382
398
|
</body>
|
|
383
399
|
</html>`;
|
|
384
400
|
}
|
|
401
|
+
escapeHtml(str) {
|
|
402
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
403
|
+
}
|
|
385
404
|
errorHTML(error) {
|
|
386
405
|
return `
|
|
387
406
|
<!DOCTYPE html>
|
|
@@ -440,7 +459,7 @@ var CallbackServer = class {
|
|
|
440
459
|
<div class="error-icon">\u2715</div>
|
|
441
460
|
<h1>Authentication Failed</h1>
|
|
442
461
|
<p>There was an error during authentication.</p>
|
|
443
|
-
<div class="error-details">${error}</div>
|
|
462
|
+
<div class="error-details">${this.escapeHtml(error)}</div>
|
|
444
463
|
</div>
|
|
445
464
|
</body>
|
|
446
465
|
</html>
|