您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn.

保护 OAuth 2.0 OBO 刷新令牌Secure OAuth 2.0 OBO refresh tokens

开发 web 服务时,可能需要使用 OAuth 2.0 (OBO) 流来获取令牌。When developing web services, you may need to get tokens using the OAuth 2.0 On-Behalf-Of (OBO) flow. OBO 流提供应用程序调用服务或 web API 的用例,而后者又需要调用另一个服务或 web API。The OBO flow serves the use case where an application invokes a service or web API, which in turn needs to call another service or web API. OBO 通过请求链传播委托用户标识和权限。OBO propagates the delegated user identity and permissions through the request chain. 当应用程序需要无限期地使用访问和刷新令牌时,通常在脱机访问方案中,安全地存储刷新令牌至关重要。When an application needs to use access and refresh tokens indefinitely, typically in offline access scenarios, it's critical to store the refresh tokens securely.

警告

请仔细考虑存储任何安全令牌所涉及的风险和责任,因为这些令牌可以使恶意执行组件访问由组织的 Azure Active Directory (Azure AD) 保护的资源。Carefully consider the risk and responsibility involved in storing any security tokens, since these tokens can give a malicious actor access to resources protected by the organization's Azure Active Directory (Azure AD). 对于以任何组织目录中的帐户为目标的应用程序,如果 ** (任何 Azure AD 的目录多租户) ** ,则会出现安全漏洞。A security breach of an application that targets Accounts in any organizational directory (Any Azure AD directory - Multitenant) can be especially disastrous.

存储访问令牌会带来更大的安全风险,因为本身和中的访问令牌都可以访问资源。Storing access tokens poses a greater security risk, since an access token in and of itself can access resources. 建议的方法不会存储访问令牌,但会根据需要获取访问令牌。The recommended approach is not to store access tokens, but get the access tokens as needed. 安全地仅存储刷新令牌,其严格就像访问令牌一样严格。Securely store only the refresh tokens, with as much rigor as if they were access tokens.

如有必要,您可以 撤消刷新令牌 (如果它们被泄露)。If necessary, you can revoke refresh tokens if they become compromised.

此解决方案使用 Azure Key Vault、Azure Functions 和 Azure DevOps 来安全更新和存储 OBO 刷新令牌。This solution uses Azure Key Vault, Azure Functions, and Azure DevOps to securely update and store OBO refresh tokens.

体系结构Architecture

显示密钥和令牌刷新过程的关系图。

  • Azure Key Vault 保存每个 Azure AD 租户的机密加密密钥。Azure Key Vault holds secret encryption keys for each Azure AD tenant.
  • Azure Functions计时器触发的函数从 Key Vault 中获取最新的密钥。An Azure Functions timer-triggered function gets the latest secret key from Key Vault. 另一个 Azure Functions 函数检索 Microsoft 标识平台中的刷新令牌,并将其保存为最新的密钥版本。Another Azure Functions function retrieves the refresh token from the Microsoft identity platform and saves it with the latest secret key version.
  • 数据库存储最新的加密密钥和不透明数据。A database stores the latest encrypted key and opaque data.
  • Azure DevOps持续交付管道管理并同步机密轮换和令牌刷新过程。An Azure DevOps continuous delivery pipeline manages and syncs the secret rotation and token refresh processes.

如果你已将管道用于基础结构即代码 (IaC) 或持续集成和交付 (CI/CD) ,则可以使用Azure Pipelines来添加密钥轮换策略。Azure Pipelines is a convenient place to add your key rotation strategy, if you're already using Pipelines for infrastructure-as-code (IaC) or continuous integration and delivery (CI/CD). 只要限制用于设置和检索机密的路径,就不必使用 Azure Pipelines。You don't have to use Azure Pipelines, as long as you limit the paths for setting and retrieving secrets.

应用以下策略,以允许 Azure DevOps service 连接的服务主体在 Key Vault 中设置机密。Apply the following policy to allow the Service Principal for your Azure DevOps service connection to set secrets in Key Vault. <Key Vault Name><Service Connection Principal> 变量替换为环境的正确值。Replace the <Key Vault Name> and <Service Connection Principal> variables with the correct values for your environment.

az keyvault set-policy --name $<Key Vault Name> --spn $<Service Connection Principal> --secret-permissions set

设置用于创建和更新密钥的 Azure Pipelines 后,你可以将管道计划为定期运行。After you set up Azure Pipelines to create and update keys, you can schedule the pipeline to run periodically. 管道将 Key Vault 机密更新为与密钥轮换同步,并将加密令牌保存为新的密钥版本。The pipeline updates the Key Vault secret to sync with key rotation, and saves the encrypted token with the new secret version. 有关详细信息,请参阅为 管道配置计划For more information, see Configure schedules for pipelines.

托管标识Managed identity

Azure 服务(例如 Azure Functions 访问 Key Vault)的首选方法是使用该服务的 托管标识The preferred way for an Azure service like Azure Functions to access Key Vault is to use the service's managed identity. 可以通过 Azure 门户、Azure CLI 或通过 Azure 资源管理器 (ARM) 模板为 IaC 方案授予访问权限。You can grant access through the Azure portal, Azure CLI, or through an Azure Resource Manager (ARM) template for IaC scenarios.

Azure 门户Azure portal

