Ejercicio: Integración de un complemento de API con una API protegida con OAuth

Completado

Los complementos de API para Microsoft 365 Copilot le permiten integrarse con API protegidas con OAuth. Mantenga el identificador de cliente y el secreto de la aplicación que protege la API registrándolos en el almacén de Teams. En tiempo de ejecución, Microsoft 365 Copilot ejecuta el complemento, recupera la información del almacén y la usa para obtener un token de acceso y llamar a la API. Al seguir este proceso, el identificador de cliente y el secreto permanecen seguros y nunca se exponen al cliente.

Abrir el proyecto de ejemplo

Para empezar, descargue el proyecto de ejemplo:

  1. En un explorador web, vaya a https://aka.ms/learn-da-api-ts-repairs. Obtendrá un mensaje para descargar un archivo ZIP con el proyecto de ejemplo.
  2. Guarde el archivo ZIP en el equipo.
  3. Extraiga el contenido del archivo ZIP.
  4. Abra la carpeta en Visual Studio Code.

El proyecto de ejemplo es un proyecto de Microsoft 365 Agents Toolkit que incluye un agente declarativo, un complemento de API y una API protegida con Microsoft Entra ID. La API se ejecuta en Azure Functions e implementa la seguridad mediante las funcionalidades integradas de autenticación y autorización de Azure Functions, a veces denominadas Easy Auth.

Examen de la configuración de autorización de OAuth2

Antes de continuar, examine la configuración de autorización de OAuth2 en el proyecto de ejemplo.

Examen de la definición de API

En primer lugar, examine la configuración de seguridad de la definición de API incluida en el proyecto.

