練習 - 整合 API 外掛程式與使用 OAuth 保護的 API

已完成

適用於 Microsoft 365 Copilot的 API 外掛程式可讓您與使用 OAuth 保護的 API 整合。 您可以在 Teams 保存庫中註冊保護 API 的應用程式用戶端識別碼和秘密,以保護其安全。 在運行時間,Microsoft 365 Copilot 執行外掛程式、從保存庫擷取資訊,並使用它來取得存取令牌並呼叫 API。 藉由遵循此程式,用戶端標識碼和秘密會保持安全,且永遠不會向客戶端公開。

開啟範例專案

從下載範例項目開始:

  1. 在網頁瀏覽器中,瀏覽至 https://aka.ms/learn-da-api-ts-repairs。 您會收到使用範例項目下載 ZIP 檔案的提示。
  2. 將 ZIP 檔案儲存在您的電腦上。
  3. 解壓縮 ZIP 檔案內容。
  4. 在 Visual Studio Code 中開啟資料夾。

範例專案是Microsoft 365 代理程式工具組專案,其中包含宣告式代理程式、API 外掛程式,以及使用 Microsoft Entra ID 保護的 API。 API 是在 Azure Functions 上執行,並使用 Azure Functions 的內建驗證和授權功能來實作安全性,有時稱為「簡單驗證」。

檢查 OAuth2 授權組態

繼續之前,請先檢查範例專案中的 OAuth2 授權組態。

檢查 API 定義

首先,請查看專案中所包含 API 定義的安全性組態。

在 Visual Studio Code:

  1. 開啟 appPackage/apiSpecificationFile/repair.yml 檔案。

  2. components.securitySchemes 區 段中,請注意 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 
    

    屬性會定義 OAuth2 安全性配置,並包含要呼叫以取得存取令牌的 URL 相關信息,以及 API 所使用的範圍。

    重要事項

    請注意,範圍是完整且應用程式標識碼 URI (api://...) 。使用 Microsoft Entra 您需要完整限定自訂範圍。 當 Microsoft Entra 看到不限定的範圍時,它會假設它屬於 Microsoft Graph,這會導致授權流程錯誤。

  3. 找出 paths./repairs.get.security 屬性。 請注意,它會參考客戶端執行作業所需的 oAuth2AuthCode 安全性配置和範圍。

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

    重要事項

    在 API 規格中列出必要的範圍純粹是資訊。 實作 API 時,您必須負責驗證令牌,並檢查其是否包含必要的範圍。

檢查 API 實作

接下來,請查看 API 實作。

在 Visual Studio Code:

  1. 開啟 src/functions/repairs.ts 檔案。

  2. repairs 處理程式函式中,找出下列這一行,檢查要求是否包含具有必要範圍的存取令牌:

    if (!hasRequiredScopes(req, 'repairs_read')) {
      return {
        status: 403,
        body: "Insufficient permissions",
      };
    }
    
  3. hasRequiredScopes 函式會在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;
      }
    }
    

    函式一開始會從授權要求標頭擷取持有人令牌。 接下來,它會使用 jwt-decode 套件來譯碼令牌,並從 scp 宣告取得範圍清單。 最後,它會檢查 scp 宣告是否包含所有必要的範圍。

    請注意,函式不會驗證存取令牌。 相反地,它只會檢查存取令牌是否包含必要的範圍。 在此範本中,API 是在 Azure Functions 上執行,並使用負責驗證存取令牌的 Easy Auth 實作安全性。 如果要求未包含有效的存取令牌,Azure Functions 運行時間會在到達您的程式代碼之前拒絕它。 雖然簡單驗證會驗證令牌,但不會檢查您需要自行執行的必要範圍。

檢查保存庫工作設定

在此專案中,您會使用 Microsoft 365 代理程式工具組將 OAuth 資訊新增至保存庫。 Microsoft 365 代理程式工具組會使用項目組態中的特殊工作,在保存庫中註冊 OAuth 資訊。

在 Visual Studio Code:

  1. 開啟 ./teampsapp.local.yml 檔案。

  2. 在 [ 布建] 區段中,找出 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
    

    工作會採用儲存在 env/.env.local 和 env/.env.local.user 檔案中的 TEAMS_APP_IDAAD_APP_CLIENT_IDSECRET_AAD_APP_CLIENT_SECRET 項目變數值,並在保存庫中註冊它們。 它也會啟用 Code Exchange (PKCE) 的證明金鑰作為額外的安全性措施。 然後,它會取得保存庫項目標識符,並將它寫入環境檔案 env/.env.local。 這項工作的結果是名為 OAUTH2AUTHCODE_CONFIGURATION_ID的環境變數。 Microsoft 365 Agents Toolkit 會將此變數的值寫入包含外掛程式定義的 appPackages/ai-plugin.json 檔案。 在運行時間,會載入 API 外掛程式的宣告式代理程式會使用此標識元從保存庫擷取 OAuth 資訊,並啟動和驗證流程以取得存取令牌。

    重要事項

    oauth/register 工作只負責在保存庫中註冊 OAuth 資訊,如果 OAuth 資訊還不存在。 如果資訊已存在,Microsoft 365 代理程式工具組將會略過執行這項工作。

  3. 接下來,找出 oauth/update 工作。

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

    工作會將保存庫中的 OAuth 資訊與您的專案保持同步。 您的項目必須正常運作。 其中一個主要屬性是 API 外掛程式可用的 URL。 每次啟動專案時,Microsoft 365 代理程式工具組都會在新的 URL 上開啟開發通道。 保存庫中的 OAuth 信息必須參考此 URL,Copilot 才能連線到您的 API。

