使用 OAuth 2.0 授予对 REST API 的访问权限

Azure DevOps Services

注意

以下指南适用于Azure DevOps Services用户,因为 Azure DevOps Server 不支持 OAuth 2.0。 客户端库是一系列专为扩展Azure DevOps Server功能而构建的包。 对于本地用户,我们建议使用客户端库、Windows身份验证或个人访问令牌 (PAT) 代表用户进行身份验证。

对 Web 应用用户进行身份验证以进行 REST API 访问,因此应用不会继续请求用户名和密码。 Azure DevOps Services使用 OAuth 2.0 协议为用户授权应用并生成访问令牌。 从应用程序调用 REST API 时,请使用此令牌。

为该用户调用Azure DevOps Services API 时,请使用该用户的访问令牌。 访问令牌过期,因此,如果访问令牌已过期,请刷新访问令牌。

Process to get authorization.

有关总体流的 C# 示例,请参阅 vsts-auth-samples

注册应用

转到 https://app.vsaex.visualstudio.com/app/register 注册应用。

请确保选择应用程序所需的 范围 ,然后在 授权应用时使用相同的范围。 如果使用预览 API 注册应用,请重新注册,因为所使用的范围现已弃用。

Azure DevOps Services向用户显示授权审批页面时,它将使用公司名称、应用名称和说明。 它还使用公司网站、应用网站和服务条款和隐私声明的 URL。

Visual Studio Codespaces authorization page with your company and app information.

当Azure DevOps Services请求用户的授权,并且用户向其授予授权时,用户的浏览器会使用授权代码重定向到授权回调 URL。 回调 URL 必须是 (https) 的安全连接,才能将代码传输回应用。 它必须与应用中注册的 URL 完全匹配。 如果未显示,将显示 400 错误页,而不是要求用户向应用授予授权的页面。

注册应用时,将显示应用程序设置页。

Applications settings shown for your app.

如果想要让用户授权应用访问其组织,请调用授权 URL 并传递应用 ID 和授权范围。 如果要获取访问令牌来调用 Azure DevOps Services REST API,请调用访问令牌 URL。

注册的每个应用的设置可从配置文件 https://app.vssps.visualstudio.com/profile/view获取。

授权应用

如果用户尚未授权应用访问其组织,请调用授权 URL。

https://app.vssps.visualstudio.com/oauth2/authorize
        ?client_id={app ID}
        &response_type={Assertion}
        &state={state}
        &scope={scope}
        &redirect_uri={callback URL}
参数 类型 注释
client_id GUID 注册应用时分配给应用的 ID。
response_type string Assertion
state string 可以是任何值。 通常,生成的字符串值将回调与其关联的授权相关联。 请求。
scope 字符串 注册到应用的作用域。 空格分隔。 请参阅 可用范围
redirect_uri URL 应用的回调 URL。 必须与注册到应用的 URL 完全匹配

Azure DevOps Services要求用户授权应用。 它处理身份验证,然后通过授权代码调用你,如果用户批准授权。

将用户转到Azure DevOps Services授权终结点的站点添加链接或按钮:

https://app.vssps.visualstudio.com/oauth2/authorize
        ?client_id=88e2dd5f-4e34-45c6-a75d-524eb2a0399e
        &response_type=Assertion
        &state=User1
        &scope=vso.work%20vso.code_write
        &redirect_uri=https://fabrikam.azurewebsites.net/myapp/oauth-callback

Azure DevOps Services要求用户授权应用。

假设用户接受,Azure DevOps Services将用户的浏览器重定向到回调 URL,包括短期授权代码和授权 URL 中提供的状态值:

https://fabrikam.azurewebsites.net/myapp/oauth-callback
        ?code={authorization code}
        &state=User1

获取用户的访问权限和刷新令牌

现在,使用授权代码为用户请求访问令牌 (和刷新令牌) 。 服务必须向Azure DevOps Services发出服务到服务 HTTP 请求。

URL - 授权应用

POST https://app.vssps.visualstudio.com/oauth2/token

HTTP 请求标头 - 授权应用

标头
Content-Type application/x-www-form-urlencoded
Content-Length 请求正文的计算字符串长度 (请参阅以下示例)
Content-Type: application/x-www-form-urlencoded
Content-Length: 1322

HTTP 请求正文 - 授权应用

client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={0}&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion={1}&redirect_uri={2}

替换上一示例请求正文中的占位符值:

  • {0}:注册应用时获取的 URL 编码客户端密码
  • {1}:通过查询参数提供给回调 URL 的 code URL 编码的“代码”
  • {2}:注册到应用的回调 URL

用于形成请求正文的 C# 示例 - 授权应用

