Skip to content

Commit 610d60f

Browse files
authored
Update secure-websocket-js.md
add js code snippet
1 parent 72bef4d commit 610d60f

File tree

1 file changed

+71
-37
lines changed

1 file changed

+71
-37
lines changed

articles/communication-services/how-tos/call-automation/includes/secure-websocket-js.md

Lines changed: 71 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,53 +16,87 @@ ms.author: kpunjabi
1616
This sample code demonstrates how to configure OIDC client to validate webhook payload using JWT
1717

1818
```JavaScript
19-
import express from "express";
19+
import { createServer } from "http";
20+
import WebSocket from "ws";
2021
import { JwksClient } from "jwks-rsa";
2122
import { verify } from "jsonwebtoken";
22-
23-
const app = express();
23+
import url from "url";
24+
2425
const port = 3000;
2526
const audience = "ACS resource ID";
2627
const issuer = "https://acscallautomation.communication.azure.com";
27-
28-
app.use(express.json());
29-
30-
app.post("/api/callback", (req, res) => {
31-
const token = req?.headers?.authorization?.split(" ")[1] || "";
32-
33-
if (!token) {
34-
res.sendStatus(401);
35-
36-
return;
37-
}
38-
39-
try {
28+
const jwksUri = `${issuer}/calling/keys`;
29+
30+
const server = createServer();
31+
const wss = new WebSocket.Server({ noServer: true });
32+
33+
const jwksClient = new JwksClient({ jwksUri });
34+
35+
function verifyToken(token: string): Promise<any> {
36+
return new Promise((resolve, reject) => {
4037
verify(
4138
token,
42-
(header, callback) => {
43-
const client = new JwksClient({
44-
jwksUri: "https://acscallautomation.communication.azure.com/calling/keys",
45-
});
46-
47-
client.getSigningKey(header.kid, (err, key) => {
48-
const signingKey = key?.publicKey || key?.rsaPublicKey;
49-
50-
callback(err, signingKey);
39+
(header, cb) => {
40+
jwksClient.getSigningKey(header.kid, (err, key) => {
41+
const signingKey = key?.getPublicKey();
42+
cb(err, signingKey);
5143
});
5244
},
53-
{
54-
audience,
55-
issuer,
56-
algorithms: ["RS256"],
57-
});
58-
// Your implementation on the callback event
59-
res.sendStatus(200);
60-
} catch (error) {
61-
res.sendStatus(401);
45+
{ audience, issuer, algorithms: ["RS256"] },
46+
(err, decoded) => (err ? reject(err) : resolve(decoded))
47+
);
48+
});
49+
}
50+
51+
// Upgrade HTTP to WebSocket only if token is valid
52+
server.on("upgrade", async (req, socket, head) => {
53+
const tokenHeader = req.headers["authorization"];
54+
const token = tokenHeader?.toString().split(" ")[1];
55+
56+
if (!token) {
57+
socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n");
58+
socket.destroy();
59+
return;
60+
}
61+
62+
try {
63+
const decoded = await verifyToken(token);
64+
(req as any).user = decoded;
65+
66+
wss.handleUpgrade(req, socket, head, (ws) => {
67+
wss.emit("connection", ws, req);
68+
});
69+
} catch (e) {
70+
console.error("WebSocket token validation failed:", e);
71+
socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n");
72+
socket.destroy();
6273
}
6374
});
64-
65-
app.listen(port, () => {
66-
console.log(`Server running on port ${port}`);
75+
76+
// Handle accepted WebSocket connections
77+
wss.on("connection", async (ws: WebSocket, req) => {
78+
const user = (req as any).user;
79+
console.log("Authenticated WebSocket connection from:", user);
80+
81+
await initWebsocket(ws);
82+
await startConversation();
83+
84+
ws.on("message", async (packetData: ArrayBuffer) => {
85+
try {
86+
if (ws.readyState === WebSocket.OPEN) {
87+
await processWebsocketMessageAsync(packetData);
88+
}
89+
} catch (err) {
90+
1. console.error("WebSocket message error:", err);
91+
}
92+
});
93+
94+
ws.on("close", () => {
95+
console.log("WebSocket connection closed");
96+
});
97+
});
98+
99+
server.listen(port, () => {
100+
console.log(`WebSocket server running on port ${port}`);
67101
});
68102
```

0 commit comments

Comments
 (0)