Skip to main content

授权 OAuth 应用

你可以允许其他用户授权 OAuth app。

Note

请考虑生成 GitHub App 而不是 OAuth app。

OAuth apps 和 GitHub Apps 使用 OAuth 2.0。

GitHub Apps 可以代表用户执行操作(类似于 OAuth app),也可以自行执行操作,这对不需要用户输入的自动程序很有利。 此外,GitHub Apps 使用细化权限,让用户更好地控制应用可以访问的存储库,并使用生存期较短的令牌。 有关详细信息,请参阅“GitHub 应用和 OAuth 应用之间的差异”和“关于创建 GitHub 应用”。

GitHub 的 OAuth 实现支持标准授权代码授权类型和对无权访问 Web 浏览器的应用的 OAuth 2.0 设备授权

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

要授权你的 OAuth app,请考虑哪个授权流程最适合你的应用。

Web 应用程序流程

Note

如果要生成 GitHub 应用,仍可以使用 OAuth Web 应用程序流,但设置方面有一些重要差别。 有关详细信息,请参阅“代表用户使用 GitHub 应用进行身份验证”。

授权应用程序用户的 web 应用程序流程是:

  1. 用户被重定向,以请求他们的 GitHub 身份
  2. 用户被 GitHub 重定向回您的站点
  3. 您的应用程序使用用户的访问令牌访问 API

1. 请求用户的 GitHub 标识

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

此终结点采用以下输入参数。

查询参数类型必需?说明
client_idstring必须注册时从 GitHub 收到的客户端 ID。
redirect_uristring强烈建议用户获得授权后被发送到的应用程序中的 URL。 请参阅以下有关重定向 URL 的详细信息。
loginstring可选提供用于登录和授权应用程序的特定账户。
scopestring上下文相关范围的空格分隔列表。 如果未提供,则 scope 默认为未授权应用程序的任何范围的用户的空列表。 对于已向应用程序授权作用域的用户,不会显示含作用域列表的 OAuth 授权页面。 相反,通过用户向应用程序授权的作用域集,此流程步骤将自动完成。 例如,如果用户已经执行了两次 Web 流,并且已授权一个具有 user 范围的令牌和另一个具有 repo 范围的令牌,则不提供 scope 的第三个 Web 流将收到具有 userrepo 范围的令牌。
statestring强烈建议不可猜测的随机字符串。 它用于防止跨站请求伪造攻击。
allow_signupstring可选在 OAuth 流程中,是否向经过验证的用户提供注册 GitHub 的选项。 默认为 true。 在策略禁止注册时使用 false
promptstring可选强制帐户选取器在设置为 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_idstring必须从 GitHub 收到的 OAuth app 的客户端 ID。
client_secretstring必须从 GitHub 收到的 OAuth app 的客户端密码。
codestring必须收到的作为对步骤 1 的响应的代码。
redirect_uristring强烈建议用户获得授权后被发送到的应用程序中的 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 中设置“授权”标头:

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

每次收到访问令牌时,都应使用该令牌重新验证用户的标识。 当你向他们发送邮件授权应用时,用户可以更改他们登录的帐户,如果在每次登录后没有验证用户的标识,则可能会出现混合用户数据的风险。

设备流程

设备流允许你授权用户使用无头应用程序,例如 CLI 工具或 Git 凭据管理器

在使用设备流识别和授权用户之前,必须先在应用的设置中启用它。 有关在应用中启用设备流的详细信息,请参阅“修改 GitHub 应用注册”(对于 GitHub Apps)和“修改 OAuth 应用”(对于 OAuth apps)。

设备流程概述

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

第 1 步:应用程序从 GitHub 请求设备和用户验证码

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

您的应用程序必须请求用户验证码和验证 URL,因为应用程序在下一步中提示用户进行身份验证时将使用它们。 此请求还返回设备验证代码,应用程序必须使用它们来接收访问令牌和检查用户身份验证的状态。

