Exercício - Integrar um plug-in de API com uma API protegida com OAuth

Concluído

Os plug-ins de API para o Microsoft 365 Copilot permitem a integração com APIs protegidas pelo OAuth. Você mantém a ID do cliente e o segredo do aplicativo que protege sua API seguros registrando-os no cofre do Teams. Em tempo de execução, o Microsoft 365 Copilot executa seu plug-in, recupera as informações do cofre e as usa para obter um token de acesso e chamar a API. Seguindo esse processo, a ID do cliente e o segredo permanecem seguros e nunca são expostos ao cliente.

Abrir o projeto de exemplo

Comece baixando o projeto de exemplo:

  1. Em um navegador da web, acesse https://aka.ms/learn-da-api-ts-repairs. Você recebe um prompt para baixar um arquivo ZIP com o projeto de exemplo.
  2. Salve o arquivo ZIP no computador.
  3. Extraia o conteúdo do arquivo ZIP.
  4. Abra a pasta no Visual Studio Code.

O projeto de exemplo é um projeto do Kit de Ferramentas de Agentes do Microsoft 365 que inclui um agente declarativo, um plug-in de API e uma API protegida com o Microsoft Entra ID. A API está em execução no Azure Functions e implementa a segurança usando os recursos internos de autenticação e autorização do Azure Functions, às vezes chamados de Easy Auth.

Examinar a configuração de autorização OAuth2

Antes de continuar, examine a configuração de autorização OAuth2 no projeto de exemplo.

Examinar a definição de API

Primeiro, dê uma olhada na configuração de segurança da definição de API incluída no projeto.

No Visual Studio Code:

  1. Abra o arquivo appPackage/apiSpecificationFile/repair.yml .

  2. Na seção components.securitySchemes , observe a propriedade 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 
    

    A propriedade define um esquema de segurança OAuth2 e inclui informações sobre as URLs a serem chamadas para obter um token de acesso e quais escopos a API usa.

    Importante

    Observe que o escopo é totalmente qualificado com o URI da ID do aplicativo (api://...). Ao trabalhar com o Microsoft Entra, você precisa qualificar totalmente os escopos personalizados. Quando o Microsoft Entra vê um escopo não qualificado, ele presume que ele pertence ao Microsoft Graph, o que leva a erros de fluxo de autorização.

  3. Localize a propriedade paths./repairs.get.security . Observe que ele faz referência ao esquema de segurança oAuth2AuthCode e ao escopo de que o cliente precisa para executar a operação.

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

    Importante

    A listagem dos escopos necessários na especificação da API é puramente informativa. Ao implementar a API, você é responsável por validar o token e verificar se ele contém os escopos necessários.

Examine a implementação da API

Em seguida, dê uma olhada na implementação da API.

No Visual Studio Code:

  1. Abra o arquivo src/functions/repairs.ts .

  2. Na função de manipulador de reparos , localize a seguinte linha que verifica se a solicitação contém um token de acesso com os escopos necessários:

    if (!hasRequiredScopes(req, 'repairs_read')) {
      return {
        status: 403,
        body: "Insufficient permissions",
      };
    }
    
  3. A função hasRequiredScopes é implementada ainda mais no arquivo 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;
      }
    }
    

    A função começa extraindo o token de portador do cabeçalho da solicitação de autorização. Em seguida, ele usa o pacote jwt-decode para decodificar o token e obter a lista de escopos da declaração scp . Por fim, ele verifica se a declaração scp contém todos os escopos necessários.

    Observe que a função não está validando o token de acesso. Em vez disso, ele só verifica se o token de acesso contém os escopos necessários. Neste modelo, a API está em execução no Azure Functions e implementa a segurança usando o Easy Auth, que é responsável por validar o token de acesso. Se a solicitação não contiver um token de acesso válido, o runtime do Azure Functions o rejeitará antes que ele atinja seu código. Embora o Easy Auth valide o token, ele não marca os escopos necessários, o que você precisa fazer por conta própria.

Examinar a configuração da tarefa do cofre

Neste projeto, você usa o Microsoft 365 Agents Toolkit para adicionar as informações do OAuth ao cofre. O Microsoft 365 Agents Toolkit registra as informações de OAuth no cofre usando uma tarefa especial na configuração do projeto.

No Visual Studio Code:

  1. Abra o arquivo ./teampsapp.local.yml .

  2. Na seção provisionamento , localize a tarefa 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
    

    A tarefa pega os valores das variáveis de projeto TEAMS_APP_ID, AAD_APP_CLIENT_ID e SECRET_AAD_APP_CLIENT_SECRET , armazenados nos arquivos env/.env.local e env/.env.local.user e os registra no cofre. Ela também habilita a PKCE (Chave de Prova para Troca de Código) como uma medida de segurança extra. Em seguida, ele pega a ID de entrada do cofre e a grava no arquivo de ambiente env/.env.local. O resultado dessa tarefa é uma variável de ambiente chamada OAUTH2AUTHCODE_CONFIGURATION_ID. O Microsoft 365 Agents Toolkit grava o valor dessa variável no arquivo appPackages/ai-plugin.json que contém a definição do plug-in. No tempo de execução, o agente declarativo que carrega o plug-in da API usa essa ID para recuperar as informações do OAuth do cofre e iniciar um fluxo de autenticação para obter um token de acesso.

    Importante

    A tarefa oauth/register só é responsável por registrar as informações do OAuth no cofre se elas ainda não existirem. Se as informações já existirem, o Microsoft 365 Agents Toolkit ignorará a execução dessa tarefa.

  3. Em seguida, localize a tarefa oauth/update .

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

    A tarefa mantém as informações do OAuth no cofre sincronizadas com seu projeto. É necessário que seu projeto funcione corretamente. Uma das principais propriedades é a URL na qual seu plug-in de API está disponível. Sempre que você inicia seu projeto, o Kit de Ferramentas de Agentes do Microsoft 365 abre um túnel de desenvolvimento em uma nova URL. As informações do OAuth no cofre precisam fazer referência a essa URL para que o Copilot possa acessar sua API.