public string GenerateRequestPostData(string appSecret, string authCode, string callbackUrl)
{
   return String.Format("client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={0}&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion={1}&redirect_uri={2}",
               HttpUtility.UrlEncode(appSecret),
               HttpUtility.UrlEncode(authCode),
               callbackUrl
        );
}

响应 - 授权应用

{
    "access_token": { access token for the user },
    "token_type": { type of token },
    "expires_in": { time in seconds that the token remains valid },
    "refresh_token": { refresh token to use to acquire a new access token }
}

重要

安全地保留 refresh_token ,以便应用无需提示用户再次授权。 访问令牌相对快过期,不应持久保存。

使用访问令牌

若要使用访问令牌,请将它作为持有者令牌包含在 HTTP 请求的授权标头中:

Authorization: Bearer {access_token}

例如, 用于获取项目最近生成的 HTTP 请求:

GET https://dev.azure.com/myaccount/myproject/_apis/build-release/builds?api-version=3.0
Authorization: Bearer {access_token}

刷新过期的访问令牌

如果用户的访问令牌过期,可以使用他们在授权流中获取的刷新令牌来获取新的访问令牌。 就像交换访问和刷新令牌的授权代码的原始过程一样。

URL - 刷新令牌

POST https://app.vssps.visualstudio.com/oauth2/token

HTTP 请求标头 - 刷新令牌

标头
Content-Type application/x-www-form-urlencoded
Content-Length 请求正文的计算字符串长度 (请参阅以下示例)
Content-Type: application/x-www-form-urlencoded
Content-Length: 1654

HTTP 请求正文 - 刷新令牌

client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={0}&grant_type=refresh_token&assertion={1}&redirect_uri={2}

替换上一示例请求正文中的占位符值:

  • {0}:注册应用时获取的 URL 编码客户端密码
  • {1}:用户的 URL 编码刷新令牌
  • {2}:注册到应用的回调 URL

响应 - 刷新令牌

{
    "access_token": { access token for this user },
    "token_type": { type of token },
    "expires_in": { time in seconds that the token remains valid },
    "refresh_token": { new refresh token to use when the token has timed out }
}

重要

为用户颁发新的刷新令牌。 保留此新令牌,并在下次需要为用户获取新的访问令牌时使用它。

作用域

重要

范围仅允许访问 REST API 并选择 Git 终结点。 不支持 SOAP API 访问。

