|
| 1 | +--- |
| 2 | +title: include file |
| 3 | +description: Python websocket callback security |
| 4 | +services: azure-communication-services |
| 5 | +author: Kunaal Punjabi |
| 6 | +ms.service: azure-communication-services |
| 7 | +ms.subservice: azure-communication-services |
| 8 | +ms.date: 05/06/2025 |
| 9 | +ms.topic: include |
| 10 | +ms.topic: include file |
| 11 | +ms.author: kpunjabi |
| 12 | +--- |
| 13 | + |
| 14 | +## Websocket code sample |
| 15 | + |
| 16 | +This sample code demonstrates how to configure OIDC client to validate websocket payload using JWT |
| 17 | + |
| 18 | +```python |
| 19 | +from quart import Quart, websocket, abort, request import jwt from jwt import PyJWKClient, InvalidTokenError |
| 20 | +app = Quart(name) |
| 21 | +JWKS_URL = "https://acscallautomation.communication.azure.com/calling/keys" EXPECTED_ISSUER = "https://acscallautomation.communication.azure.com" EXPECTED_AUDIENCE = "ACS resource ID" # replace with actual audience |
| 22 | +async def validate_token(token: str): try: jwks_client = PyJWKClient(JWKS_URL) signing_key = jwks_client.get_signing_key_from_jwt(token).key |
| 23 | + decoded_token = jwt.decode( |
| 24 | + token, |
| 25 | + signing_key, |
| 26 | + algorithms=["RS256"], |
| 27 | + audience=EXPECTED_AUDIENCE, |
| 28 | + issuer=EXPECTED_ISSUER, |
| 29 | + ) |
| 30 | + |
| 31 | + return decoded_token # Could return claims if needed |
| 32 | +except InvalidTokenError: |
| 33 | + print("Token is invalid.") |
| 34 | + return None |
| 35 | +except Exception as e: |
| 36 | + print(f"Uncaught exception during token validation: {e}") |
| 37 | + return None |
| 38 | + |
| 39 | +@app.websocket("/ws") async def ws(): auth_header = websocket.headers.get("Authorization") |
| 40 | +if not auth_header or not auth_header.startswith("Bearer "): |
| 41 | + await websocket.close(code=4401, reason="Missing or invalid Authorization header") |
| 42 | + return |
| 43 | + |
| 44 | +token = auth_header.split(" ")[1] |
| 45 | + |
| 46 | +claims = await validate_token(token) |
| 47 | +if not claims: |
| 48 | + await websocket.close(code=4401, reason="Invalid token") |
| 49 | + return |
| 50 | + |
| 51 | +correlation_id = websocket.headers.get("x-ms-call-correlation-id", "not provided") |
| 52 | +call_connection_id = websocket.headers.get("x-ms-call-connection-id", "not provided") |
| 53 | +print(f"Authenticated WebSocket - Correlation ID: {correlation_id}") |
| 54 | +print(f"Authenticated WebSocket - CallConnection ID: {call_connection_id}") |
| 55 | + |
| 56 | +try: |
| 57 | + while True: |
| 58 | + message = await websocket.receive() |
| 59 | + print(f"Received: {message}") |
| 60 | + # TODO: process message |
| 61 | +except Exception as e: |
| 62 | + print(f"WebSocket closed: {e}") |
| 63 | + |
| 64 | +if name == "main": app.run() |
| 65 | + |
| 66 | +``` |
0 commit comments