Examinar a configuração de autenticação e autorização

A próxima parte a ser explorada são as configurações de autenticação e autorização do Azure Functions. A API neste exercício usa os recursos internos de autenticação e autorização do Azure Functions. O Microsoft 365 Agents Toolkit configura esses recursos ao provisionar o Azure Functions para o Azure.

No Visual Studio Code:

  1. Abra o arquivo infra/azure.bicep .

  2. Localize o 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
              ]
            }
          }
        }
      }
    }
    

    Esse recurso habilita os recursos internos de autenticação e autorização no aplicativo do Azure Functions. Primeiro, na seção globalValidation , ele define que o aplicativo só permite solicitações autenticadas. Se o aplicativo receber uma solicitação não autenticada, ele a rejeitará com um erro HTTP 401. Em seguida, na seção identityProviders, a configuração define que ele usa o Microsoft Entra ID (anteriormente conhecido como Azure Active Directory) para autorizar solicitações. Ele especifica qual registro do aplicativo Microsoft Entra ele usa para proteger a API e quais audiências têm permissão para chamar a API.

Examine o registro do aplicativo Microsoft Entra

A parte final a ser examinada é o registro do aplicativo Microsoft Entra que o projeto usa para proteger a API. Ao usar o OAuth, você protege o acesso aos recursos usando um aplicativo. O aplicativo normalmente define as credenciais necessárias para obter um token de acesso, como um segredo do cliente ou um certificado. Ele também especifica as diferentes permissões (também conhecidas como escopos) que o cliente pode solicitar ao chamar a API. O registro de aplicativo do Microsoft Entra representa um aplicativo na nuvem da Microsoft e define um aplicativo para uso com fluxos de autorização OAuth.

No Visual Studio Code:

  1. Abra o arquivo ./aad.manifest.json .

  2. Localize a propriedade 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"
      }
    ],
    

    A propriedade define um escopo personalizado, chamado repairs_read que concede ao cliente a permissão para ler reparos da API de reparos.

  3. Localize a propriedade identifierUris .

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

    A propriedade identifierUris define um identificador usado para qualificar totalmente o escopo.

Teste o agente declarativo com o plug-in de API no Microsoft 365 Copilot

A etapa final é testar o agente declarativo com o plug-in de API no Microsoft 365 Copilot.

No Visual Studio Code:

  1. Na Barra de Atividades, ative a extensão Microsoft 365 Agents Toolkit .

  2. No painel de extensão do Kit de Ferramentas de Agentes do Microsoft 365 , na seção Contas , verifique se você está conectado ao seu locatário do Microsoft 365 com o Copilot habilitado.

    Captura de tela do Kit de Ferramentas de Agentes do Microsoft 365 mostrando o status da conexão com o Microsoft 365.

  3. Na Barra de Atividades, alterne para o modo de exibição Executar e Depurar .

  4. Na lista de configurações, escolha Depurar no Copilot (Edge) e pressione o botão de reprodução para iniciar a depuração.

    Captura de tela da opção de depuração no Visual Studio Code.

    O Visual Studio Code abre um novo navegador da Web com o Microsoft 365 Copilot. Se receber a solicitação, entre com sua conta do Microsoft 365.

No navegador da Web:

  1. No painel lateral, selecione o agente da-repairs-oauthlocal .

    Captura de tela do agente personalizado exibido no Microsoft 365 Copilot.

  2. Na caixa de texto do prompt, digite Show repair records assigned to Karin Blair e envie o prompt.

    Dica

    Em vez de digitar o prompt, você pode selecioná-lo nos iniciadores de conversa.

    Captura de tela de uma conversa iniciada no agente declarativo personalizado.

  3. Confirme que deseja enviar dados para o plug-in da API usando o botão Sempre permitir .

    Captura de tela do prompt para permitir o envio de dados para a API.

  4. Quando solicitado, entre na API para continuar usando a mesma conta que você usa para entrar em seu locatário do Microsoft 365, selecionando Entrar em da-repairs-oauthlocal.

    Captura de tela do prompt para entrar no aplicativo que protege a API.

  5. Aguarde a resposta do agente.

    Captura de tela da resposta do agente declarativo ao prompt do usuário.

Embora sua API possa ser acessada anonimamente porque está em execução no computador local, o Microsoft 365 Copilot está chamando sua API autenticada conforme especificado na especificação da API. Você pode verificar se a solicitação contém um token de acesso, definindo um ponto de interrupção na função de reparos e enviando outro prompt no agente declarativo. Quando o código atingir seu ponto de interrupção, expanda a coleção req.headers e procure o cabeçalho de autorização que contém um JSON Web Token (JWT).

Captura de tela do Visual Studio Code com um ponto de interrupção e o painel de depuração mostrando o cabeçalho de autorização na solicitação de entrada.

Interrompa a sessão de depuração no Visual Studio Code quando terminar de testar.