Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Zabezpečení doručování zpráv od konce do konce je zásadní pro zajištění důvěrnosti, integrity a důvěryhodnosti citlivých informací přenášených mezi systémy. Vaše schopnost a ochota důvěřovat informacím přijatým ze vzdáleného systému závisí na tom, že odesílatel poskytne svoji identitu. Automatizace volání má dva způsoby komunikace událostí, které je možné zabezpečit; sdílenou událost IncomingCall odesílanou službou Azure Event Grid a všechny ostatní události volání uprostřed volání odesílané platformou Automatizace volání prostřednictvím webhooku.
Událost příchozího volání
Služba Azure Communication Services spoléhá na odběry služby Azure Event Grid k doručení události IncomingCall. Informace o zabezpečení předplatného webhooku najdete v týmu Azure Event Gridu.
Události webhooku služby Call Automation
Události automatizace volání se odesílají do webhook URI pro zpětné volání zadaného při přijetí hovoru nebo při uskutečňování nového odchozího hovoru. Identifikátor URI zpětného volání musí být veřejným koncovým bodem s platným certifikátem HTTPS, názvem DNS a IP adresou, se správně otevřenými porty brány firewall, aby k němu mohla služba automatizace volání přistupovat. Tento anonymní veřejný webový server může vytvořit bezpečnostní riziko, pokud neuděláte potřebné kroky k zabezpečení před neoprávněným přístupem.
Běžným způsobem, jak toto zabezpečení zlepšit, je implementace mechanismu KLÍČE rozhraní API. Váš webový server může klíč vygenerovat za běhu a poskytnout ho v identifikátoru URI zpětného volání jako parametr dotazu, když přijmete nebo vytvoříte volání. Váš webový server může před povolením přístupu ověřit klíč ve zpětném volání webhooku z Call Automation. Někteří zákazníci vyžadují větší bezpečnostní opatření. V těchto případech může hraniční síťové zařízení ověřit příchozí webhook odděleně od samotného webového serveru nebo aplikace. Samotný mechanismus klíče rozhraní API nemusí být dostatečný.
Vylepšení zabezpečení zpětného volání webhooku pro automatizované hovory
Každé zpětné volání webhooku během hovoru odeslané službou Call Automation používá podepsaný webový token JSON (JWT) v hlavičce ověřování příchozího požadavku HTTPS. K zajištění integrity tokenu můžete použít standardní techniky ověřování Open ID Connect (OIDC) JWT, jak je uvedeno dále. Životnost JWT je pět (5) minut a pro každou událost odesílanou do identifikátoru URI zpětného volání se vytvoří nový token.
- Získejte adresu URL konfigurace Open ID: https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
- Nainstalujte balíček NuGet Microsoft.AspNetCore.Authentication.JwtBearer .
- Nakonfigurujte aplikaci tak, aby ověřila JWT pomocí balíčku NuGet a konfigurace prostředku Azure Communication Services. Potřebujete hodnoty
audience
, které jsou přítomné v datové části JWT. - Ověřte vystavitele, cílovou skupinu a JWT.
- Cílová skupina je ID prostředku služby Azure Communication Services, které jste použili k nastavení klienta automatizace volání. Informace o tom, jak ho získat, najdete tady .
- Koncový bod sady webových klíčů JSON (JWKS) v konfiguraci OpenId obsahuje klíče použité k ověření JWT. Pokud je podpis platný a platnost tokenu nevypršela (do 5 minut od generování), klient může token použít k autorizaci.
Tento ukázkový kód ukazuje, jak použít Microsoft.IdentityModel.Protocols.OpenIdConnect
k ověření payloadu webhooku.
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Add Azure Communication Services CallAutomation OpenID configuration
var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
builder.Configuration["OpenIdConfigUrl"],
new OpenIdConnectConfigurationRetriever());
var configuration = configurationManager.GetConfigurationAsync().Result;
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Configuration = configuration;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = builder.Configuration["AllowedAudience"]
};
});
builder.Services.AddAuthorization();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapPost("/api/callback", (CloudEvent[] events) =>
{
// Your implementation on the callback event
return Results.Ok();
})
.RequireAuthorization()
.WithOpenApi();
app.UseAuthentication();
app.UseAuthorization();
app.Run();
Vylepšení zabezpečení zpětného volání webhooku pro automatizované hovory
Každé zpětné volání webhooku během hovoru odeslané službou Call Automation používá podepsaný webový token JSON (JWT) v hlavičce ověřování příchozího požadavku HTTPS. K zajištění integrity tokenu můžete použít standardní techniky ověřování Open ID Connect (OIDC) JWT, jak je uvedeno dále. Životnost JWT je pět (5) minut a pro každou událost odesílanou do identifikátoru URI zpětného volání se vytvoří nový token.
- Získejte adresu URL konfigurace Open ID: https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
- Následující ukázka používá architekturu Spring vytvořenou pomocí spring initializru s Mavenem jako nástroj pro sestavení projektu.
- Do svého
pom.xml
přidejte následující závislosti:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
- Nakonfigurujte aplikaci tak, aby ověřila JWT a konfiguraci prostředku Azure Communication Services. Potřebujete hodnoty
audience
, které jsou přítomné v datové části JWT. - Ověřte vystavitele, cílovou skupinu a JWT.
- Cílová skupina je ID prostředku služby Azure Communication Services, které jste použili k nastavení klienta automatizace volání. Informace o tom, jak ho získat, najdete tady .
- Koncový bod sady webových klíčů JSON (JWKS) v konfiguraci OpenId obsahuje klíče použité k ověření JWT. Pokud je podpis platný a platnost tokenu nevypršela (do 5 minut od generování), klient může token použít k autorizaci.
Tento ukázkový kód ukazuje, jak nakonfigurovat klienta OIDC tak, aby ověřil datovou část webhooku pomocí JWT.
package callautomation.example.security;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
import org.springframework.security.oauth2.jwt.*;
@EnableWebSecurity
public class TokenValidationConfiguration {
@Value("ACS resource ID")
private String audience;
@Value("https://acscallautomation.communication.azure.com")
private String issuer;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.mvcMatchers("/api/callbacks").permitAll()
.anyRequest()
.and()
.oauth2ResourceServer()
.jwt()
.decoder(jwtDecoder());
return http.build();
}
class AudienceValidator implements OAuth2TokenValidator<Jwt> {
private String audience;
OAuth2Error error = new OAuth2Error("invalid_token", "The required audience is missing", null);
public AudienceValidator(String audience) {
this.audience = audience;
}
@Override
public OAuth2TokenValidatorResult validate(Jwt token) {
if (token.getAudience().contains(audience)) {
return OAuth2TokenValidatorResult.success();
} else {
return OAuth2TokenValidatorResult.failure(error);
}
}
}
JwtDecoder jwtDecoder() {
OAuth2TokenValidator<Jwt> withAudience = new AudienceValidator(audience);
OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuer);
OAuth2TokenValidator<Jwt> validator = new DelegatingOAuth2TokenValidator<>(withAudience, withIssuer);
NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder) JwtDecoders.fromOidcIssuerLocation(issuer);
jwtDecoder.setJwtValidator(validator);
return jwtDecoder;
}
}
Vylepšení zabezpečení zpětného volání webhooku pro automatizované hovory
Každé zpětné volání webhooku během hovoru odeslané službou Call Automation používá podepsaný webový token JSON (JWT) v hlavičce ověřování příchozího požadavku HTTPS. K zajištění integrity tokenu můžete použít standardní techniky ověřování Open ID Connect (OIDC) JWT, jak je uvedeno dále. Životnost JWT je pět (5) minut a pro každou událost odesílanou do identifikátoru URI zpětného volání se vytvoří nový token.
- Získejte adresu URL konfigurace Open ID: https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
- Nainstalujte následující balíčky:
npm install express jwks-rsa jsonwebtoken
- Nakonfigurujte aplikaci tak, aby ověřila JWT a konfiguraci prostředku Azure Communication Services. Potřebujete hodnoty
audience
, které jsou přítomné v datové části JWT. - Ověřte vystavitele, cílovou skupinu a JWT.
- Cílová skupina je ID prostředku služby Azure Communication Services, které jste použili k nastavení klienta automatizace volání. Informace o tom, jak ho získat, najdete tady .
- Koncový bod sady webových klíčů JSON (JWKS) v konfiguraci OpenId obsahuje klíče použité k ověření JWT. Pokud je podpis platný a platnost tokenu nevypršela (do 5 minut od generování), klient může token použít k autorizaci.
Tento ukázkový kód ukazuje, jak nakonfigurovat klienta OIDC tak, aby ověřil datovou část webhooku pomocí JWT.
import express from "express";
import { JwksClient } from "jwks-rsa";
import { verify } from "jsonwebtoken";
const app = express();
const port = 3000;
const audience = "ACS resource ID";
const issuer = "https://acscallautomation.communication.azure.com";
app.use(express.json());
app.post("/api/callback", (req, res) => {
const token = req?.headers?.authorization?.split(" ")[1] || "";
if (!token) {
res.sendStatus(401);
return;
}
try {
verify(
token,
(header, callback) => {
const client = new JwksClient({
jwksUri: "https://acscallautomation.communication.azure.com/calling/keys",
});
client.getSigningKey(header.kid, (err, key) => {
const signingKey = key?.publicKey || key?.rsaPublicKey;
callback(err, signingKey);
});
},
{
audience,
issuer,
algorithms: ["RS256"],
});
// Your implementation on the callback event
res.sendStatus(200);
} catch (error) {
res.sendStatus(401);
}
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
Vylepšení zabezpečení zpětného volání webhooku pro automatizované hovory
Každé zpětné volání webhooku během hovoru odeslané službou Call Automation používá podepsaný webový token JSON (JWT) v hlavičce ověřování příchozího požadavku HTTPS. K zajištění integrity tokenu můžete použít standardní techniky ověřování Open ID Connect (OIDC) JWT, jak je uvedeno dále. Životnost JWT je pět (5) minut a pro každou událost odesílanou do identifikátoru URI zpětného volání se vytvoří nový token.
- Získejte adresu URL konfigurace Open ID: https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
- Nainstalujte následující balíčky:
pip install flask pyjwt
- Nakonfigurujte aplikaci tak, aby ověřila JWT a konfiguraci prostředku Azure Communication Services. Potřebujete hodnoty
audience
, které jsou přítomné v datové části JWT. - Ověřte vystavitele, cílovou skupinu a JWT.
- Cílová skupina je ID prostředku služby Azure Communication Services, které jste použili k nastavení klienta automatizace volání. Informace o tom, jak ho získat, najdete tady .
- Koncový bod sady webových klíčů JSON (JWKS) v konfiguraci OpenId obsahuje klíče použité k ověření JWT. Pokud je podpis platný a platnost tokenu nevypršela (do 5 minut od generování), klient může token použít k autorizaci.
Tento ukázkový kód ukazuje, jak nakonfigurovat klienta OIDC tak, aby ověřil datovou část webhooku pomocí JWT.
from flask import Flask, jsonify, abort, request
import jwt
app = Flask(__name__)
@app.route("/api/callback", methods=["POST"])
def handle_callback_event():
token = request.headers.get("authorization").split()[1]
if not token:
abort(401)
try:
jwks_client = jwt.PyJWKClient(
"https://acscallautomation.communication.azure.com/calling/keys"
)
jwt.decode(
token,
jwks_client.get_signing_key_from_jwt(token).key,
algorithms=["RS256"],
issuer="https://acscallautomation.communication.azure.com",
audience="ACS resource ID",
)
# Your implementation on the callback event
return jsonify(success=True)
except jwt.InvalidTokenError:
print("Token is invalid")
abort(401)
except Exception as e:
print("uncaught exception" + e)
abort(500)
if __name__ == "__main__":
app.run()
Události websockets služby Call Automation
Ověřovací token v hlavičce WebSocket
Každý požadavek na připojení WebSocket provedený službou Call Automation teď obsahuje podepsaný webový token JSON (JWT) v hlavičce Ověřování. Tento token lze ověřit pomocí standardních metod ověřování JWT (OpenID Connect).
- JWT má životnost 24 hodin.
- Pro každý požadavek na připojení k serveru WebSocket se vygeneruje nový token.
- Další podrobnosti najdete v oficiální dokumentaci: Zabezpečený koncový bod webhooku – Azure Communication Services
Ukázka kódu Websocket
Tento ukázkový kód ukazuje, jak ověřovat požadavky na připojení WebSocket pomocí tokenů JSON Web Token (JWT).
// 1. Load OpenID Connect metadata
var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
builder.Configuration["OpenIdConfigUrl"],
new OpenIdConnectConfigurationRetriever());
var openIdConfig = await configurationManager.GetConfigurationAsync();
// 2. Register JWT authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Configuration = openIdConfig;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = builder.Configuration["AllowedAudience"]
};
});
builder.Services.AddAuthorization();
var app = builder.Build();
// 3. Use authentication & authorization middleware
app.UseAuthentication();
app.UseAuthorization();
app.UseWebSockets();
// 4. WebSocket token validation manually in middleware
app.Use(async (context, next) =>
{
if (context.Request.Path != "/ws")
{
await next(context);
return;
}
if (!context.WebSockets.IsWebSocketRequest)
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
await context.Response.WriteAsync("WebSocket connection expected.");
return;
}
var result = await context.AuthenticateAsync();
if (!result.Succeeded)
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
await context.Response.WriteAsync("Unauthorized WebSocket connection.");
return;
}
context.User = result.Principal;
// Optional: Log headers
var correlationId = context.Request.Headers["x-ms-call-correlation-id"].FirstOrDefault();
var callConnectionId = context.Request.Headers["x-ms-call-connection-id"].FirstOrDefault();
Console.WriteLine($"Authenticated WebSocket - Correlation ID: {correlationId ?? "not provided"}");
Console.WriteLine($"Authenticated WebSocket - CallConnection ID: {callConnectionId ?? "not provided"}");
// Now you can safely accept the WebSocket and process the connection
// var webSocket = await context.WebSockets.AcceptWebSocketAsync();
// var mediaService = new AcsMediaStreamingHandler(webSocket, builder.Configuration);
// await mediaService.ProcessWebSocketAsync();
});
Ukázka kódu Websocket
Tato ukázka ukazuje, jak nakonfigurovat klienta OpenID Connect (OIDC) k ověření požadavků připojení WebSocket pomocí webového tokenu JSON (JWT).
const audience = "ACS resource ID";
const issuer = "https://acscallautomation.communication.azure.com";
const jwksClient = new JwksClient({
jwksUri: "https://acscallautomation.communication.azure.com/calling/keys",
});
wss.on("connection", async (ws, req) => {
try {
const authHeader = req.headers?.authorization || "";
const token = authHeader.split(" ")[1];
if (!token) {
ws.close(1008, "Unauthorized");
return;
}
verify(
token,
async (header, callback) => {
try {
const key = await jwksClient.getSigningKey(header.kid);
const signingKey = key.getPublicKey();
callback(null, signingKey);
} catch (err) {
callback(err);
}
},
{
audience,
issuer,
algorithms: ["RS256"],
},
(err, decoded) => {
if (err) {
console.error("WebSocket authentication failed:", err);
ws.close(1008, "Unauthorized");
return;
}
console.log(
"Authenticated WebSocket connection with decoded JWT payload:",
decoded
);
ws.on("message", async (message) => {
// Process message
});
ws.on("close", () => {
console.log("WebSocket connection closed");
});
}
);
} catch (err) {
console.error("Unexpected error during WebSocket setup:", err);
ws.close(1011, "Internal Server Error"); // 1011 = internal error
}
});
Ukázka kódu Websocket
Tato ukázka ukazuje, jak nakonfigurovat klienta kompatibilního s protokolem OIDC tak, aby ověřil požadavky připojení WebSocket pomocí JWT.
Nezapomeňte nainstalovat požadovaný balíček: pip install cryptography
JWKS_URL = "https://acscallautomation.communication.azure.com/calling/keys"
ISSUER = "https://acscallautomation.communication.azure.com"
AUDIENCE = "ACS resource ID”
@app.websocket('/ws')
async def ws():
try:
auth_header = websocket.headers.get("Authorization")
if not auth_header or not auth_header.startswith("Bearer "):
await websocket.close(1008) # Policy violation
return
token = auth_header.split()[1]
jwks_client = PyJWKClient(JWKS_URL)
signing_key = jwks_client.get_signing_key_from_jwt(token)
decoded = jwt.decode(
token,
signing_key.key,
algorithms=["RS256"],
issuer=ISSUER,
audience=AUDIENCE,
)
app.logger.info(f"Authenticated WebSocket connection with decoded JWT payload: {decoded}")
await websocket.send("Connection authenticated.")
while True:
data = await websocket.receive()
# Process incoming data
except InvalidTokenError as e:
app.logger.warning(f"Invalid token: {e}")
await websocket.close(1008)
except Exception as e:
app.logger.error(f"Uncaught exception: {e}")
await websocket.close(1011) # Internal error
Rozsah IP adresy
Dalším způsobem, jak zabezpečit připojení websocket, je povolením pouze připojení Microsoft z určitých rozsahů IP adres.
Kategorie | Rozsahy IP adres nebo plně kvalifikovaný název domény | Přístavy |
---|---|---|
Volání automatizačního média | 52.112.0.0/14, 52.122.0.0/15, 2603:1063::/38 | UDP: 3478, 3479, 3480, 3481 |
Adresy URL zpětného volání služby Automation | *.lync.com, *.teams.cloud.microsoft, *.teams.microsoft.com, teams.cloud.microsoft, teams.microsoft.com 52.112.0.0/14, 52.122.0.0/15, 2603:1027::/48, 2603:1037::/48, 2603:1047::/48, 2603:1057::/48, 2603:1063::/38, 2620:1ec:6::/48, 2620:1ec:40::/42 | TCP: 443, 80 UDP: 443 |
Další kroky
- Přečtěte si další informace o tom, jak řídit a řídit volání pomocí automatizace volání.