使用 OAuth 2.0 JSON Web 令牌 (JWT) 在命名空间中进行身份验证

本文介绍如何使用 OAuth 2.0 JSON Web 令牌通过 Azure 事件网格命名空间进行身份验证。

Azure 事件网格的 MQTT 代理支持 OAuth 2.0 JWT 身份验证,使客户端能够使用任何标识提供者颁发的 JSON Web 令牌(除了Microsoft Entra ID 之外)通过事件网格命名空间进行连接和身份验证。

先决条件

若要对命名空间使用 OAuth 2.0 JWT 身份验证,需要满足以下先决条件:

  • 可以颁发 JSON Web 令牌的标识提供者。
  • CA 证书,其中包括用于验证公钥证书(直接上传)的客户端令牌 (Key Vault) 或 PEM 文件的公钥。

简要步骤

若要对命名空间使用 OAuth 2.0 JWT 身份验证,请执行以下步骤:

  1. 创建命名空间并配置其子资源。

  2. 在事件网格命名空间上启用托管标识。

  3. 按照以下步骤在事件网格命名空间上配置 OAuth 2.0 身份验证设置:

    1. 创建一个 Azure Key Vault 帐户,该帐户托管包含公钥的 CA 证书,并在 Key Vault 中为命名空间的托管标识添加角色分配。
    2. 或者将公钥证书的 PEM 文件上传到命名空间。
  4. 客户端可以使用标识提供者提供的令牌连接到事件网格命名空间。

创建命名空间并配置其子资源

按照快速入门:使用 Azure 门户在事件网格命名空间上发布和订阅 MQTT 消息创建命名空间并配置其子资源。 跳过证书和客户端创建步骤,因为客户端标识来自提供的令牌。 客户端属性基于客户端令牌中的自定义声明。 客户端属性用于客户端组查询、主题模板变量和路由扩充配置。

在事件网格命名空间上启用托管标识

命名空间使用托管标识访问 Azure 密钥保管库实例,以获取自定义域的服务器证书。 使用以下命令在事件网格命名空间上启用系统分配的托管标识:

az eventgrid namespace update --resource-group <resource group name> --name <namespace name> --identity "{type:systemassigned}" 

有关使用 Azure 门户配置系统和用户分配的标识的信息,请参阅为事件网格命名空间启用托管标识

在事件网格命名空间 -Key 保管库上配置 OAuth 2.0 JWT 身份验证设置

首先,创建 Azure Key Vault 帐户,上传服务器证书,并在密钥保管库上为命名空间的托管标识分配适当的角色。 然后,使用 Azure 门户或 Azure CLI 在事件网格命名空间上配置自定义身份验证设置。 首先需要创建命名空间,然后使用以下步骤对其进行更新。

创建 Azure Key Vault 帐户并上传服务器证书

  1. 使用以下命令创建 Azure Key Vault 帐户:

    az keyvault create --name "<your-unique-keyvault-name>" --resource-group "<resource group name>" --___location "centraluseuap" 
    
  2. 使用以下命令将证书导入 Azure Key Vault

    az keyvault certificate import --vault-name "<your-key-vault-name>" -n "<cert name>" -f "<path to your certificate pem file> " 
    

    注意

    证书必须在 DNS 的使用者可选名称中包含域名。 有关详细信息,请参阅教程:在 Azure Key Vault 中导入证书

在 Azure Key Vault 中为命名空间的托管标识添加角色分配

需要使用以下步骤提供对命名空间的访问权限才能访问 Azure Key Vault 帐户:

  1. 使用以下命令获取事件网格命名空间系统托管标识主体 ID

    $principalId=(az eventgrid namespace show --resource-group <resource group name> --name <namespace name> --query identity.principalId -o tsv) 
    
  2. 获取 Azure 密钥保管库资源 ID。

    $keyVaultResourceId=(az keyvault show --resource-group <resource group name> --name <your key vault name> --query id -o tsv) 
    
  3. 在密钥保管库中为命名空间的托管标识添加角色分配。

    az role assignment create --role "Key Vault Certificate User" --assignee $principalId --scope $keyVaultResourceId 
    

    有关密钥保管库访问和门户体验的详细信息,请参阅使用 Azure 基于角色的访问控制提供对密钥保管库密钥、证书和机密的访问权限

