كيفية تأمين نقطة نهاية خطاف الويب

يعد تأمين تسليم الرسائل من طرف إلى طرف أمرا بالغ الأهمية لضمان سرية المعلومات الحساسة المرسلة بين الأنظمة وسلامتها وموثوقيتها. تعتمد قدرتك واستعدادك للثقة في المعلومات الواردة من نظام بعيد على المرسل الذي يقدم هويته. أتمتة المكالمات لها طريقتان لتوصيل الأحداث التي يمكن تأمينها؛ حدث IncomingCall المشترك المرسل بواسطة Azure Event Grid، وجميع أحداث منتصف المكالمة الأخرى المرسلة من قبل النظام الأساسي لأتمتة المكالمات عبر خطاف الويب.

حدث المكالمة الواردة

تعتمد Azure Communication Services على اشتراكات Azure Event Grid لتقديم حدث IncomingCall. يمكنك الرجوع إلى فريق Azure Event Grid للحصول على وثائقهم حول كيفية تأمين اشتراك webhook.

أحداث إخطار على الويب لأتمتة الاتصال

يتم إرسال أحداث أتمتة المكالمات إلى عنوان URI لرد اتصال خطاف الويب المحدد عند الرد على مكالمة، أو إجراء مكالمة صادرة جديدة. يجب أن يكون عنوان URI لرد الاتصال نقطة نهاية عامة مع شهادة HTTPS صالحة واسم DNS وعنوان IP مع فتح منافذ جدار الحماية الصحيحة لتمكين أتمتة المكالمات للوصول إليها. قد ينشئ خادم الويب العام المجهول هذا خطرا أمنيا إذا لم تتخذ الخطوات اللازمة لتأمينه من الوصول غير المصرح به.

إحدى الطرق الشائعة التي يمكنك من خلالها تحسين هذا الأمان هي تنفيذ آلية مفتاح واجهة برمجة التطبيقات. يمكن لخادم الويب إنشاء المفتاح في وقت التشغيل وتوفيره في عنوان URI لرد الاتصال كمعلمة استعلام عند الرد على مكالمة أو إنشائها. يمكن لخادم الويب التحقق من المفتاح في رد اتصال الإخطار على الويب من أتمتة المكالمات قبل السماح بالوصول. يتطلب بعض العملاء المزيد من التدابير الأمنية. في هذه الحالات، قد يتحقق جهاز الشبكة المحيطة من خطاف الويب الوارد، منفصلا عن خادم الويب أو التطبيق نفسه. قد لا تكون آلية مفتاح واجهة برمجة التطبيقات وحدها كافية.

تحسين أمان رد اتصال إخطار على الويب لأتمتة المكالمات

يستخدم كل رد اتصال إخطار على الويب منتصف المكالمة يتم إرساله بواسطة أتمتة المكالمات رمز ويب JSON موقع (JWT) في عنوان المصادقة لطلب HTTPS الوارد. يمكنك استخدام تقنيات التحقق من صحة JWT الاتصال المعرف المفتوح (OIDC) القياسية لضمان تكامل الرمز المميز كما يلي. عمر JWT هو خمس (5) دقائق ويتم إنشاء رمز مميز جديد لكل حدث يتم إرساله إلى URI رد الاتصال.

  1. الحصول على عنوان URL لتكوين Open ID: https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
  2. تثبيت حزمة NuGet Microsoft.AspNetCore.Authentication.JwtBearer.
  3. قم بتكوين التطبيق الخاص بك للتحقق من صحة JWT باستخدام حزمة NuGet وتكوين مورد Azure Communication Services. تحتاج إلى audience القيم كما هي موجودة في حمولة JWT.
  4. تحقق من صحة المصدر والجمهور ورمز JWT المميز.
    • الجمهور هو معرف مورد Azure Communication Services الذي استخدمته لإعداد عميل أتمتة المكالمات. راجع هنا حول كيفية الحصول عليه.
    • تحتوي نقطة نهاية JSON Web Key Set (JWKS) في تكوين OpenId على المفاتيح المستخدمة للتحقق من صحة رمز JWT المميز. عندما يكون التوقيع صالحا ولم تنته صلاحية الرمز المميز (في غضون 5 دقائق من إنشاء)، يمكن للعميل استخدام الرمز المميز للتخويل.

يوضح نموذج التعليمات البرمجية هذا كيفية استخدام Microsoft.IdentityModel.Protocols.OpenIdConnect للتحقق من صحة حمولة خطاف الويب

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();

تحسين أمان رد اتصال إخطار على الويب لأتمتة المكالمات