类别 范围 名称 说明
代理池 vso.agentpools 代理池 (读取) 授予查看代理的任务、池、队列、代理以及当前正在运行或最近完成的作业的功能。
vso.agentpools_manage 代理池 (读取、管理) 授予管理池、队列和代理的功能。
vso.environment_manage 环境 (读取、管理) 授予管理池、队列、代理和环境的功能。
分析 vso.analytics 分析 (读取) 授予查询分析数据的功能。
审核日志 vso.auditlog 审核日志 (读取) 授予向用户读取审核日志的功能。
生成 vso.build 生成 (读取) 授予访问生成项目的功能,包括生成结果、定义和请求,以及通过服务挂钩接收有关生成事件的通知的能力。
vso.build_execute 生成 (读取和执行) 授予访问生成项目的功能,包括生成结果、定义和请求,以及排队生成、更新生成属性以及通过服务挂钩接收有关生成事件的通知的能力。
代码 vso.code 代码(读取) 授予读取有关提交、更改集、分支和其他版本控制项目的源代码和元数据的功能。 此外,还可以通过服务挂钩搜索代码并收到有关版本控制事件的通知。
vso.code_write 代码 (读取和写入) 授予读取、更新和删除源代码、访问有关提交、更改集、分支和其他版本控制项目的元数据的功能。 此外,还授予创建和管理拉取请求和代码评审的功能,并通过服务挂钩接收有关版本控制事件的通知。
vso.code_manage 代码 (读取、写入和管理) 授予读取、更新和删除源代码、访问有关提交、更改集、分支和其他版本控制项目的元数据的功能。 此外,还授予创建和管理代码存储库、创建和管理拉取请求和代码评审以及通过服务挂钩接收有关版本控制事件的通知的能力。
vso.code_full 代码 (完整) 授予对源代码、有关提交、更改集、分支和其他版本控制项目的完全访问权限。 此外,还授予创建和管理代码存储库、创建和管理拉取请求和代码评审以及通过服务挂钩接收有关版本控制事件的通知的能力。 还包括对客户端 OM API 的有限支持。
vso.code_status 代码 (状态) 授予读取和写入提交和拉取请求状态的功能。
权利 vso.entitlements 权利 (读取) 提供对许可权利终结点的只读访问权限,以获取帐户权利。
vso.memberentitlementmanagement MemberEntitlement Management (读取) 授予读取用户、其许可证以及可以访问的项目和扩展的能力。
vso.memberentitlementmanagement_write MemberEntitlement Management (写入) 授予管理用户、其许可证以及可以访问的项目和扩展的能力。
扩展 vso.extension 扩展 (读取) 授予读取已安装扩展的功能。
vso.extension_manage 扩展 (读取和管理) 授予在已安装扩展上安装、卸载和执行其他管理操作的功能。
vso.extension.data 扩展数据 (读取) 授予读取由已安装扩展存储的数据 (设置和文档) 的功能。
vso.extension.data_write 扩展数据 (读取和写入) 授予读取和写入 (设置和文档) 由已安装扩展存储的功能。
& Graph标识 vso.graph Graph (读取) 授予读取用户、组、范围和组成员身份信息的功能。
vso.graph_manage Graph (管理) 授予读取用户、组、范围和组成员身份信息以及添加用户、组和管理组成员身份的功能。
vso.identity 标识(读取) 授予读取标识和组的功能。
vso.identity_manage 标识 (管理) 授予读取、写入和管理标识和组的功能。
负载测试 vso.loadtest 负载测试 (读取) 授予读取负载测试运行、测试结果和 APM 项目的能力。
vso.loadtest_write 负载测试 (读取和写入) 授予创建和更新负载测试运行的功能,以及读取元数据,包括测试结果和 APM 项目。
计算机组 vso.machinegroup_manage 部署组 (读取、管理) 提供管理部署组和代理池的功能。
市场 vso.gallery 市场 授予对公共和专用项和发布者的读取访问权限。
vso.gallery_acquire 市场 (获取) 授予读取访问权限和获取项的能力。
vso.gallery_publish 市场 (发布) 授予读取访问权限以及上传、更新和共享项目的能力。
vso.gallery_manage 市场 (管理) 授予读取访问权限以及发布和管理项和发布者的能力。
通知 vso.notification 通知 (读取) 提供对订阅和事件元数据的读取访问权限,包括可筛选字段值。
vso.notification_write 通知 (写入) 提供对订阅的读取和写入访问权限,以及对事件元数据的读取访问权限,包括可筛选字段值。
vso.notification_manage 通知 (管理) 提供对订阅的读取、写入和管理访问权限,以及对事件元数据(包括可筛选字段值)的读取、写入和管理访问权限。
vso.notification_diagnostics 通知 (诊断) 提供对通知相关的诊断日志的访问权限,并提供为单个订阅启用诊断的功能。
包装 vso.packaging 打包 (读取) 授予读取源和包的功能。
vso.packaging_write 打包 (读写) 授予创建和读取源和包的功能。
vso.packaging_manage 打包 (读取、写入和管理) 授予创建、读取、更新和删除源和包的功能。
Project和团队 vso.project 项目和团队(读取) 授予读取项目和团队的能力。
vso.project_write Project和团队 (读取和写入) 授予读取和更新项目和团队的能力。
vso.project_manage Project和团队 (读取、写入和管理) 授予创建、读取、更新和删除项目和团队的功能。
版本 vso.release 发布 (读取) 授予读取发布项目的功能,包括发布、发布定义和发布环境。
vso.release_execute 发布 (读取、写入和执行) 授予读取和更新发布项目的功能,包括发布、发布定义和发布环境,以及将新版本排队的功能。
vso.release_manage 发布 (读取、写入、执行和管理) 授予读取、更新和删除发布项目(包括发布、发布定义和发布环境)以及排队和批准新版本的功能。
安全性 vso.security_manage 安全 (管理) 授予读取、写入和管理安全权限的能力。
服务连接 vso.serviceendpoint 服务终结点 (读取) 授予读取服务终结点的功能。
vso.serviceendpoint_query 服务终结点 (读取和查询) 授予读取和查询服务终结点的能力。
vso.serviceendpoint_manage 服务终结点 (读取、查询和管理) 授予读取、查询和管理服务终结点的功能。
设置 vso.settings 设置 (读取) 授予读取设置的功能。
vso.settings_write 设置 (读取和写入) 授予创建和读取设置的能力。
符号 vso.symbols 读取) 的符号 ( 授予读取符号的功能。
vso.symbols_write 符号 (读取和写入) 授予读取和写入符号的能力。
vso.symbols_manage 符号 (读取、写入和管理) 授予读取、写入和管理符号的能力。
任务组 vso.taskgroups_read 任务组 (读取) 授予读取任务组的功能。
vso.taskgroups_write 任务组 (读取、创建) 授予读取和创建任务组的功能。
vso.taskgroups_manage 任务组 (读取、创建和管理) 授予读取、创建和管理任务组的能力。
团队仪表板 vso.dashboards 团队仪表板 (读取) 授予读取团队仪表板信息的功能。
vso.dashboards_manage (管理) 的团队仪表板 授予管理团队仪表板信息的能力。
测试管理 vso.test 测试管理 (读取) 授予读取测试计划、案例、结果和其他测试管理相关项目的能力。
vso.test_write 测试管理 (读取和写入) 授予读取、创建和更新测试计划、案例、结果和其他与测试管理相关的项目的能力。
标记 vso.tokens 委托的授权令牌 授予向用户管理委派授权令牌的能力。
vso.tokenadministration 令牌管理 向组织管理员授予管理 (视图和撤销现有令牌) 的能力。
用户配置文件 vso.profile 用户配置文件(读取) 授予读取配置文件、帐户、集合、项目、团队和其他顶级组织项目的能力。
vso.profile_write 用户配置文件 (写入) 授予写入配置文件的功能。
变量组 vso.variablegroups_read 变量组 (读取) 授予读取变量组的功能。
vso.variablegroups_write (读取的变量组,创建) 授予读取和创建变量组的功能。
vso.variablegroups_manage 变量组 (读取、创建和管理) 授予读取、创建和管理变量组的能力。
Wiki vso.wiki Wiki (阅读) 授予读取 Wiki、Wiki 页面和 Wiki 附件的功能。 此外,还授予搜索 Wiki 页面的功能。
vso.wiki_write Wiki (读写) 授予读取、创建和更新 Wiki、Wiki 页面和 Wiki 附件的功能。
工作项 vso.work 工作项(读取) 授予读取工作项、查询、板、区域和迭代路径和其他工作项跟踪相关元数据的能力。 此外,还可以通过服务挂钩执行查询、搜索工作项和接收有关工作项事件的通知。
vso.work_write 工作项 (读取和写入) 授予读取、创建和更新工作项和查询、更新板元数据、读取区域和迭代路径的其他工作项跟踪相关元数据、执行查询以及通过服务挂钩接收有关工作项事件的通知的能力。
vso.work_full 工作项 (完整) 授予对工作项、查询、积压工作、计划和工作项跟踪元数据的完全访问权限。 此外,还可以通过服务挂钩接收有关工作项事件的通知。

注册应用并使用范围来指示应用所需的Azure DevOps Services哪些权限。 当用户授权应用访问其组织时,会授权应用访问这些范围。 请求授权 会传递注册的相同范围。

有关详细信息,请参阅 创建工作项跟踪/附件

示例

可以在 C# OAuth GitHub 示例中找到实现 OAuth 以调用 Azure DevOps Services REST API 的 C# 示例。

常见问题 (FAQ)

问:是否可以将 OAuth 与手机应用配合使用?

答:否。 Azure DevOps Services仅支持 Web 服务器流,因此无法实现 OAuth,因为无法安全地存储应用机密。

问:代码中需要处理哪些错误或特殊条件?

答:请确保处理以下条件:

  • 如果用户拒绝应用访问权限,则不会返回授权代码。 不要在检查拒绝的情况下使用授权代码。
  • 如果用户撤销应用的授权,则访问令牌不再有效。 当应用使用令牌访问数据时,将返回 401 错误。 再次请求授权。

问:我想在本地调试 Web 应用。 注册应用时,是否可以将 localhost 用于回调 URL?

A:是的。 Azure DevOps Services现在允许回调 URL 中的 localhost。 确保在注册应用时用作 https://localhost 回调 URL 的开头。

问:尝试获取访问令牌时出现 HTTP 400 错误。 可能有什么错?

答:检查是否在请求标头中将内容类型设置为 application/x-www-form-urlencoded。

问:使用基于 OAuth 的访问令牌时,我收到 HTTP 401 错误,但具有相同范围的 PAT 可以正常工作。 为什么?

答:验证组织管理员https://dev.azure.com/{your-org-name}/_settings/organizationPolicy尚未禁用通过 OAuth 进行的第三方应用程序访问

在此方案中,用于授权应用并生成访问令牌的整个流正常工作,但所有 REST API 仅返回错误,例如 TF400813: The user "<GUID>" is not authorized to access this resource.

问:是否可以将 OAuth 与 SOAP 终结点和 REST API 配合使用?

答:否。 目前仅在 REST API 中支持 OAuth。

问:如何使用 Azure DevOps REST API 获取工作项的附件详细信息?

答:首先,使用工作项获取工作项详细信息 - 获取工作项 REST API:

GET https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/{id}

若要获取附件详细信息,需要将以下参数添加到 URL:

$expand=all

使用结果可获取关系属性。 可以在其中找到附件 URL,在 URL 中可以找到该 ID。 例如:

$url = https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/434?$expand=all&api-version=5.0

$workItem = Invoke-RestMethod -Uri $url -Method Get -ContentType application/json

$split = ($workitem.relations.url).Split('/')

$attachmentId = $split[$split.count - 1]

# Result: 1244nhsfs-ff3f-25gg-j64t-fahs23vfs