使用 Azure 门户配置身份验证

  1. Azure 门户中,导航到事件网格命名空间。

  2. 在“事件网格命名空间”页面中,选择左侧菜单上的“配置”。

  3. 在“自定义 JWT 身份验证”部分中,指定以下属性的值

    1. 选择“启用自定义 JWT 身份验证”

    2. 令牌颁发者:输入 MQTT 客户端提供的 JWT 的颁发者声明的值。

    3. 对于“颁发者证书”,请选择“从 Azure Key Vault”。

      显示事件网格命名空间的“配置”页的“Azure Key Vault”选项选择的屏幕截图。

    4. 在新页面中,指定以下属性的值。

      1. 证书 URL:所创建的 Azure 密钥保管库中颁发者证书的证书标识符。 可以改为选择“使用密钥保管库选择证书”,从订阅中选择证书和密钥保管库

      2. 标识:用于向密钥保管库进行身份验证以访问创建的颁发者证书的标识。

      3. 选择 添加

        显示“添加颁发者证书”页的屏幕截图。

  4. 返回“配置”页面,选择“应用”

    注意

    最多可以添加两个 iss 证书用于证书/密钥轮换。

使用 Azure CLI

使用以下命令通过自定义 JWT 身份验证配置更新命名空间。

az resource update \
  --resource-type Microsoft.EventGrid/namespaces \
  --api-version 2024-06-01-preview \
  --ids /subscriptions/1111a1a1-bb2b-cc3c-dd4d-ffffee5e5e5e/resourceGroups/sample-rg/providers/Microsoft.EventGrid/namespaces/sample-namespace \
  --set properties.topicSpacesConfiguration.clientAuthentication='{
    \"customJwtAuthentication\":{
      \"tokenIssuer\":\"sample-issuer\",
      \"issuerCertificates\":[
        {
          \"certificateUrl\":\"https://sample-vault.vault.azure.net/certificates/sample-cert/12345abcdef67890\",
          \"identity\":{
            \"type\":\"UserAssigned\",
            \"userAssignedIdentity\":\"/subscriptions/1111a1a1-bb2b-cc3c-dd4d-ffffee5e5e5e/resourceGroups/sample-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/sample-identity\"
          }
        }
      ]
    }
  }'
 

JSON Web 令牌格式

JSON Web 令牌需要具有 JWT 标头、JWT 有效负载和 JWT 签名部分。

JWT 标头

标头必须至少包含 typalg 字段。 typ 必须始终是 JWSalg 必须始终是 RS256。 令牌标头必须如下所示:

{
    "typ": "JWT",
    "alg": "RS256"
}

JWT 有效负载

事件网格需要以下声明:isssubaudexpnbf

名称 描述
iss 颁发者。 JWT 中的值必须与事件网格命名空间配置中的颁发者匹配才能进行自定义 JWT 身份验证。
sub 主题。 值用作身份验证标识名称。
aud Audience。 值是字符串数组。 值必须包含标准事件网格命名空间主机名和/或该事件网格命名空间的自定义域(如果已配置)。 受众可以包含其他字符串,但至少需要其中一个字符串是标准事件网格命名空间主机名或该命名空间的自定义域。
exp Expiration。 JWT 到期时的 Unix 时间。
nbf 生效时间。 JWT 生效时的 Unit 时间。

事件网格将所有声明映射到客户端属性,前提是它们具有以下类型之一:int32stringarray of strings。 标准声明 isssubaudexpnbf 均从客户端属性中排除。 在以下 JWT 示例中,只有三个声明转换为客户端属性,num_attrstr_attrstr_list_attr,因为它们具有正确的类型 int32stringarray of strings。 incorrect_attr_1incorrect_attr_2incorrect_attr_3 不会转换为客户端属性,因为它们具有错误类型:floatarray of integersobject