En Visual Studio Code:

  1. Abra el archivo appPackage/apiSpecificationFile/repair.yml .

  2. En la sección components.securitySchemes , observe la propiedad oAuth2AuthCode :

    components:
      securitySchemes:
        oAuth2AuthCode:
          type: oauth2
          description: OAuth configuration for the repair service
          flows:
            authorizationCode:
              authorizationUrl: https://login.microsoftonline.com/${{AAD_APP_TENANT_ID}}/oauth2/v2.0/authorize
              tokenUrl: https://login.microsoftonline.com/${{AAD_APP_TENANT_ID}}/oauth2/v2.0/token
              scopes:
                api://${{AAD_APP_CLIENT_ID}}/repairs_read: Read repair records 
    

    La propiedad define un esquema de seguridad de OAuth2 e incluye información sobre las direcciones URL a las que llamar para obtener un token de acceso y qué ámbitos usa la API.

    Importante

    Observe que el ámbito está completo con el URI del identificador de aplicación (api://...). Al trabajar con Microsoft Entra debe calificar completamente los ámbitos personalizados. Cuando Microsoft Entra ve un ámbito no calificado, se supone que pertenece a Microsoft Graph, lo que conduce a errores de flujo de autorización.

  3. Busque la propiedad paths./repairs.get.security . Observe que hace referencia al esquema de seguridad oAuth2AuthCode y al ámbito que el cliente necesita para realizar la operación.

    [...]
    paths:
      /repairs:
        get:
          operationId: listRepairs
          [...]
          security:
            - oAuth2AuthCode:
              - api://${{AAD_APP_CLIENT_ID}}/repairs_read
    [...]
    

    Importante

    Enumerar los ámbitos necesarios en la especificación de API es puramente informativo. Al implementar la API, es responsable de validar el token y comprobar que contiene los ámbitos necesarios.

Examen de la implementación de API

A continuación, examine la implementación de la API.

En Visual Studio Code:

  1. Abra el archivo src/functions/repairs.ts .

  2. En la función de controlador de reparaciones , busque la línea siguiente, que comprueba si la solicitud contiene un token de acceso con los ámbitos necesarios:

    if (!hasRequiredScopes(req, 'repairs_read')) {
      return {
        status: 403,
        body: "Insufficient permissions",
      };
    }
    
  3. La función hasRequiredScopes se implementa aún más en el archivo repairs.ts :

    function hasRequiredScopes(req: HttpRequest, requiredScopes: string[] | string): boolean {
      if (typeof requiredScopes === 'string') {
        requiredScopes = [requiredScopes];
      }
    
      const token = req.headers.get("Authorization")?.split(" ");
      if (!token || token[0] !== "Bearer") {
        return false;
      }
    
      try {
        const decodedToken = jwtDecode<JwtPayload & { scp?: string }>(token[1]);
        const scopes = decodedToken.scp?.split(" ") ?? [];
        return requiredScopes.every(scope => scopes.includes(scope));
      }
      catch (error) {
        return false;
      }
    }
    

    La función se inicia mediante la extracción del token de portador del encabezado de solicitud de autorización. A continuación, usa el paquete jwt-decode para descodificar el token y obtener la lista de ámbitos de la notificación scp . Por último, comprueba si la notificación scp contiene todos los ámbitos necesarios.

    Observe que la función no valida el token de acceso. En su lugar, solo comprueba si el token de acceso contiene los ámbitos necesarios. En esta plantilla, la API se ejecuta en Azure Functions e implementa la seguridad mediante Easy Auth, que es responsable de validar el token de acceso. Si la solicitud no contiene un token de acceso válido, el entorno de ejecución de Azure Functions lo rechaza antes de que alcance el código. Aunque Easy Auth valida el token, no comprueba los ámbitos necesarios, lo que debe hacer usted mismo.

Examen de la configuración de la tarea del almacén

En este proyecto, usará Microsoft 365 Agents Toolkit para agregar la información de OAuth al almacén. Microsoft 365 Agents Toolkit registra la información de OAuth en el almacén mediante una tarea especial en la configuración del proyecto.

En Visual Studio Code:

  1. Abra el archivo ./teampsapp.local.yml .

  2. En la sección de aprovisionamiento , busque la tarea oauth/register .

    - uses: oauth/register
      with:
        name: oAuth2AuthCode
        flow: authorizationCode
        appId: ${{TEAMS_APP_ID}}
        clientId: ${{AAD_APP_CLIENT_ID}}
        clientSecret: ${{SECRET_AAD_APP_CLIENT_SECRET}}
        isPKCEEnabled: true
        # Path to OpenAPI description document
        apiSpecPath: ./appPackage/apiSpecificationFile/repair.yml
      writeToEnvironmentFile:
        configurationId: OAUTH2AUTHCODE_CONFIGURATION_ID
    

    La tarea toma los valores de las variables de proyecto TEAMS_APP_ID, AAD_APP_CLIENT_ID y SECRET_AAD_APP_CLIENT_SECRET , almacenadas en los archivos env/.env.local y env/.env.local.user y los registra en el almacén. También habilita la clave de prueba para el intercambio de código (PKCE) como una medida de seguridad adicional. A continuación, toma el identificador de entrada del almacén y lo escribe en el archivo de entorno env/.env.local. El resultado de esta tarea es una variable de entorno denominada OAUTH2AUTHCODE_CONFIGURATION_ID. Microsoft 365 Agents Toolkit escribe el valor de esta variable en el archivo appPackages/ai-plugin.json que contiene la definición del complemento. En tiempo de ejecución, el agente declarativo que carga el complemento de API, usa este identificador para recuperar la información de OAuth del almacén e iniciar y autenticar el flujo para obtener un token de acceso.

    Importante

    La tarea oauth/register solo es responsable de registrar la información de OAuth en el almacén si aún no existe. Si la información ya existe, microsoft 365 Agents Toolkit omitirá la ejecución de esta tarea.

  3. A continuación, busque la tarea oauth/update .

    - uses: oauth/update
      with:
        name: oAuth2AuthCode
        appId: ${{TEAMS_APP_ID}}
        apiSpecPath: ./appPackage/apiSpecificationFile/repair.yml
        configurationId: ${{OAUTH2AUTHCODE_CONFIGURATION_ID}}
        isPKCEEnabled: true
    

    La tarea mantiene la información de OAuth en el almacén sincronizado con el proyecto. Es necesario que el proyecto funcione correctamente. Una de las propiedades clave es la dirección URL en la que está disponible el complemento de API. Cada vez que inicie el proyecto, Microsoft 365 Agents Toolkit abre un túnel de desarrollo en una nueva dirección URL. La información de OAuth del almacén debe hacer referencia a esta dirección URL para que Copilot pueda acceder a la API.

Examen de la configuración de autenticación y autorización

La siguiente parte que se va a explorar es la configuración de autenticación y autorización del Azure Functions. La API de este ejercicio usa las funcionalidades integradas de autenticación y autorización de Azure Functions. Microsoft 365 Agents Toolkit configura estas funcionalidades al aprovisionar Azure Functions en Azure.

En Visual Studio Code:

  1. Abra el archivo infra/azure.bicep .

  2. Busque el recurso authSettings :

    resource authSettings 'Microsoft.Web/sites/config@2021-02-01' = {
      parent: functionApp
      name: 'authsettingsV2'
      properties: {
        globalValidation: {
          requireAuthentication: true
          unauthenticatedClientAction: 'Return401'
        }
        identityProviders: {
          azureActiveDirectory: {
            enabled: true
            registration: {
              openIdIssuer: oauthAuthority
              clientId: aadAppClientId
            }
            validation: {
              allowedAudiences: [
                aadAppClientId
                aadApplicationIdUri
              ]
            }
          }
        }
      }
    }
    

    Este recurso habilita las funcionalidades integradas de autenticación y autorización en la aplicación Azure Functions. En primer lugar, en la sección globalValidation , define que la aplicación solo permite solicitudes autenticadas. Si la aplicación recibe una solicitud no autenticada, la rechaza con un error HTTP 401. A continuación, en la sección identityProviders, la configuración define que usa Microsoft Entra ID (anteriormente conocida como Azure Active Directory) para autorizar las solicitudes. Especifica qué Microsoft Entra registro de aplicaciones usa para proteger la API y qué audiencias pueden llamar a la API.

Examen del registro de la aplicación Microsoft Entra

La parte final que se debe examinar es el registro de aplicación Microsoft Entra que el proyecto usa para proteger la API. Cuando se usa OAuth, se protege el acceso a los recursos mediante una aplicación. Normalmente, la aplicación define las credenciales necesarias para obtener un token de acceso, como un secreto de cliente o un certificado. También especifica los distintos permisos (también conocidos como ámbitos) que el cliente puede solicitar al llamar a la API. Microsoft Entra registro de aplicaciones representa una aplicación en la nube de Microsoft y define una aplicación para su uso con flujos de autorización de OAuth.

En Visual Studio Code:

  1. Abra el archivo ./aad.manifest.json .

  2. Busque la propiedad oauth2Permissions .

    "oauth2Permissions": [
      {
        "adminConsentDescription": "Allows Copilot to read repair records on your behalf.",
        "adminConsentDisplayName": "Read repairs",
        "id": "${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}",
        "isEnabled": true,
        "type": "User",
        "userConsentDescription": "Allows Copilot to read repair records.",
        "userConsentDisplayName": "Read repairs",
        "value": "repairs_read"
      }
    ],
    

    La propiedad define un ámbito personalizado, denominado repairs_read que concede al cliente el permiso para leer las reparaciones de la API de reparaciones.

  3. Busque la propiedad identifierUris .

    "identifierUris": [
      "api://${{AAD_APP_CLIENT_ID}}"
    ]
    

    La propiedad identifierUris define un identificador que se usa para calificar completamente el ámbito.

Pruebe el agente declarativo con el complemento de API en Microsoft 365 Copilot

El último paso consiste en probar el agente declarativo con el complemento de API en Microsoft 365 Copilot.

En Visual Studio Code:

  1. En la barra de actividad, active la extensión Microsoft 365 Agents Toolkit .

  2. En el panel de extensión microsoft 365 Agents Toolkit , en la sección Cuentas , asegúrese de que ha iniciado sesión en su inquilino de Microsoft 365 con Copilot habilitado.

    Captura de pantalla de Microsoft 365 Agents Toolkit que muestra el estado de la conexión a Microsoft 365.

  3. En la barra de actividad, cambie a la vista Ejecutar y depurar .

  4. En la lista de configuraciones, elija Depurar en Copilot (Edge) y presione el botón reproducir para iniciar la depuración.

    Captura de pantalla de la opción de depuración en Visual Studio Code.

    Visual Studio Code abre un nuevo explorador web con Microsoft 365 Copilot. Si se le solicita, inicie sesión con la cuenta de Microsoft 365.

En el explorador web:

  1. En el panel lateral, seleccione el agente da-repairs-oauthlocal .

    Captura de pantalla del agente personalizado que se muestra en Microsoft 365 Copilot.

  2. En el cuadro de texto del símbolo del sistema, escriba Show repair records assigned to Karin Blair y envíe el mensaje.

    Sugerencia

    En lugar de escribir el símbolo del sistema, puede seleccionarlo en los inicios de la conversación.

    Captura de pantalla de una conversación iniciada en el agente declarativo personalizado.

  3. Confirme que desea enviar datos al complemento de API mediante el botón Permitir siempre .

    Captura de pantalla del símbolo del sistema para permitir el envío de datos a la API.

  4. Cuando se le solicite, inicie sesión en la API para seguir usando la misma cuenta que usa para iniciar sesión en su inquilino de Microsoft 365; para ello, seleccione Iniciar sesión en da-repairs-oauthlocal.

    Captura de pantalla del símbolo del sistema para iniciar sesión en la aplicación que protege la API.

  5. Espere a que el agente responda.

    Captura de pantalla de la respuesta del agente declarativo al mensaje del usuario.

Aunque la API es accesible de forma anónima porque se ejecuta en el equipo local, Microsoft 365 Copilot llama a la API autenticada como se especifica en la especificación de API. Puede comprobar que la solicitud contiene un token de acceso estableciendo un punto de interrupción en la función de reparaciones y enviando otro mensaje en el agente declarativo. Cuando el código llegue al punto de interrupción, expanda la colección req.headers y busque el encabezado de autorización que contiene un token web JSON (JWT).

Captura de pantalla de Visual Studio Code con un punto de interrupción y el panel de depuración que muestra el encabezado de autorización en la solicitud entrante.

Detenga la sesión de depuración en Visual Studio Code cuando haya terminado de realizar las pruebas.