diff --git a/samples/functions/csharp/aadchat/negotiate.cs b/samples/functions/csharp/aadchat/negotiate.cs index ea7ff9e75..007393a53 100644 --- a/samples/functions/csharp/aadchat/negotiate.cs +++ b/samples/functions/csharp/aadchat/negotiate.cs @@ -44,7 +44,7 @@ public static async Task Run( } else { - log.LogWarning("No x-ms-client-principal-name: " + req.Headers); + log.LogWarning("No x-ms-client-principal-name found in request headers."); return new UnauthorizedResult(); } } diff --git a/samples/javascript/scoreboard/src/server/app.ts b/samples/javascript/scoreboard/src/server/app.ts index dd16e3802..e445757ba 100644 --- a/samples/javascript/scoreboard/src/server/app.ts +++ b/samples/javascript/scoreboard/src/server/app.ts @@ -69,10 +69,6 @@ app.set('port', port) app.use(express.static(staticRoot)) app.use(handler.getMiddleware()) -app.get('/', function (req, res) { - res.sendFile(path.join(path.join(staticRoot, '/index.html'))) -}) - // return negotiate response to redirect websocket client to Azure Web PubSub service app.get('/negotiate', async (req, res) => { const userId = req.query.id as string diff --git a/samples/javascript/whiteboard/server.js b/samples/javascript/whiteboard/server.js index 5057d65db..7ec46bd02 100644 --- a/samples/javascript/whiteboard/server.js +++ b/samples/javascript/whiteboard/server.js @@ -74,10 +74,15 @@ app }); }) .post('/background/upload', async (req, res) => { + const file = req.files['file']; + const allowedMimeTypes = ['image/jpeg', 'image/png', 'image/gif']; + if (!allowedMimeTypes.includes(file.mimetype)) { + return res.status(400).send('Invalid file type.'); + } diagram.background = { id: Math.random().toString(36).substr(2, 8), - data: req.files['file'].data, - contentType: req.files['file'].mimetype + data: file.data, + contentType: file.mimetype }; await serviceClient.sendToAll({ name: 'updateBackground', @@ -87,6 +92,7 @@ app }) .get('/background/:id', (req, res) => { if (diagram.background && diagram.background.id === req.params.id) { + res.setHeader('Content-Disposition', 'attachment; filename="background"'); res.type(diagram.background.contentType); res.send(diagram.background.data); } else res.status(404).end(); diff --git a/samples/python/chatapp-microsoft-entra-id/server.py b/samples/python/chatapp-microsoft-entra-id/server.py index 82ed6d61c..3c4eb1bad 100644 --- a/samples/python/chatapp-microsoft-entra-id/server.py +++ b/samples/python/chatapp-microsoft-entra-id/server.py @@ -38,7 +38,7 @@ def handle_event(): elif request.method == 'POST': user_id = request.headers.get('ce-userid') if request.headers.get('ce-type') == 'azure.webpubsub.sys.connected': - return user_id + ' connected', 200 + return 'connected', 200 elif request.headers.get('ce-type') == 'azure.webpubsub.user.message': service.send_to_all(content_type="application/json", message={ 'from': user_id, diff --git a/samples/python/chatapp/server.py b/samples/python/chatapp/server.py index a187babf0..0dca55a46 100644 --- a/samples/python/chatapp/server.py +++ b/samples/python/chatapp/server.py @@ -1,6 +1,7 @@ import os import sys import json +import html from flask import ( Flask, @@ -53,13 +54,13 @@ def handle_event(): id_element = query.get('id') user_id = id_element[0] if id_element else None if user_id: - return {'userId': user_id}, 200 + return {'userId': html.escape(user_id)}, 200 return 'missing user id', 401 elif type == 'azure.webpubsub.sys.connected': - return user_id + ' connected', 200 + return 'connected', 200 elif type == 'azure.webpubsub.user.message': service.send_to_all(content_type="application/json", message={ - 'from': user_id, + 'from': html.escape(user_id), 'message': request.data.decode('UTF-8') }) return Response(status=204, content_type='text/plain') diff --git a/sdk/server-proxies/src/utils.ts b/sdk/server-proxies/src/utils.ts index e53ccfffa..bec0aca15 100644 --- a/sdk/server-proxies/src/utils.ts +++ b/sdk/server-proxies/src/utils.ts @@ -1,6 +1,7 @@ import { AbortSignalLike } from "@azure/abort-controller"; import { AzureKeyCredential } from "@azure/core-auth"; import { URL } from "url"; +import { randomBytes } from "crypto"; interface ParsedConnectionString { credential: AzureKeyCredential; @@ -49,7 +50,7 @@ export class PromiseCompletionSource { export class Guid { public static newGuid(): string { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { - const r = (Math.random() * 16) | 0; + const r = randomBytes(1)[0] % 16; const v = c === "x" ? r : (r & 0x3) | 0x8; return v.toString(16); }); diff --git a/sdk/webpubsub-socketio-extension/examples/chat-with-auth-passport/index.js b/sdk/webpubsub-socketio-extension/examples/chat-with-auth-passport/index.js index 1d7fb6fd6..2fddee417 100644 --- a/sdk/webpubsub-socketio-extension/examples/chat-with-auth-passport/index.js +++ b/sdk/webpubsub-socketio-extension/examples/chat-with-auth-passport/index.js @@ -4,6 +4,7 @@ const session = require("express-session"); const bodyParser = require("body-parser"); const passport = require("passport"); const LocalStrategy = require("passport-local").Strategy; +const RateLimit = require('express-rate-limit'); const { useAzureSocketIO, negotiate, usePassport, restorePassport } = require("@azure/web-pubsub-socket.io"); const wrap = middleware => (socket, next) => middleware(socket.request, {}, next); @@ -17,6 +18,11 @@ app.use(bodyParser.urlencoded({ extended: false })); app.use(passport.initialize()); app.use(passport.session()); +const limiter = RateLimit({ + windowMs: 15 * 60 * 1000, // 15 minutes + max: 100, // max 100 requests per windowMs +}); + const USERS = [ { id: 0, username: "john", password: "doe", age: 18 } ]; @@ -33,7 +39,7 @@ passport.use( }) ); -app.get("/", (req, res) => { +app.get("/", limiter, (req, res) => { const isAuthenticated = !!req.user; if (isAuthenticated) { console.log(`user is authenticated, session is ${req.session.id}`); diff --git a/sdk/webpubsub-socketio-extension/examples/chat-with-auth-passport/package.json b/sdk/webpubsub-socketio-extension/examples/chat-with-auth-passport/package.json index a177a3e57..b149f038b 100644 --- a/sdk/webpubsub-socketio-extension/examples/chat-with-auth-passport/package.json +++ b/sdk/webpubsub-socketio-extension/examples/chat-with-auth-passport/package.json @@ -11,7 +11,8 @@ "express": "~4.17.1", "express-session": "^1.17.3", "passport": "^0.6.0", - "passport-local": "^1.0.0" + "passport-local": "^1.0.0", + "express-rate-limit": "^7.4.1" }, "scripts": { "start": "node index.js"