{
    "iss": "correct_issuer",
    "sub": "d1",
    "aud": "testns.mqtt-broker-int.azure.net",
    "exp": 1712876224,
    "nbf": 1712869024,
    "num_attr": 1,
    "str_attr": "some string",
    "str_list_attr": [
        "string 1",
        "string 2"
    ],
    "incorrect_attr_1": 1.23,
    "incorrect_attr_2": [
        1,
        2,
        3
    ],
    "incorrect_attr_3": {
        "field": "value"
    }
}

在事件网格命名空间上配置 OAuth 2.0 JWT 身份验证设置 - 直接上传

在此步骤中,将使用 Azure 门户和 Azure CLI 在事件网格命名空间上配置自定义 JWT 身份验证设置。 首先需要创建命名空间,然后使用以下步骤对其进行更新。

使用 Azure 门户

  1. 在 Azure 门户中,导航到事件网格命名空间。
  2. 在“事件网格命名空间”页上,选择左侧菜单中的配置。
  3. 在“自定义 JWT 身份验证”部分中,指定以下属性的值:
    1. 选择“启用自定义 JWT 身份验证”

    2. 令牌颁发者:输入 MQTT 客户端提供的 JWT 的颁发者声明的值。

    3. 选择颁发者证书选项 – 直接上传

      显示事件网格命名空间的“配置”页的“直接上传”选项选择的屏幕截图。

  4. 在新页面中,指定以下属性的值。
    1. 证书:以 PEM 格式上传服务器证书。

    2. 儿童:证书的唯一密钥标识符。

    3. 选择 添加

      显示“上传颁发者证书”页的屏幕截图。

  5. 返回“配置”页面,选择“应用”

使用 Azure CLI

使用以下命令使用 OAuth 2.0 JWT 身份验证配置更新命名空间。

az eventgrid namespace update \ 
    --resource-group <resource-group-name> \ 
    --name <namespace-name> \ 
    --api-version 2024-12-15-preview \ 
    --set customJwtAuthenticationSettings='{ 
        "tokenIssuer": "issuer-name", 
        "encodedIssuerCertificates": [
            { 
                "kid": "key1", 
                "encodedCertificate": "-----BEGIN CERTIFICATE-----\n<certificate-in-PEM-format>\n-----END CERTIFICATE-----" 
            } 
        ] 
    } 
  • <resource-group-name><namespace-name><___location><key-vault-name><certificate-name><certificate-in-PEM-format>替换为你的实际值。
  • encodedCertificate 值必须包含 PEM 格式的完整证书和公钥,包括标头( "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE----, ``-----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY-----)。
  • 确保提供的公钥证书有效且受标识提供者信任。
  • 如果证书已轮换或过期,请定期更新 encodedIssuerCertificate。

JSON Web 令牌格式

JSON Web 令牌需要具有 JWT 标头、JWT 有效负载和 JWT 签名部分。

事件网格需要以下声明:isssubaudexpnbf

  • kid 是可选的。 如果存在,则使用匹配 kid 的证书进行验证。
  • 未用作属性的标准声明列表 - isssubaudexpnbf、 、 。 iatjti
  • 所有具有正确数据类型的声明项(包括适合 int32 的数字、字符串和字符串数组)都用作属性。 在此示例中num_attr_posnum_attr_negstr_attrstr_list_attr声明具有正确的数据类型,并用作属性。
  • 在此示例中bool_attrnum_attr_to_bignum_attr_floatobj_attr声明的数据类型不正确,不能用作属性。
{ 
  "typ": "JWT", 
  "alg": "RS256", 
  "kid": "keyId1" 
}.{ 
  "iss": "some-issuer", 
  "sub": "device1", 
  "aud": "event-grid-namespace.ts.eventgrid.azure.net", 
  "exp": 1770426501, 
  "nbf": 1738886901, 
  "bool_attr": true, 
  "num_attr_pos": 1, 
  "num_attr_neg": -1, 
  "num_attr_to_big": 9223372036854775807, 
  "num_attr_float": 1.23, 
  "str_attr": "str_value", 
  "str_list_attr": [ 
    "str_value_1", 
    "str_value_2" 
  ], 
  "obj_attr": { 
      "key": "value" 
  } 
}