使用 Bot 連線 or API 進行驗證

您的 Bot 會透過安全通道使用 HTTP 與 Bot 連線 or 服務通訊(SSL/TLS)。 當您的 Bot 將要求傳送至 連線 or 服務時,它必須包含 連線 or 服務可用來驗證其身分識別的資訊。 同樣地,當 連線 or 服務傳送要求給您的 Bot 時,它必須包含 Bot 可用來驗證其身分識別的資訊。 本文說明 Bot 與 Bot 連線 or 服務之間所發生的服務層級驗證的驗證技術和需求。 如果您要撰寫自己的驗證程式碼,您必須實作本文所述的安全性程式,讓您的 Bot 能夠與 Bot 連線 or 服務交換訊息。

重要

如果您正在撰寫自己的驗證程序代碼,請務必正確實作所有安全性程式。 藉由實作本文中的所有步驟,您可以降低攻擊者能夠讀取傳送至 Bot 的訊息、傳送模擬 Bot 的訊息,以及竊取秘密密鑰的風險。

如果您使用 Bot Framework SDK,就不需要實作本文所述的安全性程式,因為 SDK 會自動為您執行。 只要使用您在註冊期間為 Bot 取得的應用程式識別碼和密碼來設定專案,SDK 就會處理其餘專案。

驗證技術

四種驗證技術可用來建立 Bot 與 Bot 連線 or 之間的信任:

