Comment sécuriser le point de terminaison webhook
La sécurisation de la remise des messages de bout en bout est essentielle pour garantir la confidentialité, l’intégrité et la fiabilité des informations sensibles transmises entre les systèmes. Votre capacité et votre volonté de faire confiance aux informations reçues d’un système distant s’appuient sur l’expéditeur fournissant leur identité. L’automatisation des appels a deux façons de communiquer des événements qui peuvent être sécurisés ; l’événement IncomingCall partagé envoyé par Azure Event Grid et tous les autres événements intermédiaires envoyés par la plateforme Call Automation via le webhook.
Événement d’appel entrant
Azure Communication Services s’appuie sur les abonnements Azure Event Grid pour remettre l’événement IncomingCall. Vous pouvez consulter l’équipe Azure Event Grid pour obtenir sa documentation sur la sécurisation d’un abonnement webhook.
Événements webhook Call Automation
Les événements Automation d’appel sont envoyés à l’URI de rappel webhook spécifié lorsque vous répondez à un appel ou que vous placez un nouvel appel sortant. Votre URI de rappel doit être un point de terminaison public avec un certificat HTTPS valide, un nom DNS et une adresse IP avec les ports de pare-feu appropriés ouverts pour permettre à Call Automation de l’atteindre. Ce serveur web public anonyme peut créer un risque de sécurité si vous ne prenez pas les mesures nécessaires pour le sécuriser contre un accès non autorisé.
Une façon courante d’améliorer cette sécurité consiste à implémenter un mécanisme API KEY. Votre serveur web peut générer la clé au moment de l’exécution et la fournir dans l’URI de rappel en tant que paramètre de requête lorsque vous répondez ou créez un appel. Votre serveur web peut vérifier la clé dans le rappel de webhook à partir de Call Automation avant d’autoriser l’accès. Certains clients nécessitent davantage de mesures de sécurité. Dans ces cas, un périphérique réseau de périmètre peut vérifier le webhook entrant, séparé du serveur web ou de l’application lui-même. Le mécanisme de clé API seul peut ne pas suffire.
Amélioration de la sécurité des rappels webhook Automation
Chaque rappel de webhook intermédiaire envoyé par Call Automation utilise un jeton web JSON signé (JWT) dans l’en-tête d’authentification de la requête HTTPS entrante. Vous pouvez utiliser des techniques de validation JWT Connecter (OIDC) Open ID standard pour garantir l’intégrité du jeton comme suit. La durée de vie du JWT est de cinq (5) minutes et un nouveau jeton est créé pour chaque événement envoyé à l’URI de rappel.
- Obtenez l’URL de configuration Open ID : https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
- Installez le package NuGet Microsoft.AspNetCore.Authentication.JwtBearer.
- Configurez votre application pour valider JWT à l’aide du package NuGet et de la configuration de votre ressource Azure Communication Services. Vous avez besoin des
audience
valeurs telles qu’elles sont présentes dans la charge utile JWT. - Validez l’émetteur, l’audience et le jeton JWT.
- L’audience est votre ID de ressource Azure Communication Services que vous avez utilisé pour configurer votre client Call Automation. Reportez-vous ici pour savoir comment l’obtenir.
- Le point de terminaison JWKS (JSON Web Key Set) dans la configuration OpenId contient les clés utilisées pour valider le jeton JWT. Lorsque la signature est valide et que le jeton n’a pas expiré (dans les 5 minutes de génération), le client peut utiliser le jeton pour l’autorisation.
Cet exemple de code montre comment utiliser Microsoft.IdentityModel.Protocols.OpenIdConnect
pour valider la charge utile du webhook
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 implemenation on the callback event
return Results.Ok();
})
.RequireAuthorization()
.WithOpenApi();
app.UseAuthentication();
app.UseAuthorization();
app.Run();
Amélioration de la sécurité des rappels webhook Automation
Chaque rappel de webhook intermédiaire envoyé par Call Automation utilise un jeton web JSON signé (JWT) dans l’en-tête d’authentification de la requête HTTPS entrante. Vous pouvez utiliser des techniques de validation JWT Connecter (OIDC) Open ID standard pour garantir l’intégrité du jeton comme suit. La durée de vie du JWT est de cinq (5) minutes et un nouveau jeton est créé pour chaque événement envoyé à l’URI de rappel.
- Obtenez l’URL de configuration Open ID : https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
- L’exemple suivant utilise Spring Framework, créé à l’aide de spring initializr avec Maven en tant qu’outil de génération de projet.
- Ajoutez les dépendances suivantes dans votre
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>
- Configurez votre application pour valider JWT et la configuration de votre ressource Azure Communication Services. Vous avez besoin des
audience
valeurs telles qu’elles sont présentes dans la charge utile JWT. - Validez l’émetteur, l’audience et le jeton JWT.
- L’audience est votre ID de ressource Azure Communication Services que vous avez utilisé pour configurer votre client Call Automation. Reportez-vous ici pour savoir comment l’obtenir.
- Le point de terminaison JWKS (JSON Web Key Set) dans la configuration OpenId contient les clés utilisées pour valider le jeton JWT. Lorsque la signature est valide et que le jeton n’a pas expiré (dans les 5 minutes de génération), le client peut utiliser le jeton pour l’autorisation.
Cet exemple de code montre comment configurer le client OIDC pour valider la charge utile du webhook à l’aide de 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;
}
}
Amélioration de la sécurité des rappels webhook Automation
Chaque rappel de webhook intermédiaire envoyé par Call Automation utilise un jeton web JSON signé (JWT) dans l’en-tête d’authentification de la requête HTTPS entrante. Vous pouvez utiliser des techniques de validation JWT Connecter (OIDC) Open ID standard pour garantir l’intégrité du jeton comme suit. La durée de vie du JWT est de cinq (5) minutes et un nouveau jeton est créé pour chaque événement envoyé à l’URI de rappel.
- Obtenez l’URL de configuration Open ID : https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
- Installez les packages suivants :
npm install express jwks-rsa jsonwebtoken
- Configurez votre application pour valider JWT et la configuration de votre ressource Azure Communication Services. Vous avez besoin des
audience
valeurs telles qu’elles sont présentes dans la charge utile JWT. - Validez l’émetteur, l’audience et le jeton JWT.
- L’audience est votre ID de ressource Azure Communication Services que vous avez utilisé pour configurer votre client Call Automation. Reportez-vous ici pour savoir comment l’obtenir.
- Le point de terminaison JWKS (JSON Web Key Set) dans la configuration OpenId contient les clés utilisées pour valider le jeton JWT. Lorsque la signature est valide et que le jeton n’a pas expiré (dans les 5 minutes de génération), le client peut utiliser le jeton pour l’autorisation.
Cet exemple de code montre comment configurer le client OIDC pour valider la charge utile du webhook à l’aide de 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}`);
});
Amélioration de la sécurité des rappels webhook Automation
Chaque rappel de webhook intermédiaire envoyé par Call Automation utilise un jeton web JSON signé (JWT) dans l’en-tête d’authentification de la requête HTTPS entrante. Vous pouvez utiliser des techniques de validation JWT Connecter (OIDC) Open ID standard pour garantir l’intégrité du jeton comme suit. La durée de vie du JWT est de cinq (5) minutes et un nouveau jeton est créé pour chaque événement envoyé à l’URI de rappel.
- Obtenez l’URL de configuration Open ID : https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
- Installez les packages suivants :
pip install flask pyjwt
- Configurez votre application pour valider JWT et la configuration de votre ressource Azure Communication Services. Vous avez besoin des
audience
valeurs telles qu’elles sont présentes dans la charge utile JWT. - Validez l’émetteur, l’audience et le jeton JWT.
- L’audience est votre ID de ressource Azure Communication Services que vous avez utilisé pour configurer votre client Call Automation. Reportez-vous ici pour savoir comment l’obtenir.
- Le point de terminaison JWKS (JSON Web Key Set) dans la configuration OpenId contient les clés utilisées pour valider le jeton JWT. Lorsque la signature est valide et que le jeton n’a pas expiré (dans les 5 minutes de génération), le client peut utiliser le jeton pour l’autorisation.
Cet exemple de code montre comment configurer le client OIDC pour valider la charge utile du webhook à l’aide de 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()
Étapes suivantes
- Apprenez-en davantage sur la façon de contrôler et de diriger les appels avec Call Automation.