{"meta":{"title":"授权 OAuth 应用","intro":"你可以允许其他用户授权 OAuth app。","product":"应用","breadcrumbs":[{"href":"/zh/apps","title":"应用"},{"href":"/zh/apps/oauth-apps","title":"OAuth 应用"},{"href":"/zh/apps/oauth-apps/building-oauth-apps","title":"构建 OAuth 应用"},{"href":"/zh/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps","title":"授权 OAuth 应用"}],"documentType":"article"},"body":"# 授权 OAuth 应用\n\n你可以允许其他用户授权 OAuth app。\n\n> \\[!NOTE]\n> 请考虑生成 GitHub App 而不是 OAuth app。\n>\n> OAuth apps 和 GitHub Apps 使用 OAuth 2.0。\n>\n> GitHub Apps 可以代表用户执行操作（类似于 OAuth app），也可以自行执行操作，这对不需要用户输入的自动程序很有利。 此外，GitHub Apps 使用细化权限，让用户更好地控制应用可以访问的存储库，并使用生存期较短的令牌。 有关详细信息，请参阅 [GitHub 应用和 OAuth 应用之间的差异](/zh/apps/oauth-apps/building-oauth-apps/differences-between-github-apps-and-oauth-apps) 和 [关于创建GitHub应用](/zh/apps/creating-github-apps/setting-up-a-github-app/about-creating-github-apps)。\n\nGitHub 的 OAuth 实现支持标准[授权代码授权类型](https://tools.ietf.org/html/rfc6749#section-4.1)和对无权访问 Web 浏览器的应用的 OAuth 2.0 [设备授权](https://tools.ietf.org/html/rfc8628)。\n\n如果想跳过以标准方式授权应用（例如在测试应用时），可以使用[非 Web 应用程序流](#non-web-application-flow)。\n\n要授权你的 OAuth app，请考虑哪个授权流程最适合你的应用。\n\n* [Web 应用程序流](#web-application-flow)：用于授权用户使用在浏览器中运行的标准 OAuth apps。 （不支持[隐式授权类型](https://tools.ietf.org/html/rfc6749#section-4.2)。）\n* [设备流](#device-flow)：用于无外设应用，例如 CLI 工具。\n\n## Web 应用程序流程\n\n> \\[!NOTE]\n> 如果要生成GitHub应用，仍可使用 OAuth Web 应用程序流，但设置有一些重要差异。 有关详细信息，请参阅“[代表用户使用 GitHub 应用进行身份验证](/zh/apps/creating-github-apps/authenticating-with-a-github-app/identifying-and-authorizing-users-for-github-apps)”。\n\n为您的应用授权用户的 Web 应用流程是：\n\n1. 用户将被重定向以请求其GitHub标识\n2. 用户通过GitHub重定向回您的网站\n3. 您的应用程序使用用户的访问令牌访问 API\n\n### 1.请求用户的GitHub标识\n\n```\nGET https://github.com/login/oauth/authorize\n```\n\n此终结点采用以下输入参数。\n\n| 查询参数                    | 类型       | 必需？   | 说明                                                                                                                                                                                                                                                                                                                  |\n| ----------------------- | -------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `client_id`             | `string` | 必需的   | [注册](https://github.com/settings/applications/new)时从 GitHub 收到的客户端 ID。                                                                                                                                                                                                                                              |\n| `redirect_uri`          | `string` | 强烈建议  | 用户获得授权后被发送到的应用程序中的 URL。 请参阅以下有关[重定向 URL](#redirect-urls) 的详细信息。                                                                                                                                                                                                                                                     |\n| `login`                 | `string` | 可选    | 提供用于登录和授权应用程序的特定账户。                                                                                                                                                                                                                                                                                                 |\n| `scope`                 | `string` | 上下文相关 | 一个由空格分隔的[范围](/zh/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps)列表。 如果未提供，则 `scope` 对于未为应用程序授权任何范围的用户默认为空列表。 对于已向应用程序授权作用域的用户，不会显示含作用域列表的 OAuth 授权页面。 相反，通过用户向应用程序授权的作用域集，此流程步骤将自动完成。 例如，如果用户已经执行了两次 Web 流，并且已授权一个具有 `user` 范围的令牌和另一个具有 `repo` 范围的令牌，则不提供 `scope` 的第三个 Web 流将收到具有 `user` 和 `repo` 范围的令牌。 |\n| `state`                 | `string` | 强烈建议  | 不可猜测的随机字符串。 它用于防止跨站请求伪造攻击。                                                                                                                                                                                                                                                                                          |\n|                         |          |       |                                                                                                                                                                                                                                                                                                                     |\n| `code_challenge`        | `string` | 强烈建议  | 用于使用 PKCE（代码交换的证明密钥）保护身份验证流。 如果包含 `code_challenge_method`，则需要。 必须是客户端生成的随机字符串，包含 43 个字符且为 SHA-256 哈希值。 有关此安全扩展的更多详细信息，请参阅 [PKCE RFC](https://datatracker.ietf.org/doc/html/rfc7636)。                                                                                                                                |\n| `code_challenge_method` | `string` | 强烈建议  | 用于使用 PKCE（代码交换的证明密钥）保护身份验证流。 如果包含 `code_challenge`，则需要。 必须是 `S256` - `plain` 不支持代码质询方法。                                                                                                                                                                                                                             |\n|                         |          |       |                                                                                                                                                                                                                                                                                                                     |\n| `allow_signup`          | `string` | 可选    | 是否向未经身份验证的用户提供了在 OAuth 流期间注册GitHub的选项。 默认值为 `true`。 在策略禁止注册时使用 `false`。                                                                                                                                                                                                                                             |\n| `prompt`                | `string` | 可选    | 强制帐户选取器在设置为 `select_account` 时显示。 如果应用程序具有非 HTTP 重定向 URI，或者用户登录了多个帐户，则帐户选取器也会显示。                                                                                                                                                                                                                                    |\n\n目前不支持 CORS 预检请求 (OPTIONS)。\n\n### 2. 用户被GitHub重定向回您的网站\n\n如果用户接受你的请求，GitHub 会使用代码参数中的临时 `code` 以及你在上一步的 `state` 参数中提供的状态重定向回你的站点。 临时代码将在 10 分钟后到期。 如果状态不匹配，然后第三方创建了请求，您应该中止此过程。\n\n将此 `code` 交换为访问令牌：\n\n```\nPOST https://github.com/login/oauth/access_token\n```\n\n此终结点采用以下输入参数。\n\n| 参数名称            | 类型       | 必需？  | 说明                                                                                                                                                                   |\n| --------------- | -------- | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `client_id`     | `string` | 必需的  | 您从 GitHub 收到的客户端 ID 适用于您的 OAuth app。                                                                                                                                 |\n| `client_secret` | `string` | 必需的  | 从 GitHub 收到的 OAuth app 的客户端机密。                                                                                                                                       |\n| `code`          | `string` | 必需的  | 您收到的代码是作为对步骤 1 的响应。                                                                                                                                                  |\n| `redirect_uri`  | `string` | 强烈建议 | 用户获得授权后将被发送到的应用程序 URL。 我们可以使用此参数来匹配发放 `code` 时最初提供的 URI，以防止对服务的攻击。                                                                                                   |\n|                 |          |      |                                                                                                                                                                      |\n| `code_verifier` | `string` | 强烈建议 | 用于使用 PKCE（代码交换的证明密钥）保护身份验证流。 如果`code_challenge`在用户授权期间发送，则是必需的。 必须是用于在授权请求中生成 `code_challenge` 的原始值。 这可以与 `state` 参数一起存储在 Cookie 中，也可以在身份验证期间存储在会话变量中，具体取决于应用程序体系结构。 |\n|                 |          |      |                                                                                                                                                                      |\n\n默认情况下，响应采用以下形式：\n\n```shell\naccess_token=gho_16C7e42F292c6912E7710c838347Ae178B4a&scope=repo%2Cgist&token_type=bearer\n```\n\n如果在 `Accept` 标头中提供格式，则还可以接收不同格式的响应。 例如 `Accept: application/json` 或 `Accept: application/xml`：\n\n```json\nAccept: application/json\n{\n  \"access_token\":\"gho_16C7e42F292c6912E7710c838347Ae178B4a\",\n  \"scope\":\"repo,gist\",\n  \"token_type\":\"bearer\"\n}\n```\n\n```xml\nAccept: application/xml\n<OAuth>\n  <token_type>bearer</token_type>\n  <scope>repo,gist</scope>\n  <access_token>gho_16C7e42F292c6912E7710c838347Ae178B4a</access_token>\n</OAuth>\n```\n\n### 3. 使用访问令牌访问 API\n\n访问令牌可用于代表用户向 API 提出请求。\n\n```\nAuthorization: Bearer OAUTH-TOKEN\nGET https://api.github.com/user\n```\n\n例如，您可以像以下这样在 curl 中设置“授权”标头：\n\n```shell\ncurl -H \"Authorization: Bearer OAUTH-TOKEN\" https://api.github.com/user\n```\n\n每次收到访问令牌时，都应使用该令牌重新验证用户的标识。 当你向他们发送邮件授权应用时，用户可以更改他们登录的帐户，如果在每次登录后没有验证用户的标识，则可能会出现混合用户数据的风险。\n\n## 设备流动\n\n设备流允许你授权用户使用无头应用程序，例如 CLI 工具或 [Git 凭据管理器](https://github.com/git-ecosystem/git-credential-manager)。\n\n在使用设备流识别和授权用户之前，必须先在应用的设置中启用它。 有关在应用中启用设备流的详细信息，请参阅“[修改GitHub应用注册](/zh/apps/maintaining-github-apps/modifying-a-github-app)”（对于 GitHub Apps）和“[修改 OAuth 应用](/zh/apps/oauth-apps/maintaining-oauth-apps/modifying-an-oauth-app)”（对于 OAuth apps）。\n\n### 设备流程概述\n\n1. 您的应用程序会请求设备和用户验证码，并获取用户将在其中输入用户验证码的授权 URL。\n2. 应用程序提示用户在  [`https://github.com/login/device`](https://github.com/login/device) 中输入用户验证码。\n3. 应用程序轮询用户的身份验证状态。 用户授权设备后，应用程序将能够使用新的访问令牌进行 API 调用。\n\n### 步骤 1：应用从GitHub请求设备和用户验证码\n\n```\nPOST https://github.com/login/device/code\n```\n\n您的应用程序必须请求用户验证码和验证 URL，因为应用程序在下一步中提示用户进行身份验证时将使用它们。 此请求还返回设备验证代码，应用程序必须使用它们来接收访问令牌和检查用户身份验证的状态。\n\n终结点采用以下输入参数。\n\n| 参数名称        | 类型       | 说明 |\n| ----------- | -------- | -- |\n| `client_id` | `string` |    |\n\n```\n          **必填。** 从 GitHub 收到的应用程序的客户端 ID。\n```\n\n`scope` | `string` | 应用请求访问的范围的列表（以空格分隔）。 有关详细信息，请参阅“[OAuth 应用的范围](/zh/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps)”。\n\n默认情况下，响应采用以下形式：\n\n```shell\ndevice_code=3584d83530557fdd1f46af8289938c8ef79f9dc5&expires_in=900&interval=5&user_code=WDJB-MJHT&verification_uri=https%3A%2F%2Fgithub.com%2Flogin%2Fdevice\n```\n\n| 参数名称               | 类型        | 说明                                                                                                   |\n| ------------------ | --------- | ---------------------------------------------------------------------------------------------------- |\n| `device_code`      | `string`  | 设备验证码为 40 个字符，用于验证设备。                                                                                |\n| `user_code`        | `string`  | 用户验证码显示在设备上，以便用户可以在浏览器中输入该代码。 此代码为 8 个字符，中间有连字符。                                                     |\n| `verification_uri` | `string`  | 用户需要在其中输入 `user_code` 的验证 URL： [`https://github.com/login/device`](https://github.com/login/device)。 |\n| `expires_in`       | `integer` |                                                                                                      |\n\n```\n          `device_code` 和 `user_code` 过期之前的秒数。 默认值为 900 秒或 15 分钟。\n```\n\n`interval` | `integer` | 在能够发出新的访问令牌请求 (`POST https://github.com/login/oauth/access_token`) 以完成设备授权之前必须经过的最短秒数。 例如，如果间隔为 5，则只有经过 5 秒后才能发出新请求。 如果在 5 秒内发出多个请求，则将达到速率限制并收到 `slow_down` 错误。\n\n如果在 `Accept` 标头中提供格式，则还可以接收不同格式的响应。 例如 `Accept: application/json` 或 `Accept: application/xml`：\n\n```json\nAccept: application/json\n{\n  \"device_code\": \"3584d83530557fdd1f46af8289938c8ef79f9dc5\",\n  \"user_code\": \"WDJB-MJHT\",\n  \"verification_uri\": \"https://github.com/login/device\",\n  \"expires_in\": 900,\n  \"interval\": 5\n}\n```\n\n```xml\nAccept: application/xml\n<OAuth>\n  <device_code>3584d83530557fdd1f46af8289938c8ef79f9dc5</device_code>\n  <user_code>WDJB-MJHT</user_code>\n  <verification_uri>https://github.com/login/device</verification_uri>\n  <expires_in>900</expires_in>\n  <interval>5</interval>\n</OAuth>\n```\n\n### 第 2 步：提示用户在浏览器中输入用户代码\n\n您的设备将显示用户验证码并提示用户在  [`https://github.com/login/device`](https://github.com/login/device) 中输入该代码。\n\n### 步骤 3：应用程序通过轮询 GitHub 来检查用户是否已授权设备。\n\n```\nPOST https://github.com/login/oauth/access_token\n```\n\n应用将发出轮询 `POST https://github.com/login/oauth/access_token` 的设备授权请求，直到设备和用户代码过期，或者用户已使用有效的用户代码成功授权应用。 应用必须使用在步骤 1 中检索到的最短轮询 `interval`，以免出现速率限制错误。 有关详细信息，请参阅[设备流的速率限制](#rate-limits-for-the-device-flow)。\n\n用户必须在 15 分钟（或 900 秒内）内输入有效代码。 15 分钟后，需要使用 `POST https://github.com/login/device/code` 请求新的设备授权代码。\n\n一旦用户授权， 应用程序将收到一个访问令牌，该令牌可用于代表用户向 API 发出请求。\n\n终结点采用以下输入参数。\n\n| 参数名称        | 类型       | 说明 |\n| ----------- | -------- | -- |\n| `client_id` | `string` |    |\n\n```\n          **必填。** 您从 GitHub 收到的客户端 ID 适用于您的 OAuth app。\n```\n\n`device_code` | `string` |\n**必填。** 你从 `device_code` 请求中收到的 `POST https://github.com/login/device/code`。\n`grant_type` | `string` |\n**必填。** 授权类型必须是 `urn:ietf:params:oauth:grant-type:device_code`。\n\n默认情况下，响应采用以下形式：\n\n```shell\naccess_token=gho_16C7e42F292c6912E7710c838347Ae178B4a&token_type=bearer&scope=repo%2Cgist\n```\n\n如果在 `Accept` 标头中提供格式，则还可以接收不同格式的响应。 例如 `Accept: application/json` 或 `Accept: application/xml`：\n\n```json\nAccept: application/json\n{\n \"access_token\": \"gho_16C7e42F292c6912E7710c838347Ae178B4a\",\n  \"token_type\": \"bearer\",\n  \"scope\": \"repo,gist\"\n}\n```\n\n```xml\nAccept: application/xml\n<OAuth>\n  <access_token>gho_16C7e42F292c6912E7710c838347Ae178B4a</access_token>\n  <token_type>bearer</token_type>\n  <scope>gist,repo</scope>\n</OAuth>\n```\n\n### 设备流的速率限制\n\n当用户在浏览器上提交验证码时，每个应用程序在一个小时内的提交速率限制为 50 个。\n\n如果在请求之间所需的最小时间范围（即 `POST https://github.com/login/oauth/access_token`）内发出多个访问令牌请求 (`interval`)，你将达到速率限制，并收到 `slow_down` 错误响应。\n`slow_down` 错误响应向上一个 `interval` 添加 5 秒钟的时间。 有关详细信息，请参阅[设备流的错误代码](#error-codes-for-the-device-flow)。\n\n### 设备流的错误代码\n\n| 错误代码                           | 说明                                                                                                                                                                                                                                |\n| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `authorization_pending`        | 授权请求待处理并且用户尚未输入用户代码时，将发生此错误。 应用应在不超出 `POST https://github.com/login/oauth/access_token` 的情况下继续轮询 `interval` 请求，这需要每个请求之间的最短秒数。                                                                                                    |\n| `slow_down`                    | 收到 `slow_down` 错误时，会使用 `interval` 向请求之间所需的最短 `POST https://github.com/login/oauth/access_token` 或时间范围添加 5 秒钟的额外时间。 例如，如果请求之间的启动间隔至少需要 5 秒，并且你收到了 `slow_down` 错误响应，那么现在必须等待至少 10 秒，然后才能发出新的 OAuth 访问令牌请求。 错误响应包括必须使用的新 `interval`。 |\n| `expired_token`                | 如果设备代码已过期，则将看到 `token_expired` 错误。 您必须发出新的设备代码请求。                                                                                                                                                                                 |\n| `unsupported_grant_type`       | 轮询 OAuth 令牌请求 `urn:ietf:params:oauth:grant-type:device_code` 时，授权类型必须为 `POST https://github.com/login/oauth/access_token` 并且必须作为输入参数包含在内。                                                                                         |\n| `incorrect_client_credentials` | 对于设备流，您必须传递应用程序的客户端 ID，该 ID 可以在应用程序的设置页面上找到。 设备流不需要 `client_secret`。                                                                                                                                                              |\n| `incorrect_device_code`        | 提供的 device\\_code 无效。                                                                                                                                                                                                              |\n| `access_denied`                | 当用户在授权过程中单击取消时，你将收到 `access_denied` 错误，该用户将无法再次使用验证码。                                                                                                                                                                             |\n| `device_flow_disabled`         | 尚未在应用的设置中启用设备流。 有关详细信息，请参阅[设备流](#device-flow)。                                                                                                                                                                                    |\n\n有关详细信息，请参阅 [OAuth 2.0 设备授权](https://tools.ietf.org/html/rfc8628#section-3.5)。\n\n## 非 Web 应用程序流程\n\n非 web 身份验证适用于测试等有限的情况。 如果需要，可以使用[基本身份验证](/zh/rest/overview/authenticating-to-the-rest-api#using-basic-authentication)通过 [personal access token 设置页](/zh/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)创建 personal access token。 此方法支持用户随时撤销访问权限。\n\n## 重定向 URL\n\n```\n          `redirect_uri` 参数是可选的。 如果忽略该参数，GitHub 会将用户重定向到 OAuth app 设置中配置的回叫 URL。 如果提供该参数，重定向 URL 的主机（不含子域）和端口必须与回叫 URL 完全匹配。 重定向 URL 的路径必须指向回调 URL 的子目录。\n\nCALLBACK: http://example.com/path\n\nGOOD: http://example.com/path\nGOOD: http://example.com/path/subdir/other\nGOOD: http://oauth.example.com/path\nGOOD: http://oauth.example.com/path/subdir/other\nBAD:  http://example.com/bar\nBAD:  http://example.com/\nBAD:  http://example.com:8080/path\nBAD:  http://oauth.example.com:8080/path\nBAD:  http://example.org\n```\n\n### 环回重定向网址\n\n可选的 `redirect_uri` 参数还可用于环回 URL，这对于在台式计算机上运行的本机应用程序非常实用。 如果应用程序指定了环回 URL 和端口，那么在授权应用程序后，用户将被重定向到提供的 URL 和端口。\n`redirect_uri` 不需要与应用的回叫 URL 中指定的端口匹配。\n\n对于 `http://127.0.0.1/path` 回调 URL，如果应用程序正在端口 `redirect_uri` 上进行侦听，则可以使用此 `1234`：\n\n```http\nhttp://127.0.0.1:1234/path\n```\n\n请注意，OAuth RFC [建议不要使用 `localhost`](https://datatracker.ietf.org/doc/html/rfc8252#section-7.3)，而是使用环回文本 `127.0.0.1` 或 IPv6 `::1`。\n\n## 为 OAuth apps 创建多个令牌\n\n您可以为用户/应用程序/作用域组合创建多个令牌，以便为特定用例创建令牌。\n\n如果你的 OAuth app 支持一个使用 GitHub 登录且只需基本用户信息的工作流程，此方法将非常有用。 另一个工作流程可能需要访问用户的私有仓库。 你的 OAuth app 可以使用多个令牌为每个用例执行 Web 流程，只需要所需的作用域。 如果用户仅使用你的应用程序登录，则无需向他们的专用存储库授予你的 OAuth app 访问权限。\n\n每个用户/应用程序/作用域组合签发的令牌数量有限，速率限制是每小时创建十个令牌。 如果应用程序为同一用户和相同作用域创建超过十个令牌，则将撤销具有相同用户/应用程序/作用域组合的最旧令牌。 但是，达到每小时速率限制不会撤销最早的令牌。 相反，它会在浏览器中触发重新授权提示，要求用户仔细检查他们向你的应用授予的权限。 此提示旨在中断应用陷入的任何潜在的无限循环，因为应用几乎没有理由在一小时内向用户请求十个令牌。\n\n> \\[!WARNING]\n> 从 OAuth app 撤销所有权限将会删除应用程序代表用户生成的所有 SSH 密钥，包括[部署密钥](/zh/authentication/connecting-to-github-with-ssh/managing-deploy-keys#deploy-keys)。\n\n## 指示用户审查其访问权限\n\n可以链接至 OAuth app 的授权信息，以便用户审查和撤销其应用程序授权。\n\n若要生成此链接，需要使用在注册应用程序时从 GitHub 收到的 OAuth app 的 `client_id`。\n\n```http\nhttps://github.com/settings/connections/applications/:client_id\n```\n\n> \\[!TIP]\n> 若要详细了解 OAuth app 可以为用户访问的资源，请参阅“[为用户发现资源](/zh/rest/guides/discovering-resources-for-a-user)”。\n\n## 故障排除\n\n* [排查授权请求错误](/zh/apps/oauth-apps/maintaining-oauth-apps/troubleshooting-authorization-request-errors)\n* [排查 OAuth 应用访问令牌请求错误](/zh/apps/oauth-apps/maintaining-oauth-apps/troubleshooting-oauth-app-access-token-request-errors)\n* [设备流错误](#error-codes-for-the-device-flow)\n* [令牌过期和吊销](/zh/authentication/keeping-your-account-and-data-secure/token-expiration-and-revocation)\n\n## 其他阅读材料\n\n* [关于 GitHub 的身份验证](/zh/authentication/keeping-your-account-and-data-secure/about-authentication-to-github)"}