يستخدم كل رد اتصال إخطار على الويب منتصف المكالمة يتم إرساله بواسطة أتمتة المكالمات رمز ويب JSON موقع (JWT) في عنوان المصادقة لطلب HTTPS الوارد. يمكنك استخدام تقنيات التحقق من صحة JWT الاتصال المعرف المفتوح (OIDC) القياسية لضمان تكامل الرمز المميز كما يلي. عمر JWT هو خمس (5) دقائق ويتم إنشاء رمز مميز جديد لكل حدث يتم إرساله إلى URI رد الاتصال.

  1. الحصول على عنوان URL لتكوين Open ID: https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
  2. يستخدم النموذج التالي إطار عمل Spring، الذي تم إنشاؤه باستخدام spring initializr مع Maven كأداة لبناء المشروع.
  3. أضف التبعيات التالية في 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. تكوين التطبيق الخاص بك للتحقق من صحة JWT وتكوين مورد Azure Communication Services. تحتاج إلى audience القيم كما هي موجودة في حمولة JWT.
  2. تحقق من صحة المصدر والجمهور ورمز JWT المميز.
    • الجمهور هو معرف مورد Azure Communication Services الذي استخدمته لإعداد عميل أتمتة المكالمات. راجع هنا حول كيفية الحصول عليه.
    • تحتوي نقطة نهاية JSON Web Key Set (JWKS) في تكوين OpenId على المفاتيح المستخدمة للتحقق من صحة رمز JWT المميز. عندما يكون التوقيع صالحا ولم تنته صلاحية الرمز المميز (في غضون 5 دقائق من إنشاء)، يمكن للعميل استخدام الرمز المميز للتخويل.

يوضح نموذج التعليمات البرمجية هذا كيفية تكوين عميل OIDC للتحقق من صحة حمولة خطاف الويب باستخدام 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;
    }
}

تحسين أمان رد اتصال إخطار على الويب لأتمتة المكالمات

يستخدم كل رد اتصال إخطار على الويب منتصف المكالمة يتم إرساله بواسطة أتمتة المكالمات رمز ويب JSON موقع (JWT) في عنوان المصادقة لطلب HTTPS الوارد. يمكنك استخدام تقنيات التحقق من صحة JWT الاتصال المعرف المفتوح (OIDC) القياسية لضمان تكامل الرمز المميز كما يلي. عمر JWT هو خمس (5) دقائق ويتم إنشاء رمز مميز جديد لكل حدث يتم إرساله إلى URI رد الاتصال.

  1. الحصول على عنوان URL لتكوين Open ID: https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
  2. تثبيت الحزم التالية:
npm install express jwks-rsa jsonwebtoken
  1. تكوين التطبيق الخاص بك للتحقق من صحة JWT وتكوين مورد Azure Communication Services. تحتاج إلى audience القيم كما هي موجودة في حمولة JWT.
  2. تحقق من صحة المصدر والجمهور ورمز JWT المميز.
    • الجمهور هو معرف مورد Azure Communication Services الذي استخدمته لإعداد عميل أتمتة المكالمات. راجع هنا حول كيفية الحصول عليه.
    • تحتوي نقطة نهاية JSON Web Key Set (JWKS) في تكوين OpenId على المفاتيح المستخدمة للتحقق من صحة رمز JWT المميز. عندما يكون التوقيع صالحا ولم تنته صلاحية الرمز المميز (في غضون 5 دقائق من إنشاء)، يمكن للعميل استخدام الرمز المميز للتخويل.

يوضح نموذج التعليمات البرمجية هذا كيفية تكوين عميل OIDC للتحقق من صحة حمولة خطاف الويب باستخدام 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}`);
});

تحسين أمان رد اتصال إخطار على الويب لأتمتة المكالمات

يستخدم كل رد اتصال إخطار على الويب منتصف المكالمة يتم إرساله بواسطة أتمتة المكالمات رمز ويب JSON موقع (JWT) في عنوان المصادقة لطلب HTTPS الوارد. يمكنك استخدام تقنيات التحقق من صحة JWT الاتصال المعرف المفتوح (OIDC) القياسية لضمان تكامل الرمز المميز كما يلي. عمر JWT هو خمس (5) دقائق ويتم إنشاء رمز مميز جديد لكل حدث يتم إرساله إلى URI رد الاتصال.

  1. الحصول على عنوان URL لتكوين Open ID: https://acscallautomation.communication.azure.com/calling/.well-known/acsopenidconfiguration
  2. تثبيت الحزم التالية:
pip install flask pyjwt
  1. تكوين التطبيق الخاص بك للتحقق من صحة JWT وتكوين مورد Azure Communication Services. تحتاج إلى audience القيم كما هي موجودة في حمولة JWT.
  2. تحقق من صحة المصدر والجمهور ورمز JWT المميز.
    • الجمهور هو معرف مورد Azure Communication Services الذي استخدمته لإعداد عميل أتمتة المكالمات. راجع هنا حول كيفية الحصول عليه.
    • تحتوي نقطة نهاية JSON Web Key Set (JWKS) في تكوين OpenId على المفاتيح المستخدمة للتحقق من صحة رمز JWT المميز. عندما يكون التوقيع صالحا ولم تنته صلاحية الرمز المميز (في غضون 5 دقائق من إنشاء)، يمكن للعميل استخدام الرمز المميز للتخويل.

يوضح نموذج التعليمات البرمجية هذا كيفية تكوين عميل OIDC للتحقق من صحة حمولة خطاف الويب باستخدام 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()

الخطوات التالية