技術 描述
SSL/TLS SSL/TLS 用於所有服務對服務連線。 X.509v3 憑證可用來建立所有 HTTPS 服務的身分識別。 客戶端應該一律檢查服務憑證,以確保它們受信任且有效。 (客戶端憑證不會作為此配置的一部分使用。
OAuth 2.0 OAuth 2.0 使用 Microsoft Entra ID 帳戶登入服務來產生安全令牌,Bot 可用來傳送訊息。 此令牌是服務對服務令牌;不需要使用者登入。
JSON Web 令牌 (JWT) JSON Web 令牌可用來編碼傳送至 Bot 和從 Bot 傳送的令牌。 客戶端應該根據本文中所述的需求,完整驗證他們收到的所有 JWT 令牌。
OpenID 元數據 Bot 連線 or 服務會發佈一份有效的令牌清單,用來將自己的 JWT 令牌簽署至已知靜態端點的 OpenID 元數據。

本文說明如何透過標準 HTTPS 和 JSON 使用這些技術。 雖然您可能會發現 OpenID 和其他工具的協助程式很有用,但不需要任何特殊的 SDK。

驗證 Bot 對 Bot 連線 or 服務的要求

若要與 Bot 連線 or 服務通訊,您必須使用下列格式,在每個 API 要求的標頭中Authorization指定存取權杖:

Authorization: Bearer ACCESS_TOKEN

若要取得並使用 Bot 的 JWT 令牌:

  1. 您的 Bot 會將 GET HTTP 要求傳送至 MSA 登入服務。
  2. 服務的回應包含要使用的 JWT 令牌。
  3. 您的 Bot 會在 Bot 連線 or 服務的要求中,在授權標頭中包含此 JWT 令牌。

步驟 1:從 Microsoft Entra ID 帳戶登入服務要求存取令牌

重要

如果您尚未這麼做,您必須 向 Bot Framework 註冊 Bot ,以取得其 AppID 和密碼。 您需要 Bot 的應用程式識別碼和密碼,才能要求存取令牌。

您的 Bot 身分識別可以透過數種不同的方式在 Azure 中管理。

  • 身為 使用者指派的受控識別,因此您不需要自行管理 Bot 的認證。
  • 作為單一 用戶應用程式。
  • 作為多租用戶應用程式。

根據 Bot 的應用程式類型要求存取令牌。

若要向登入服務要求存取令牌,請發出下列要求,將 MICROSOFT-APP-ID 和 MICROSOFT-APP-PASSWORD 取代為您向 Bot 服務註冊 Bot 時所取得的 AppID 和密碼。

POST https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=MICROSOFT-APP-ID&client_secret=MICROSOFT-APP-PASSWORD&scope=https%3A%2F%2Fapi.botframework.com%2F.default

步驟 2:從 Microsoft Entra ID 帳戶登入服務回應取得 JWT 令牌

如果您的應用程式是由登入服務授權,JSON 回應本文會指定您的存取令牌、其類型和到期時間(以秒為單位)。

將令牌新增至 Authorization 要求的標頭時,您必須使用此回應中指定的確切值,不要逸出或編碼令牌值。 存取令牌在到期前有效。 若要防止令牌到期影響 Bot 的效能,您可以選擇快取並主動重新整理令牌。

此範例顯示來自 Microsoft Entra ID 帳戶登入服務的回應:

HTTP/1.1 200 OK
... (other headers)
{
    "token_type":"Bearer",
    "expires_in":3600,
    "ext_expires_in":3600,
    "access_token":"eyJhbGciOiJIUzI1Ni..."
}

步驟 3:在要求的授權標頭中指定 JWT 令牌

當您將 API 要求傳送至 Bot 連線 or 服務時,請使用下列格式在要求的標頭中Authorization指定存取權杖:

Authorization: Bearer ACCESS_TOKEN

您傳送至 Bot 連線 or 服務的所有要求都必須在標頭中包含Authorization存取令牌。 如果令牌的格式正確、未過期,而且是由 Microsoft Entra ID 帳戶登入服務所產生,Bot 連線 or 服務將會授權要求。 系統會執行其他檢查,以確保令牌屬於傳送要求的 Bot。

下列範例示範如何在要求的標頭中 Authorization 指定存取令牌。

POST https://smba.trafficmanager.net/teams/v3/conversations/12345/activities
Authorization: Bearer eyJhbGciOiJIUzI1Ni...

(JSON-serialized Activity message goes here)

重要

只有在傳送至 Bot 連線 or 服務的要求標頭中Authorization指定 JWT 令牌。 請勿透過不安全的通道傳送令牌,請勿將令牌包含在您傳送給其他服務的 HTTP 要求中。 您從 Microsoft Entra ID 帳戶登入服務取得的 JWT 令牌就像是密碼,而且應該非常小心處理。 擁有令牌的任何人都可以使用它代表 Bot 執行作業。

Bot 連線 or:範例 JWT 元件

header:
{
  typ: "JWT",
  alg: "RS256",
  x5t: "<SIGNING KEY ID>",
  kid: "<SIGNING KEY ID>"
},
payload:
{
  aud: "https://api.botframework.com",
  iss: "https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/",
  nbf: 1481049243,
  exp: 1481053143,
  appid: "<YOUR MICROSOFT APP ID>",
  ... other fields follow
}

注意

實際欄位在實務上可能會有所不同。 建立並驗證上述指定的所有 JWT 令牌。

向 Bot 驗證來自 Bot 連線 or 服務的要求

當 Bot 連線 or 服務將要求傳送至 Bot 時,它會在要求的標頭中Authorization指定已簽署的 JWT 令牌。 Bot 可以驗證已簽署 JWT 令牌的真實性,以驗證 Bot 連線 or 服務的呼叫。

若要驗證來自 Bot 連線 or 服務的呼叫:

  1. 您的 Bot 會從 Bot 連線 or 服務所傳送的要求中,從授權標頭取得 JWT 令牌。
  2. 您的 Bot 會取得 Bot 連線 or 服務的 OpenID 元數據檔。
  3. 您的 Bot 會從檔案取得有效的簽署金鑰清單。
  4. 您的 Bot 會驗證 JWT 令牌的真實性。

步驟 2:取得 OpenID 元數據檔

OpenID 元數據檔會指定第二份檔的位置,其中列出 Bot 連線 or 服務的有效簽署密鑰。 若要取得 OpenID 元資料檔,請透過 HTTPS 發出此要求:

GET https://login.botframework.com/v1/.well-known/openidconfiguration

提示

這是靜態 URL,您可以硬式編碼到您的應用程式。

下列範例顯示針對要求傳 GET 回的 OpenID 元數據檔。 屬性jwks_uri會指定包含 Bot 連線 or 服務有效簽署金鑰的檔案位置。

{
    "issuer": "https://api.botframework.com",
    "authorization_endpoint": "https://invalid.botframework.com",
    "jwks_uri": "https://login.botframework.com/v1/.well-known/keys",
    "id_token_signing_alg_values_supported": [
      "RS256"
    ],
    "token_endpoint_auth_methods_supported": [
      "private_key_jwt"
    ]
}

步驟 3:取得有效簽署金鑰的清單

若要取得有效的簽署金鑰清單,請透過 HTTPS 向 OpenID 元資料檔中 屬性所jwks_uri指定的 URL 發出GET要求。 例如:

GET https://login.botframework.com/v1/.well-known/keys

回應本文會以 JWK 格式指定檔,但也包含每個索引鍵的額外屬性:endorsements

提示

索引鍵清單穩定且可能快取,但可以隨時新增新的密鑰。 為了確保 Bot 在使用這些金鑰之前有檔的最新複本,所有 Bot 實例都應該每隔 24 小時至少重新整理一次檔的本機快取

endorsements每個索引鍵內的 屬性都包含一或多個簽署字串,可用來驗證傳入要求之 Activity 物件中channelId指定之屬性中的通道標識碼是否真實。 每個 Bot 內可設定需要簽署的通道標識碼清單。 根據預設,它會是所有已發佈通道標識符的清單,不過 Bot 開發人員可能會以任一方式覆寫選取的通道標識碼值。

步驟 4:驗證 JWT 令牌

若要驗證 Bot 連線 or 服務所傳送令牌的真實性,您必須從Authorization要求的標頭擷取令牌、剖析令牌、驗證其內容,以及驗證其簽章。

JWT 剖析連結庫適用於許多平臺,而且大部分都針對 JWT 令牌實作安全且可靠的剖析,不過您通常必須設定這些連結庫,以要求令牌的某些特性(其簽發者、物件等等)包含正確的值。 剖析權杖時,您必須設定剖析連結庫,或撰寫自己的驗證,以確保令牌符合下列需求:

  1. 令牌是使用 「Bearer」 配置在 HTTP Authorization 標頭中傳送的。
  2. 令牌是符合 JWT 標準的有效 JSON。
  3. 令牌包含值為 https://api.botframework.com的「簽發者」宣告。
  4. 令牌包含值等於 Bot 的 Microsoft 應用程式識別碼的「物件」宣告。
  5. 令牌在其有效期間內。 業界標準的時鐘扭曲為5分鐘。
  6. 令牌具有有效的密碼編譯簽章,其中包含在步驟 3 中擷取之 OpenID 密鑰檔中所列的密鑰,其使用步驟 2 中所擷取之 Open ID Metadata 檔的 屬性中指定的id_token_signing_alg_values_supported簽署演算法。
  7. 令牌包含 「serviceUrl」 宣告,其值符合serviceUrl傳入要求之 Activity 物件根目錄的屬性。

如果需要通道識別碼的簽署:

  • 您應該要求傳送至具有該通道標識碼之 Bot 的任何 Activity 物件都隨附以該通道簽署的 JWT 令牌。
  • 如果簽署不存在,您的 Bot 應該傳回 HTTP 403(禁止) 狀態代碼來拒絕要求。

重要

所有這些需求都很重要,尤其是需求 4 和 6。 如果無法實作所有這些驗證需求,Bot 就會讓 Bot 開啟攻擊,這可能會導致 Bot 洩露其 JWT 令牌。

實作者不應該公開一種方式,以停用傳送至 Bot 的 JWT 令牌驗證。

連線 或 Bot:範例 JWT 元件

header:
{
  typ: "JWT",
  alg: "RS256",
  x5t: "<SIGNING KEY ID>",
  kid: "<SIGNING KEY ID>"
},
payload:
{
  aud: "<YOU MICROSOFT APP ID>",
  iss: "https://api.botframework.com",
  nbf: 1481049243,
  exp: 1481053143,
  ... other fields follow
}

注意

實際欄位在實務上可能會有所不同。 建立並驗證上述指定的所有 JWT 令牌。

驗證 Bot Framework 模擬器對 Bot 的要求

Bot Framework 模擬器 是一種桌面工具,可用來測試 Bot 的功能。 雖然 Bot Framework 模擬器使用相同的驗證技術,但無法模擬實際的 Bot 連線 or 服務。 相反地,它會使用您在將模擬器連線至 Bot 時指定的 Microsoft 應用程式識別碼和 Microsoft 應用程式密碼,來建立與 Bot 所建立令牌相同的令牌。 當模擬器將要求傳送至 Bot 時,它會在要求的標頭中 Authorization 指定 JWT 令牌,基本上是使用 Bot 本身的認證來驗證要求。

如果您要實作驗證連結庫,而且想要接受來自 Bot Framework 模擬器的要求,您必須新增此額外的驗證路徑。 路徑的結構類似於 連線 or -> Bot 驗證路徑,但它會使用 MSA 的 OpenID 檔,而不是 Bot 連線 or 的 OpenID 檔。

若要驗證來自 Bot Framework 模擬器的呼叫:

  1. 您的 Bot 會從 Bot Framework 模擬器所傳送的要求中,從授權標頭取得 JWT 令牌。
  2. 您的 Bot 會取得 Bot 連線 or 服務的 OpenID 元數據檔。
  3. 您的 Bot 會從檔案取得有效的簽署金鑰清單。
  4. 您的 Bot 會驗證 JWT 令牌的真實性。

步驟 2:取得 MSA OpenID 元數據檔

OpenID 元資料檔會指定列出有效簽署金鑰的第二份檔的位置。 若要取得 MSA OpenID 元資料檔,請透過 HTTPS 發出此要求:

GET https://login.microsoftonline.com/botframework.com/v2.0/.well-known/openid-configuration

下列範例顯示針對要求傳 GET 回的 OpenID 元數據檔。 屬性 jwks_uri 會指定包含有效簽署金鑰的檔案位置。

{
    "authorization_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
    "token_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/token",
    "token_endpoint_auth_methods_supported":["client_secret_post","private_key_jwt"],
    "jwks_uri":"https://login.microsoftonline.com/common/discovery/v2.0/keys",
    ...
}

步驟 3:取得有效簽署金鑰的清單

若要取得有效的簽署金鑰清單,請透過 HTTPS 向 OpenID 元資料檔中 屬性所jwks_uri指定的 URL 發出GET要求。 例如:

GET https://login.microsoftonline.com/common/discovery/v2.0/keys
Host: login.microsoftonline.com

回應本文會以 JWK 格式指定檔

步驟 4:驗證 JWT 令牌

若要驗證模擬器所傳送令牌的真實性,您必須從 Authorization 要求的標頭擷取令牌、剖析令牌、驗證其內容,以及驗證其簽章。

JWT 剖析連結庫適用於許多平臺,而且大部分都針對 JWT 令牌實作安全且可靠的剖析,不過您通常必須設定這些連結庫,以要求令牌的某些特性(其簽發者、物件等等)包含正確的值。 剖析權杖時,您必須設定剖析連結庫,或撰寫自己的驗證,以確保令牌符合下列需求:

  1. 令牌是使用 「Bearer」 配置在 HTTP Authorization 標頭中傳送的。
  2. 令牌是符合 JWT 標準的有效 JSON。
  3. 令牌包含「簽發者」宣告,其中包含非政府案例的 其中一個醒目提示值 。 檢查這兩個簽發者值可確保您檢查安全性通訊協定 v3.1 和 v3.2 簽發者值。
  4. 令牌包含值等於 Bot 的 Microsoft 應用程式識別碼的「物件」宣告。
  5. 模擬器會根據版本,透過appid宣告(第1版)或授權方宣告(第2版)傳送AppId。
  6. 令牌在其有效期間內。 業界標準的時鐘扭曲為5分鐘。
  7. 令牌具有有效的密碼編譯簽章,其中包含在步驟 3擷取的 OpenID 金鑰檔中所列的密鑰。

注意

需求 5 是模擬器驗證路徑的特定專案。

如果令牌不符合所有這些需求,您的 Bot 應該傳回 HTTP 403(禁止) 狀態代碼來終止要求。

重要

所有這些需求都很重要,尤其是需求 4 和 7。 如果無法實作所有這些驗證需求,Bot 就會讓 Bot 開啟攻擊,這可能會導致 Bot 洩露其 JWT 令牌。

模擬器至 Bot:範例 JWT 元件

header:
{
  typ: "JWT",
  alg: "RS256",
  x5t: "<SIGNING KEY ID>",
  kid: "<SIGNING KEY ID>"
},
payload:
{
  aud: "<YOUR MICROSOFT APP ID>",
  iss: "https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/",
  nbf: 1481049243,
  exp: 1481053143,
  ... other fields follow
}

注意

實際欄位在實務上可能會有所不同。 建立並驗證上述指定的所有 JWT 令牌。

安全性通訊協議變更

Bot 連線 or 驗證

OAuth 登入 URL

通訊協定版本 有效值
v3.1 和 v3.2 https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token

OAuth 範圍

通訊協定版本 有效值
v3.1 和 v3.2 https://api.botframework.com/.default

連線 或 Bot 驗證

OpenID 元數據檔

通訊協定版本 有效值
v3.1 和 v3.2 https://login.botframework.com/v1/.well-known/openidconfiguration

JWT 簽發者

通訊協定版本 有效值
v3.1 和 v3.2 https://api.botframework.com

模擬器對 Bot 驗證

OAuth 登入 URL

通訊協定版本 有效值
v3.1 和 v3.2 https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token

OAuth 範圍

通訊協定版本 有效值
v3.1 和 v3.2 Bot 的 Microsoft 應用程式識別碼 + /.default

JWT 物件

通訊協定版本 有效值
v3.1 和 v3.2 Bot 的 Microsoft 應用程式識別碼

JWT 簽發者

通訊協定版本 有效值
v3.1 1.0 https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/
v3.1 2.0 https://login.microsoftonline.com/d6d49420-f39b-4df7-a1dc-d59a935871db/v2.0
v3.2 1.0 https://sts.windows.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a/
v3.2 2.0 https://login.microsoftonline.com/f8cdef31-a31e-4b4a-93e4-5f571e91255a/v2.0

請參閱非政府案例的醒目提示值

OpenID 元數據檔

通訊協定版本 有效值
v3.1 和 v3.2 https://login.microsoftonline.com/botframework.com/v2.0/.well-known/openid-configuration

其他資源