跳到主要内容

授权 OAuth 应用

您可以允许其他用户授权您的 OAuth 应用。

注意

建议构建 GitHub 应用而不是 OAuth 应用。

OAuth 应用和 GitHub 应用都使用 OAuth 2.0。

GitHub 应用可以代表用户执行操作,类似于 OAuth 应用,或者代表自身执行操作,这对于不需要用户输入的自动化操作非常有利。此外,GitHub 应用使用细粒度的权限,使用户能够更好地控制应用可以访问哪些仓库,并使用短期令牌。更多信息,请参阅“GitHub 应用和 OAuth 应用之间的区别”和“关于创建 GitHub 应用”。

GitHub 的 OAuth 实现支持标准的授权码授予类型和 OAuth 2.0 设备授权授予(适用于无法访问 Web 浏览器的应用)。

如果您想跳过以标准方式授权您的应用(例如在测试您的应用时),您可以使用非 Web 应用流程

要授权您的 OAuth 应用,请考虑哪种授权流程最适合您的应用。

Web 应用流程

注意

如果您正在构建 GitHub 应用,您仍然可以使用 OAuth Web 应用流程,但设置有一些重要的区别。有关更多信息,请参阅“代表用户使用 GitHub 应用进行身份验证”。

授权用户访问您的应用的 Web 应用流程为:

  1. 用户被重定向以请求其 GitHub 身份
  2. GitHub 将用户重定向回您的网站
  3. 您的应用使用用户的访问令牌访问 API

1. 请求用户的 GitHub 身份

GET https://github.com/login/oauth/authorize

此端点采用以下输入参数。

查询参数类型必需?描述
client_id字符串必需您在注册时从 GitHub 收到的客户端 ID。
redirect_uri字符串强烈建议授权后用户将被发送到的应用程序中的 URL。请参阅下面有关重定向 URL的详细信息。
login字符串可选建议使用特定帐户进行登录并授权应用。
scope字符串上下文相关作用域的空格分隔列表。如果未提供,则对于尚未为应用程序授权任何作用域的用户,scope默认为空列表。对于已为应用程序授权作用域的用户,用户将不会看到包含作用域列表的 OAuth 授权页面。相反,此流程的这一步将自动完成,并使用用户已为应用程序授权的作用域集。例如,如果用户已经执行了两次 Web 流程,并使用user作用域授权了一个令牌,并使用repo作用域授权了另一个令牌,则不提供scope的第三个 Web 流程将收到具有userrepo作用域的令牌。
state字符串强烈建议一个不可猜测的随机字符串。它用于防止跨站点请求伪造攻击。
allow_signup字符串可选在 OAuth 流程期间是否为未经身份验证的用户提供在 GitHub 上注册的选项。默认值为true。当策略禁止注册时,使用false
prompt字符串可选如果设置为select_account,则强制显示帐户选择器。如果应用程序具有非 HTTP 重定向 URI 或用户已登录多个帐户,则也会显示帐户选择器。

目前不支持 PKCE(代码交换证明密钥)参数code_challengecode_challenge_method。目前不支持 CORS 预检请求 (OPTIONS)。

2. GitHub 将用户重定向回您的网站

如果用户接受您的请求,GitHub 将使用代码参数中的临时code以及您在上一步中提供的state参数中的状态重定向回您的网站。临时代码将在 10 分钟后过期。如果状态不匹配,则第三方创建了请求,您应该中止该过程。

将此code交换为访问令牌

POST https://github.com/login/oauth/access_token

此端点采用以下输入参数。

参数名称类型必需?描述
client_id字符串必需您从 GitHub 为您的 OAuth 应用收到的客户端 ID。
client_secret字符串必需您从 GitHub 为您的 OAuth 应用收到的客户端密钥。
code字符串必需您作为步骤 1 的响应收到的代码。
redirect_uri字符串强烈建议授权后用户被发送到的应用程序中的 URL。我们可以使用此 URL 与最初发出code时提供的 URI 进行匹配,以防止针对您的服务的攻击。

默认情况下,响应采用以下形式

access_token=gho_16C7e42F292c6912E7710c838347Ae178B4a&scope=repo%2Cgist&token_type=bearer

如果您在Accept标头中提供格式,您也可以接收不同格式的响应。例如,Accept: application/jsonAccept: application/xml

Accept: application/json
{
  "access_token":"gho_16C7e42F292c6912E7710c838347Ae178B4a",
  "scope":"repo,gist",
  "token_type":"bearer"
}
Accept: application/xml
<OAuth>
  <token_type>bearer</token_type>
  <scope>repo,gist</scope>
  <access_token>gho_16C7e42F292c6912E7710c838347Ae178B4a</access_token>
</OAuth>

3. 使用访问令牌访问 API

访问令牌允许您代表用户向 API 发出请求。

Authorization: Bearer OAUTH-TOKEN
GET https://api.github.com/user

例如,在 curl 中,您可以这样设置 Authorization 标头

curl -H "Authorization: Bearer OAUTH-TOKEN" https://api.github.com/user