檢查驗證和授權組態

下一個要探索的部分是 Azure Functions的驗證和授權設定。 此練習中的 API 會使用 Azure Functions 的內建驗證和授權功能。 Microsoft 365 代理程式工具組會在將 Azure Functions 布建至 Azure 時設定這些功能。

在 Visual Studio Code:

  1. 開啟 infra/azure.bicep 檔案。

  2. 找出 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
              ]
            }
          }
        }
      }
    }
    

    此資源可在 Azure Functions 應用程式上啟用內建驗證和授權功能。 首先,在 globalValidation 區段中,它會定義應用程式只允許已驗證的要求。 如果應用程式收到未經驗證的要求,則會拒絕該要求,並出現 401 HTTP 錯誤。 然後,在identityProviders區段中,組態會定義它使用 Microsoft Entra ID (先前稱為 Azure Active Directory) 來授權要求。 它會指定用來保護 API 的應用程式註冊 Microsoft Entra,以及允許哪些物件呼叫 API。

檢查 Microsoft Entra 應用程式註冊

要檢查的最後一個部分是專案用來保護 API 的 Microsoft Entra 應用程式註冊。 使用 OAuth 時,您可以使用應用程式來保護對資源的存取。 應用程式通常會定義取得存取令牌所需的認證,例如客戶端密碼或憑證。 它也會指定不同的許可權 (也稱為用戶端在呼叫 API 時可要求的範圍) 。 Microsoft Entra 應用程式註冊代表Microsoft雲端中的應用程式,並定義要與 OAuth 授權流程搭配使用的應用程式。

在 Visual Studio Code:

  1. 開啟 ./aad.manifest.json 檔案。

  2. 找出 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"
      }
    ],
    

    屬性會定義名為 repairs_read 的自定義範圍,以授與客戶端從修復 API 讀取修復的許可權。

  3. 找出 identifierUris 屬性。

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

    identifierUris 屬性會定義用來完整限定範圍的標識碼。

在 Microsoft 365 Copilot 中使用 API 外掛程式測試宣告式代理程式

最後一個步驟是使用 Microsoft 365 Copilot 中的 API 外掛程式來測試宣告式代理程式。

在 Visual Studio Code:

  1. 在活動列中,啟用 Microsoft 365 Agents Toolkit 擴充功能。

  2. [Microsoft 365 代理程式工具組 擴充功能] 面板的 [ 帳戶 ] 區段中,確定您已登入已啟用 Copilot 的 Microsoft 365 租使用者。

    Microsoft 365 代理程式工具組的螢幕快照,其中顯示與 Microsoft 365 的連線狀態。

  3. 在 [活動列] 中,切換至 [ 執行和偵錯] 檢視

  4. 從組態清單中,選擇 [在 Copilot (Edge) 中進行偵錯],然後按下 [播放] 按鈕以開始偵錯。

    Visual Studio Code 中偵錯選項的螢幕快照。

    Visual Studio Code 會開啟具有 Microsoft 365 Copilot 的新網頁瀏覽器。 如果出現提示,請使用您的 Microsoft 365 帳戶登入。

在網頁瀏覽器中:

  1. 從側邊面板中,選取 da-repairs-oauthlocal 代理程式。

    顯示在 Microsoft 365 Copilot 中之自定義代理程式的螢幕快照。

  2. 在提示文字框中,輸入 Show repair records assigned to Karin Blair 並提交提示。

    提示

    您可以從交談入門中選取提示,而不是輸入提示。

    在自定義宣告式代理程式中啟動交談的螢幕快照。

  3. 確認您想要使用 [ 永遠允許 ] 按鈕將資料傳送至 API 外掛程式。

    允許將數據傳送至 API 的提示螢幕快照。

  4. 出現提示時,請選取 [登入 da-repairs-oauthlocal],以繼續使用您用來登入 Microsoft 365 租使用者的相同帳戶來登入 API。

    提示登入保護 API 之應用程式的螢幕快照。

  5. 等候代理程序回應。

    宣告式代理程式回應使用者提示的螢幕快照。

即使您的 API 在本機電腦上執行,所以可以匿名存取,Microsoft 365 Copilot 會呼叫 API 規格中指定的驗證 API。您可以在 repairs 函式中設定斷點,並在宣告式代理程式中提交另一個提示,以確認要求包含存取令牌。 當程式代碼到達斷點時,展開 req.headers 集合,並尋找包含 JSON Web 令牌 (JWT) 的授權標頭。

Visual Studio Code 的螢幕快照,其中包含斷點和偵錯面板,其中顯示傳入要求上的授權標頭。

當您完成測試時,請在 Visual Studio Code 中停止偵錯會話。