终结点采用以下输入参数。

参数名称类型说明
client_idstring必填。 从 GitHub 收到的应用的客户端 ID。
scopestring应用请求访问的范围的列表(以空格分隔)。 有关详细信息,请参阅“OAuth 应用的范围”。

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

device_code=3584d83530557fdd1f46af8289938c8ef79f9dc5&expires_in=900&interval=5&user_code=WDJB-MJHT&verification_uri=https%3A%2F%2Fproxy.goincop1.workers.dev%3A443%2Fhttps%2Fgithub.com%2Flogin%2Fdevice
参数名称类型说明
device_codestring设备验证码为 40 个字符,用于验证设备。
user_codestring用户验证码显示在设备上,以便用户可以在浏览器中输入该代码。 此代码为 8 个字符,中间有连字符。
verification_uristring用户需要在其中输入 user_code 的验证 URL: https://github.com/login/device
expires_inintegerdevice_codeuser_code 过期之前的秒数。 默认值为 900 秒或 15 分钟。
intervalinteger在能够发出新的访问令牌请求 (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_idstring必填。 从 GitHub 收到的 OAuth app 的客户端 ID。
device_codestring**** 必需。 你从 POST https://github.com/login/device/code 请求中收到的 device_code
grant_typestring**** 必需。 授权类型必须是 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 错误响应向上一个 interval 添加 5 秒钟的时间。 有关详细信息,请参阅设备流代码错误

设备流程的错误代码

错误代码说明
authorization_pending授权请求待处理并且用户尚未输入用户代码时,将发生此错误。 应用应在不超出 interval 的情况下继续轮询 POST https://github.com/login/oauth/access_token 请求,这需要每个请求之间的最短秒数。
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轮询 OAuth 令牌请求 POST https://github.com/login/oauth/access_token 时,授权类型必须为 urn:ietf:params:oauth:grant-type:device_code 并且必须作为输入参数包含在内。
incorrect_client_credentials对于设备流程,您必须传递应用程序的客户端 ID,您可以在应用程序设置页面上找到该 ID。 设备流不需要 client_secret
incorrect_device_code提供的 device_code 无效。
access_denied当用户在授权过程中单击取消时,你将收到 access_denied 错误,该用户将无法再次使用验证码。
device_flow_disabled尚未在应用的设置中启用设备流。 有关详细信息,请参阅“设备流”。

有关详细信息,请参阅“OAuth 2.0 设备授权”。

非 Web 应用程序流程

非 web 身份验证适用于测试等有限的情况。 如果需要,可以使用基本身份验证通过 personal access token 设置页创建 personal access token。 此方法支持用户随时撤销访问权限。

重定向 URL

redirect_uri 参数是可选的。 如果忽略该参数,GitHub 会将用户重定向到 OAuth app 设置中配置的回叫 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 apps 创建多个令牌

您可以为用户/应用程序/作用域组合创建多个令牌,以便为特定用例创建令牌。

如果你的 OAuth app 支持一个使用 GitHub 登录且只需基本用户信息的工作流程,此方法将非常有用。 另一个工作流程可能需要访问用户的私有仓库。 你的 OAuth app 可以使用多个令牌为每个用例执行 Web 流程,只需要所需的作用域。 如果用户仅使用你的应用程序登录,则无需向他们的专用存储库授予你的 OAuth app 访问权限。

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

警告:从 OAuth app 撤销所有权限将会删除应用程序代表用户生成的所有 SSH 密钥,包括部署密钥

指示用户审查其访问权限

可以链接至 OAuth app 的授权信息,以便用户审查和撤销其应用程序授权。

若要生成此链接,需要使用在注册应用程序时从 GitHub 收到的 OAuth app 的 client_id

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

Tip

若要详细了解 OAuth app 可以为用户访问的资源,请参阅“为用户发现资源”。

故障排除

延伸阅读