Zabezpečení koncového bodu webhooku

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é lze zabezpečit; sdílená událost IncomingCall odeslaná Azure Event Grid a všechny ostatní události středního volání odeslané platformou Call Automation prostřednictvím webhooku.

Událost příchozího hovoru

Azure Communication Services k doručení události IncomingCall spoléhá na Azure Event Grid odběry. Dokumentaci k zabezpečení předplatného webhooku najdete v Azure Event Grid týmu.

Události webhooku služby Automation

Události automatizace volání se odesílají na identifikátor URI zpětného volání webhooku zadaný při přijetí hovoru nebo při zahájení nového odchozího volání. Identifikátor URI zpětného volání musí být veřejný koncový bod s platným certifikátem HTTPS, názvem DNS a IP adresou se správnými otevřenými porty brány firewall, aby se k němu mohla spojit automatizace volání. Tento anonymní veřejný webový server by mohl vytvořit bezpečnostní riziko, pokud neuděláte nezbytné kroky k jeho zabezpečení před neoprávněným přístupem.

Běžným způsobem, jak můžete toto zabezpečení vylepšit, je implementace mechanismu klíče rozhraní API. Váš webový server může vygenerovat klíč 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 ze služby Call Automation. Někteří zákazníci vyžadují další bezpečnostní opatření. V těchto případech může příchozí webhook ověřit hraniční síťové zařízení odděleně od samotného webového serveru nebo aplikace. Samotný mechanismus klíče rozhraní API nemusí být dostačující.

Vylepšení zabezpečení zpětného volání webhooku pro automatizaci volání

Každé zpětné volání webhooku uprostřed volání odeslané automatizací volání používá podepsaný webový token JSON (JWT) v ověřovací hlavičce příchozího požadavku HTTPS. K zajištění integrity tokenu můžete následujícím způsobem použít standardní techniky ověřování JWT open ID Connect (OIDC). Životnost JWT je pět (5) minut a pro každou událost odeslanou do identifikátoru URI zpětného volání se vytvoří nový token.

  1. Získejte adresu URL konfigurace Open ID: https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
  2. Nainstalujte balíček NuGet Microsoft.AspNetCore.Authentication.JwtBearer .
  3. Nakonfigurujte aplikaci tak, aby ověřila JWT pomocí balíčku NuGet a konfigurace prostředku služby ACS. Potřebujete hodnoty audience , protože se nacházejí v datové části JWT.
  4. Ověřte vystavitele, cílovou skupinu a token JWT.
    • Cílová skupina je ID prostředku služby ACS, které jste použili k nastavení klienta automatizace volání. Informace o tom, jak ji získat, najdete tady .
    • Koncový bod JWKS (JSON Web Key Set) v konfiguraci OpenId obsahuje klíče použité k ověření tokenu JWT. Pokud je podpis platný a platnost tokenu ještě nevypršela (do 5 minut od vygenerování), klient může token použít k autorizaci.

Tento ukázkový kód ukazuje použití k Microsoft.IdentityModel.Protocols.OpenIdConnect ověření datové části 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 ACS 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 implemenation 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 automatizaci volání

Každé zpětné volání webhooku uprostřed volání odeslané automatizací volání používá podepsaný webový token JSON (JWT) v ověřovací hlavičce příchozího požadavku HTTPS. K zajištění integrity tokenu můžete následujícím způsobem použít standardní techniky ověřování JWT open ID Connect (OIDC). Životnost JWT je pět (5) minut a pro každou událost odeslanou do identifikátoru URI zpětného volání se vytvoří nový token.

  1. Získejte adresu URL konfigurace Open ID: https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
  2. Následující ukázka používá architekturu Spring vytvořenou pomocí aplikace spring initializr s Mavenem jako nástrojem pro sestavení projektu.
  3. Do přidejte následující závislosti:pom.xml
  <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>
  1. Nakonfigurujte aplikaci tak, aby ověřila JWT a konfiguraci prostředku služby ACS. Potřebujete hodnoty audience , protože se nacházejí v datové části JWT.
  2. Ověřte vystavitele, cílovou skupinu a token JWT.
    • Cílová skupina je ID prostředku služby ACS, které jste použili k nastavení klienta automatizace volání. Informace o tom, jak ji získat, najdete tady .
    • Koncový bod JWKS (JSON Web Key Set) v konfiguraci OpenId obsahuje klíče použité k ověření tokenu JWT. Pokud je podpis platný a platnost tokenu ještě nevypršela (do 5 minut od vygenerování), klient může token použít k autorizaci.

Tento ukázkový kód ukazuje, jak nakonfigurovat klienta OIDC pro ověření datové části 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 automatizaci volání

Každé zpětné volání webhooku uprostřed volání odeslané automatizací volání používá podepsaný webový token JSON (JWT) v ověřovací hlavičce příchozího požadavku HTTPS. K zajištění integrity tokenu můžete následujícím způsobem použít standardní techniky ověřování JWT open ID Connect (OIDC). Životnost JWT je pět (5) minut a pro každou událost odeslanou do identifikátoru URI zpětného volání se vytvoří nový token.

  1. Získejte adresu URL konfigurace Open ID: https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
  2. Nainstalujte následující balíčky:
npm install express jwks-rsa jsonwebtoken
  1. Nakonfigurujte aplikaci tak, aby ověřila JWT a konfiguraci prostředku služby ACS. Potřebujete hodnoty audience , protože se nacházejí v datové části JWT.
  2. Ověřte vystavitele, cílovou skupinu a token JWT.
    • Cílová skupina je ID prostředku služby ACS, které jste použili k nastavení klienta automatizace volání. Informace o tom, jak ji získat, najdete tady .
    • Koncový bod JWKS (JSON Web Key Set) v konfiguraci OpenId obsahuje klíče použité k ověření tokenu JWT. Pokud je podpis platný a platnost tokenu ještě nevypršela (do 5 minut od vygenerování), klient může token použít k autorizaci.

Tento ukázkový kód ukazuje, jak nakonfigurovat klienta OIDC pro ověření datové části 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 automatizaci volání

Každé zpětné volání webhooku uprostřed volání odeslané automatizací volání používá podepsaný webový token JSON (JWT) v ověřovací hlavičce příchozího požadavku HTTPS. K zajištění integrity tokenu můžete následujícím způsobem použít standardní techniky ověřování JWT open ID Connect (OIDC). Životnost JWT je pět (5) minut a pro každou událost odeslanou do identifikátoru URI zpětného volání se vytvoří nový token.

  1. Získejte adresu URL konfigurace Open ID: https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
  2. Nainstalujte následující balíčky:
pip install flask pyjwt
  1. Nakonfigurujte aplikaci tak, aby ověřila JWT a konfiguraci prostředku služby ACS. Potřebujete hodnoty audience , protože se nacházejí v datové části JWT.
  2. Ověřte vystavitele, cílovou skupinu a token JWT.
    • Cílová skupina je ID prostředku služby ACS, které jste použili k nastavení klienta automatizace volání. Informace o tom, jak ji získat, najdete tady .
    • Koncový bod JWKS (JSON Web Key Set) v konfiguraci OpenId obsahuje klíče použité k ověření tokenu JWT. Pokud je podpis platný a platnost tokenu ještě nevypršela (do 5 minut od vygenerování), klient může token použít k autorizaci.

Tento ukázkový kód ukazuje, jak nakonfigurovat klienta OIDC pro ověření datové části 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()

Další kroky