---
url: /zh/oauth/developer.md
---
本文旨在为第三方开发者提供标准化的 OAuth 2.0 应用接入流程，支持应用的登记上架、用户授权（个人/资源级）、临时票据发放及 API 访问控制。

## 准备工作 - 申请注册 OAuth 应用

### 应用信息登记

当前需要 CNB 运营管理员审核后上架应用。请将申请信息提交给管理员，我们会与您沟通详细的 OAuth 应用创建方案。

### 应用基本信息

| 应用信息     | 是否必须 | 字段说明 |
| :--------   | ---- |  :----- |
| 应用名称   | 必须  |在授权时与用户授权管理页给用户展示，不超过 50 字 |
| 应用 Logo  | 必须  | 图片大小不超过 1MB |
| 应用简介   | 非必须 | 不超过 350 字 |
| 应用官网   | 必须  | 最多 128 字符 |
| 回调地址   | 必须  | Redirect URI，用于 OAuth 授权后跳转  |
| 支持的授权范围   | 必须  | 在应用创建方案中沟通，如 `repo-code:r`、`account-profile:r` 等，需预定义。应用仅申请必要的权限范围，CNB 平台审核时将评估授权范围合理性。 |
| 授权资源范围   | 必须  | 当前账号所有权限/当前账号所有公开资源/指定资源  |

## 授权流程

应用程序内用户的授权流程是：

1. 用户在应用程序内发起 CNB 授权请求；
2. 引导用户跳转至 CNB 的授权页面，携带对应参数，以请求他们的 CNB 身份；
3. 用户同意后，，CNB 会拉起应用或重定向到第三方网站，并且带上授权临时票据 `code` 参数；
4. 通过 `code` 参数加上 ClientID 和 ClientSecret 等，通过 API 换取 `access_token`;
5. 通过 `access_token` 进行接口调用，获取用户基本数据资源或帮助用户实现基本操作。

![](/images/oauth/7-oauth.png)

### 1. 发起授权请求

第三方使用网站应用授权登录可以通过在浏览器打开以下链接：

```text
https://cnb.share.ralphlauren.cn/oauth2/auth?client_id=CLIENTID&redirect_uri=REDIRECT_URI&response_type=code&state=STATE
```

若提示"该链接无法访问"，请检查参数是否填写错误，如 `redirect_uri` 的域名与审核时填写的授权域名不一致。

* `response_type`：表示授权类型，必选项，此处的值固定为`code`。
* `client_id`：表示客户端的 ID，必选项。
* `redirect_uri`：表示重定向 URI，可选项。
* `state`：表示客户端的当前状态，可以指定任意值，认证服务器会原封不动地返回这个值.

```http
    GET /oauth2/auth?response_type=code&client_id=s6BhdRkqt3&state=xyz
    &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
    Host: cnb.share.ralphlauren.cn
```

* `code`：表示授权码，必选项。该码的有效期应该很短，通常设为 10 分钟，客户端只能使用该码一次，否则会被授权服务器拒绝。该码与客户端 ID 和重定向 URI ，是一一对应关系。
* `state`：如果客户端的请求中包含这个参数，认证服务器的回应也必须一模一样包含这个参数。

用户允许授权后，将会重定向到`redirect_uri`的网址上，并且带上`code`和`state`参数。举例如下

```http
HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
```

### 2. 通过 code 获取 access\_token

客户端向认证服务器申请令牌的 HTTP 请求，包含以下参数：

* `grant_type`：表示使用的授权模式，必选项，此处的值固定为`authorization_code`。
* `code`：表示上一步获得的授权码，必选项。
* `redirect_uri`：表示重定向URI，可选项，必须与第一步请求 code 中的该参数值保持一致。

`client_id`/`client_secret` 还可以通过 HTTP 基本认证（ HTTP Basic Authentication ），以 Base64 编码的形式包含在请求头的 Authorization 字段中发送给服务器

```http
POST /oauth2/token HTTP/1.1
Host: cnb.share.ralphlauren.cn
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
```

* `access_token`：表示访问令牌，8 小时有效期，必选项。
* `token_type`：表示令牌类型，该值大小写不敏感，必选项，可以是 bearer 类型或 mac 类型。
* `expires_in`：表示过期时间，单位为秒。如果省略该参数，必须其他方式设置过期时间。
* `refresh_token`：表示更新令牌，用来获取下一次的访问令牌，可选项。
* `scope`：表示权限范围，如果与客户端申请的范围一致，此项可省略。