在 Azure 门户中,添加一个 Key Vault 访问策略,以允许 Azure Functions 托管标识对象 ID 获取设置 机密。In the Azure portal, add a Key Vault access policy to allow the Azure Functions managed identity Object ID to Get and Set secrets. 有关详细信息,请参阅为应用服务和 Azure Functions添加系统分配的标识并使用 Key Vault 引用。For more information, see Add a system-assigned identity and Use Key Vault references for App Service and Azure Functions.

显示如何在 Azure 门户中启用托管标识的屏幕截图。

Azure CLIAzure CLI

还可以通过使用 Azure CLI设置 Azure Key Vault 策略:You can also set Azure Key Vault policy by using the Azure CLI:

az keyvault set-policy --name $<Key Vault Name> --spn $<Service Connection Principal> --secret-permissions set
az keyvault set-policy --name $<Key Vault Name> --spn $<Managed Identity Principal> --secret-permissions get

ARM 模板ARM template

以下 ARM 模板 提供对 Azure Key Vault 的 Azure Functions 访问权限。The following ARM template gives Azure Functions access to Azure Key Vault. *** 变量替换为环境的正确值。Replace the *** variables with the correct values for your environment.

{
  "type": "Microsoft.KeyVault/vaults",
  "apiVersion": "2019-09-01",
  "name": "***",
  "location": "***",
  "properties": {
    "sku": {
      "family": "A",
      "name": "standard"
    },
    "tenantId": "***",
    "enableSoftDelete": true,
    "enabledForDeployment": false,
    "enabledForTemplateDeployment": false,
    "enabledForDiskEncryption": false,
    "accessPolicies": [
      {
        "tenantId": "***",
        "objectId": "<Managed Identity Principal>",
        "permissions": {
          "secrets": [
            "get"
          ]
        }
      },
      {
        "tenantId": "***",
        "objectId": "<Service Connection Principal>",
        "permissions": {
          "secrets": [
            "set"
          ]
        }
      }
    ]
  }
}

令牌存储Token storage

您可以使用任何数据库以加密形式存储令牌。You can use any database to store the tokens in encrypted form. 下图显示了在数据库中存储刷新令牌的顺序:The following diagram shows the sequence to store refresh tokens in a database:

显示添加令牌序列的关系图。

序列包含两个函数: userId()secretId()The sequence has two functions, userId() and secretId(). 您可以将这些函数定义为、和的一些组合 token.oid token.tid token.subYou can define these functions as some combination of token.oid, token.tid, and token.sub. 有关详细信息,请参阅 使用 id_tokenFor more information, see Using the id_token.

将加密密钥存储为机密后,可以在 Azure Key Vault 中查找最新版本的密钥。With the cryptographic key stored as a secret, you can look up the latest version of the key in Azure Key Vault.

令牌使用情况Token usage

使用密钥非常简单。Using the key is straightforward. 下面的序列根据最新的密钥版本查询密钥。The following sequence queries the key based on the latest key version.

显示存储的令牌使用序列的关系图。

标记刷新与函数相互操作 DoWork ,因此 Azure Functions 可以 DoWork 通过使用 Durable Functions异步执行和标记刷新。The token refresh is orthogonal to the DoWork function, so Azure Functions can perform DoWork and token refresh asynchronously by using Durable Functions. 有关 Durable Functions 的 HTTP 触发的函数的详细信息,请参阅 http 功能For more information about HTTP-triggered functions with Durable Functions, see HTTP features.

建议不要在 HTTP 请求管道中使用 Azure Key Vault,因此应在合理的时候使用缓存响应。It's not recommended to use Azure Key Vault in the HTTP request pipeline, so cache responses whenever reasonable. 在此示例中,Key Vault 对调用的响应 getSecret(secretId, secretVersion) 可缓存。In the example, Key Vault's response to the getSecret(secretId, secretVersion) call is cacheable.

密钥轮换和令牌刷新Key rotation and token refresh

你可以在刷新刷新令牌的同时轮换密钥,因此,最新的令牌将以最新版本的加密密钥进行加密。You can rotate the secret key at the same time that you refresh the refresh token, so the latest token gets encrypted with the latest version of the encryption secret. 此过程使用对计时器触发器的内置 Azure Functions 支持。This process uses the built-in Azure Functions support for timer triggers. 有关详细信息,请参阅 Azure Functions 的计时器触发器For more information, see Timer trigger for Azure Functions.

下面的序列图说明了同步令牌刷新与密钥旋转的过程:The following sequence diagram illustrates the process of syncing the token refresh with the key rotation:

此图显示了与密钥轮换同步令牌的顺序。

用户和访问控制User and access control

Microsoft 标识平台提供了在泄露时撤消刷新令牌的功能。Microsoft Identity Platform offers the ability to revoke refresh tokens in case of compromise. 请参阅 令牌吊销AzureADUserAllRefreshTokenSee Token revocation and Revoke-AzureADUserAllRefreshToken.

若要从 Azure AD 中删除用户,只需删除用户的记录。To remove a user from Azure AD, just remove the user's record. 若要删除每个用户的应用程序访问权限,请删除 refreshToken 部分用户数据。To remove application access per user, remove the refreshToken part of the user data.

若要删除用户组(例如目标租户中的所有用户)的访问权限,可以使用 Azure Pipelines 删除组基于的机密 secretId()To remove access for a group of users, such as all users in a target tenant, you can use Azure Pipelines to delete the group's secret based on secretId().

后续步骤Next steps