每次收到访问令牌时,都应使用该令牌重新验证用户的身份。当您将用户发送到授权您的应用时,用户可以更改其登录的帐户,如果您在每次登录后不验证用户的身份,则可能会混淆用户数据。

设备流程

设备流程允许您为无头应用程序(例如 CLI 工具或Git Credential Manager)授权用户。

在您可以使用设备流程授权和识别用户之前,必须首先在应用设置中启用它。有关在您的应用中启用设备流程的更多信息,请参阅 GitHub 应用的“修改 GitHub 应用注册”和 OAuth 应用的“修改 OAuth 应用”。

设备流程概述

  1. 您的应用请求设备和用户验证码,并获取用户将输入用户验证码的授权 URL。
  2. 应用提示用户在https://github.com/login/device处输入用户验证码。
  3. 应用轮询用户身份验证状态。一旦用户授权了设备,应用将能够使用新的访问令牌进行 API 调用。

步骤 1:应用向 GitHub 请求设备和用户验证码

POST https://github.com/login/device/code

您的应用必须请求用户验证码和验证 URL,应用将在下一步中使用该 URL 提示用户进行身份验证。此请求还会返回设备验证码,应用必须使用该验证码接收访问令牌并检查用户身份验证的状态。

此端点采用以下输入参数。

参数名称类型描述
client_id字符串必需。您从 GitHub 为您的应用收到的客户端 ID。
scope字符串您的应用请求访问权限的作用域的空格分隔列表。有关更多信息,请参阅“OAuth 应用的作用域”。

默认情况下,响应采用以下形式