```http
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
    "access_token":"2YotnFZFEjr1zCsicMWpAA",
    "token_type":"bearer",
    "expires_in":3600,
    "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA"
}
```

### 3. 通过 refresh\_token 更新令牌

`access_token`是调用授权关系接口的调用凭证，由于`access_token`有效期（ 8 小时）较短，当`access_token`超时后，可以使用`refresh_token`进行刷新。每次使用刷新令牌后，会返回新的令牌和刷新令牌，旧的令牌与刷新令牌在宽限期（ 5 分钟）内还可继续使用，请妥善保存用户的相关令牌。

`refresh_token`拥有较长的有效期（ 180 天），当`refresh_token`失效的后，需要用户重新授权。

客户端发出更新令牌的 HTTP 请求，包含以下参数：

* `grant_type`：表示使用的授权模式，此处的值固定为`refresh_token`，必选项。
* `refresh_token`：表示早前收到的更新令牌，必选项。

```http
POST /oauth2/token HTTP/1.1
Host: cnb.share.ralphlauren.cn
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
```

返回示例同`access_token`

### 4. 撤销令牌

当用户退出登录或应用需要主动使令牌失效时，可调用撤销接口吊销 `access_token` 或 `refresh_token`。令牌撤销后立即失效，无法再用于 API 调用。

客户端发出撤销令牌的 HTTP 请求，包含以下参数：

* `token`：表示需要撤销的令牌（`access_token` 或 `refresh_token`），必选项。
* `client_id`：表示客户端 ID，可选项，也可通过 HTTP Basic Authentication 传递。
* `client_secret`：表示客户端密钥，可选项，也可通过 HTTP Basic Authentication 传递。

`client_id`/`client_secret` 可以通过 HTTP 基本认证（HTTP Basic Authentication），以 Base64 编码的形式包含在请求头的 Authorization 字段中发送给服务器。

```http
POST /oauth2/revoke HTTP/1.1
Host: cnb.share.ralphlauren.cn
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

token=2YotnFZFEjr1zCsicMWpAA
```

* 撤销成功时，返回 HTTP `200`。
* 若传入的令牌无效或已过期，服务器同样返回 HTTP `200`（符合 RFC 7009 规范）。
* 若 `client_id`/`client_secret` 认证失败，服务器返回 HTTP `401`，响应体包含错误详情。

```http
HTTP/1.1 200 OK
```

认证失败时的响应示例：

```http
HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
    "error": "invalid_client",
    "error_description": "Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)."
}
```

## 可授权范围

| 可操作权限     | 权限类型 | 说明 |
| :--------   | ---- |  :----- |
| repo-code   | 只读/读写  |通过 Git 命令访问代码仓库|
| repo-pr  | 只读/读写  |访问合并请求|
| repo-issue  | 只读/读写  |访问 ISSUE |
| repo-notes |  只读/读写 | 访问 ISSUE 及合并请求中的评论|
| repo-contents | 只读/读写|访问文件、分支、提交记录、标签、版本|
| repo-commit-status | 只读/读写 |访问流水线执行状态、徽章、commit 元数据|
| repo-cnb-trigger | 只读/读写 |查询、删除、触发、执行云原生构建，启动云原生开发|
| repo-cnb-history | 只读 |查询流水线构建历史|
| repo-cnb-detail | 只读/读写 |查询或删除云原生开发空间|
| repo-basic-info | 只读 |访问仓库基础信息，如：仓库名称、描述、语言、license 等|
| repo-manage | 只读/读写 |访问仓库成员、仓库设置|
| repo-delete | 读写 |删除仓库|
| repo-security | 只读 |访问仓库安全模块数据|
| registry-package | 只读/读写 |访问制品|
| registry-package-delete | 读写 |删除制品|
| registry-manage | 只读/读写 |访问制品库成员、制品库设置|
| registry-delete | 读写 |删除制品库|
| account-profile | 只读/读写 |访问用户个人资料|
| account-email | 只读/读写 |查询用户认证邮箱|
| account-engage | 只读/读写 |访问用户关注的仓库、关注者、粉丝、云原生开发环境等|
| group-resource | 只读/读写 |访问子组织、仓库|
| group-manage | 只读/读写 |访问组织成员、仓库墙、组织设置|
| group-delete | 只读/读写 |删除组织|
| mission-delete | 只读/读写 |删除任务集|
| mission-manage | 只读/读写 |访问任务集|