device_code=3584d83530557fdd1f46af8289938c8ef79f9dc5&expires_in=900&interval=5&user_code=WDJB-MJHT&verification_uri=https%3A%2F%2Fgithub.com%2Flogin%2Fdevice
参数名称类型描述
device_code字符串设备验证码为 40 个字符,用于验证设备。
user_code字符串用户验证码显示在设备上,以便用户可以在浏览器中输入代码。此代码为 8 个字符,中间有一个连字符。
verification_uri字符串用户需要在其中输入user_code的验证 URL:https://github.com/login/device
expires_in整数device_codeuser_code过期之前的秒数。默认为 900 秒或 15 分钟。
interval整数在您可以发出新的访问令牌请求 (POST https://github.com/login/oauth/access_token) 以完成设备授权之前必须经过的最小秒数。例如,如果间隔为 5,则您必须等到 5 秒后才能发出新请求。如果您在 5 秒内发出多个请求,则会达到速率限制并收到slow_down错误。

如果您在Accept标头中提供格式,您也可以接收不同格式的响应。例如,Accept: application/jsonAccept: application/xml

Accept: application/json
{
  "device_code": "3584d83530557fdd1f46af8289938c8ef79f9dc5",
  "user_code": "WDJB-MJHT",
  "verification_uri": "https://github.com/login/device",
  "expires_in": 900,
  "interval": 5
}
Accept: application/xml
<OAuth>
  <device_code>3584d83530557fdd1f46af8289938c8ef79f9dc5</device_code>
  <user_code>WDJB-MJHT</user_code>
  <verification_uri>https://github.com/login/device</verification_uri>
  <expires_in>900</expires_in>
  <interval>5</interval>
</OAuth>

步骤 2:提示用户在浏览器中输入用户代码

您的设备将显示用户验证码,并提示用户在https://github.com/login/device处输入代码。

步骤 3:应用轮询 GitHub 以检查用户是否已授权设备

POST https://github.com/login/oauth/access_token

您的应用将发出设备授权请求,这些请求将轮询POST https://github.com/login/oauth/access_token,直到设备和用户代码过期或用户已使用有效的用户代码成功授权应用。应用必须使用步骤 1 中检索到的最小轮询interval,以避免速率限制错误。有关更多信息,请参阅“设备流程的速率限制”。

用户必须在15分钟(或900秒)内输入有效的代码。15分钟后,您需要使用POST https://github.com/login/device/code请求新的设备授权码。

用户授权后,应用将收到一个访问令牌,该令牌可用于代表用户向API发出请求。

此端点采用以下输入参数。

参数名称类型描述
client_id字符串必需。您从GitHub获取的OAuth应用的客户端ID。
device_code字符串必需。您从POST https://github.com/login/device/code请求中收到的device_code
grant_type字符串必需。授权类型必须为urn:ietf:params:oauth:grant-type:device_code

默认情况下,响应采用以下形式

access_token=gho_16C7e42F292c6912E7710c838347Ae178B4a&token_type=bearer&scope=repo%2Cgist

如果您在Accept标头中提供格式,您也可以接收不同格式的响应。例如,Accept: application/jsonAccept: application/xml

Accept: application/json
{
 "access_token": "gho_16C7e42F292c6912E7710c838347Ae178B4a",
  "token_type": "bearer",
  "scope": "repo,gist"
}
Accept: application/xml
<OAuth>
  <access_token>gho_16C7e42F292c6912E7710c838347Ae178B4a</access_token>
  <token_type>bearer</token_type>
  <scope>gist,repo</scope>
</OAuth>

设备流的速率限制

当用户在浏览器上提交验证码时,每个应用每小时的提交次数限制为50次。

如果您在请求之间所需的最小时间间隔(或interval)内发出多个访问令牌请求(POST https://github.com/login/oauth/access_token),您将达到速率限制并收到slow_down错误响应。slow_down错误响应会将5秒添加到上次interval。更多信息,请参见设备流的错误代码

设备流的错误代码

错误代码描述
authorization_pending当授权请求正在等待并且用户尚未输入用户代码时,会发生此错误。应用应继续轮询POST https://github.com/login/oauth/access_token请求,但不得超过interval,这要求每次请求之间至少间隔一定秒数。
slow_down当您收到slow_down错误时,将向使用POST https://github.com/login/oauth/access_token的请求之间所需的最小interval或时间间隔添加5秒。例如,如果起始间隔要求请求之间至少间隔5秒,并且您收到slow_down错误响应,则现在必须等待至少10秒才能发出新的OAuth访问令牌请求。错误响应包含您必须使用的新的interval
expired_token如果设备代码过期,您将看到token_expired错误。您必须重新请求设备代码。
unsupported_grant_type授权类型必须为urn:ietf:params:oauth:grant-type:device_code,并在轮询OAuth令牌请求POST https://github.com/login/oauth/access_token时作为输入参数包含。
incorrect_client_credentials对于设备流,您必须传递您的应用的客户端ID,您可以在应用设置页面上找到它。设备流不需要client_secret
incorrect_device_code提供的device_code无效。
access_denied当用户在授权过程中点击取消时,您将收到access_denied错误,并且用户将无法再次使用验证码。
device_flow_disabled应用设置中未启用设备流。更多信息,请参见设备流

更多信息,请参见OAuth 2.0 设备授权授予

非Web应用程序流程

非Web身份验证仅适用于有限的情况,例如测试。如有需要,您可以使用基本身份验证使用您的个人访问令牌设置页面创建个人访问令牌。此技术使用户可以随时撤销访问权限。

重定向URL

redirect_uri参数是可选的。如果省略,GitHub 将把用户重定向到OAuth应用设置中配置的回调URL。如果提供,重定向URL的主机(不包括子域)和端口必须与回调URL完全匹配。重定向URL的路径必须引用回调URL的子目录。

CALLBACK: http://example.com/path

GOOD: http://example.com/path
GOOD: http://example.com/path/subdir/other
GOOD: http://oauth.example.com/path
GOOD: http://oauth.example.com/path/subdir/other
BAD:  http://example.com/bar
BAD:  http://example.com/
BAD:  http://example.com:8080/path
BAD:  http://oauth.example.com:8080/path
BAD:  http://example.org

环回重定向URL

可选的redirect_uri参数也可用于环回URL,这对于在台式计算机上运行的原生应用程序非常有用。如果应用程序指定环回URL和端口,则授权应用程序后,用户将被重定向到提供的URL和端口。redirect_uri不需要与应用的回调URL中指定的端口匹配。

对于http://127.0.0.1/path回调URL,如果您的应用程序正在端口1234上监听,则可以使用此redirect_uri

http://127.0.0.1:1234/path

请注意,OAuth RFC 建议不要使用localhost,而是使用环回字面量127.0.0.1或IPv6 ::1

为OAuth应用创建多个令牌

您可以为用户/应用程序/范围组合创建多个令牌,以创建用于特定用例的令牌。

如果您OAuth应用支持一个使用GitHub进行登录并且只需要基本用户信息的工作流程,这将非常有用。另一个工作流程可能需要访问用户的私有存储库。使用多个令牌,您的OAuth应用可以为每个用例执行Web流程,仅请求所需的范围。如果用户仅使用您的应用进行登录,则他们无需向您的OAuth应用授予其私有存储库的访问权限。

每个用户/应用程序/范围组合最多可发出十个令牌,每小时创建的令牌数量限制为十个。如果一个应用程序为同一用户和相同的范围创建了超过十个令牌,则将撤销具有相同用户/应用程序/范围组合的最旧令牌。但是,达到每小时的速率限制不会撤销您最旧的令牌。相反,它将在浏览器中触发重新授权提示,要求用户仔细检查他们向您的应用授予的权限。此提示旨在为应用可能陷入的任何潜在无限循环提供中断,因为应用在一小时内向用户请求十个令牌几乎没有理由。

警告

撤销OAuth应用的所有权限将删除该应用代表用户生成的任何SSH密钥,包括部署密钥

引导用户查看其访问权限

您可以链接到OAuth应用的授权信息,以便用户可以查看和撤销其应用程序授权。

要构建此链接,您需要在注册应用程序时从GitHub收到的OAuth应用的client_id

https://github.com/settings/connections/applications/:client_id

提示

要了解您的OAuth应用可以访问用户的哪些资源,请参见了解用户的资源

故障排除

进一步阅读